Multithreading 并发消息处理设计

Multithreading 并发消息处理设计,multithreading,algorithm,design-patterns,concurrency,jms,Multithreading,Algorithm,Design Patterns,Concurrency,Jms,最近,我设计了一个系统,使用Oracle高级队列AQ使用JMS处理健康数据。消息必须包含患者信息,如姓名、健康卡号等。此外,消息可能包含患者免疫记录。我使用的是SpringBoot,通过配置多个消息侦听器(最多30个),我能够并发处理这些消息。因此,我能够获得一个性能。但是,这些消息是按时间顺序处理的,导致数据不一致。例如,消息A表示新的病历,消息B表示使用消息A创建的患者更新。如果随后处理消息A和消息B,则结果与上游系统一致。但是,如果同时处理,结果与现实不同步,则消息B可能在消息A之前得到处

最近,我设计了一个系统,使用Oracle高级队列AQ使用JMS处理健康数据。消息必须包含患者信息,如姓名、健康卡号等。此外,消息可能包含患者免疫记录。我使用的是SpringBoot,通过配置多个消息侦听器(最多30个),我能够并发处理这些消息。因此,我能够获得一个性能。但是,这些消息是按时间顺序处理的,导致数据不一致。例如,消息A表示新的病历,消息B表示使用消息A创建的患者更新。如果随后处理消息A和消息B,则结果与上游系统一致。但是,如果同时处理,结果与现实不同步,则消息B可能在消息A之前得到处理。 显然,如果存在消息A,我将不会开始处理消息B。假设我有方法确定它,每条消息都有事件时间戳和状态。但如何切实实施呢?
如果有人能分享他们的经验,我将不胜感激。实际的技术并不重要,我正在寻找某种设计模式

如果您想坚持使用JMS作为技术,而不能使用消息分组,那么我看到了两种基本的方法来处理这个问题

序列化所有消息处理

通过序列化所有消息处理,您将确保没有任何消息处理不正常。但是,这可能会导致性能显著降低

重试顺序错误的消息


当您发现正在处理一条无序的消息时,您可以简单地回滚该消息的使用并配置重新交付延迟,前提是最终将在延迟时间内处理当前消息之前的消息。大多数JMS代理支持同一消息的多次重新传递,有时甚至会有越来越长的重新传递延迟,并且最终能够在一定次数的传递尝试后将无法传递的消息放入某种死信队列。这里的好处是,您可以继续并发处理消息,同时还可以获得并发所提供的所有性能优势,并且您只需要在顺序实际中断时处理无序消息。不利的一面是,您可能会浪费一些时间多次重新处理某些相同的消息,您还需要建立某种流程来处理最终被视为无法送达的邮件,尽管您可能不得不这样做。

在不牺牲顺序的情况下提高性能的一种方法是将数据分发到多个不重叠的主题上。所以患者A和患者B可以讨论不同的话题,但是患者A的更新只会讨论患者A的话题

怎么做?一种方法是使用患者的姓氏的第一个字母作为主题。因此,Miller患者的所有消息都在主题M上,而John Doe的消息都在主题D上。当然,这个发行版并不理想,对于订阅者“X”来说没有太多工作,但您也可以使用全名模30的哈希代码,例如。或者,如果您有ID,请使用ID的最后两位数字发布和订阅主题00到99


如果您担心丢失消息,请使用JMS持久订阅或设置X个队列来代替。

只是为了结束讨论。我的最终决定是按照@justinbertram的建议,使用delay选项将消息发送回队列。Oracle高级队列允许使用延迟选项对消息进行排队。

@JustinBertram我正在使用Oracle高级队列AQ。我曾考虑过消息分组,但根据Oracle,它必须是一个事务的一部分。在我的情况下,这是不可能的,我无法控制消息的发送方式。我的回答是否解决了您的问题?如果是,请将其标记为正确,以帮助将来有相同问题的其他用户。如果没有,请详细说明原因。谢谢