我有一个独立的Java进程,它从JMS持久主题中读取消息并将它们提交给线程池进行处理。我出于明显的并发原因这样做,但是维护这些消息的处理顺序,我仍然将它们提交给单个线程池。现在这里是我对JVM崩溃的担忧..
- 非交易的 我不是在阅读和处理Transactional上下文中的每条消息,我避免这会减慢我的进程。所以,我在线程池的阻塞队列中累积消息。但是如果JVM崩溃,而等待处理的线程池中有10条消息,我将丢失该数据。
- 事务
我相信如果我在事务中阅读并处理每条消息,如果出现问题,该消息将在备份时重新传递给该进程。
对于在低延迟系统中工作的许多人来说,这是一个常见问题,想知道有经验的人如何处理这个问题?感谢。
答案 0 :(得分:1)
彼得的AFAIK是正确的。解决此问题的一种方法是,如果模式适用于您,则使用某种划分来创建不同的队列以将消息分组到其中。也就是说,此要求经常被分解为“一个帐户的所有邮件必须按顺序处理”。因此,如果你有类似的东西,你可以创建:
然后您的出版商必须确定:
执行此操作的易于维护的模式是使用您的某个业务字段(例如,帐号)并在其上计算 mod(x),其中 x 是您希望共享工作负载的订户数量。希望您的业务密钥是数字的,并且会给您一个不错的分配,但是您总是可以使用其他一些确定性算法通过反转键和/或散列它们的非数字值来生成此数字。
顺便说一句,你的大纲对它有更多的点对点/ JMS队列感觉,而不是Pub-Sub / JMS主题。您确定要使用主题吗?
如果绝对不能丢失数据,那么您应该使用事务性消息。如果使用事务性消息,则无法委派给线程池。 JMS消息的事务上下文(即会话)绑定到接收消息的线程,因此,除非您启用一些“有趣的业务”将此上下文转移到另一个线程.....
我甚至不确定如何完成那句话。
====更新====
现在我考虑一下,如果您可以从并行处理消息中受益,您可以在一个事务中检索批量消息,并将它们全部委托给ExecutorService.invokeAll调用,等待完成和在交易全部完成时提交交易。如果invokeAll超时,或者其中一个任务抛出异常,那么您将不得不回滚事务或采取某种补偿操作。