并发消息处理设计争议

时间:2019-05-10 17:16:15

标签: multithreading algorithm design-patterns concurrency jms

最近,我设计了一个使用JMS处理健康数据的系统。该消息必须包含患者信息,例如姓名,健康卡号等。此外,该消息还可能包含患者免疫记录。我正在使用Spring Boot,通过配置多个消息侦听器(最多30个),我能够同时处理这些消息。这样我就能获得表现。但是,这些消息未按时间顺序进行处理,从而导致数据不一致。例如,消息A代表新的患者记录,消息B代表对使用消息A创建的患者的更新。如果随后进行处理(消息A,然后消息B),则结果与上游系统一致。但是,如果同时处理,结果将与现实不同步(消息B可能在消息A之前得到处理)。 显然,如果有消息A,我将不会开始处理消息B。假设我有确定消息的手段(每条消息都有事件时间戳和状态)。但是如何实际实施呢? 如果有人分享他们的经验,我将不胜感激。实际的技术无所谓,我正在寻找某种设计模式

3 个答案:

答案 0 :(得分:1)

如果您想坚持使用JMS作为技术,并且不能使用消息分组,那么我会看到两种基本的处理方法。

序列化所有消息处理

通过序列化所有消息处理,您将确保不对任何消息进行乱序处理。但是,这可能会导致性能显着降低。

重试乱序消息

当您发现正在乱序处理一条消息时,您可以简单地回滚该消息的消耗并配置重新交付延迟,前提是最终假设当前消息“超前”于在延迟时间内处理。大多数JMS代理有时甚至在重新交付延迟越来越长的情况下,都支持同一条消息的多次重新交付,并且最终还具有在一定数量的交付尝试之后将无法交付的消息放入某种“死信”队列中的能力。这样做的好处是,您可以继续并发处理消息(具有并发性所带来的所有性能优势),并且只需要在订单实际中断时处理乱序消息即可。不利的一面是,您可能会浪费一些时间多次重复处理某些相同的消息,并且您将需要建立某种过程来处理最终被认为无法传递的消息(尽管您可能仍然必须这样做)。

答案 1 :(得分:0)

在不牺牲顺序的情况下获得性能的一种方法是将数据分布在多个非重叠主题中。因此,患者A和患者B可以涉及不同的主题,但是对患者A的更新将仅涉及患者A的主题。

如何?一种开始的方法是使用患者的姓氏的首字母作为主题。因此,所有耐心的Miller消息都在主题M上,而John Doe的话题在D上。例如30。或者,如果您有ID,请使用ID的后两位数字发布和订阅主题00到99。

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

答案 2 :(得分:0)

只需结束讨论即可。我的最终决定是@Justin Bertram所建议的,只需使用延迟选项将消息发送回队列即可。 Oracle Advanced Queuing允许使用延迟选项对消息进行排队。