消息处理系统如何保证相关消息的的顺序?

系统从MQ中读取消息。由于系统有多台vm,所以读到消息到处理的顺序和MQ中的顺序不一定是一致的(即后读到的消息可能先被处理 存表了)。

现在希望的是具有相同的id的几条消息要严格按照发送来的顺序来处理。

我能想到的方案就是单机单线程读取消息然后读取id再分发。相同的Id分发到相同的vm即可。但是这样相当于只能有一个线程在做这个读取 解析 分发的工作,性能上并不好。

有没有别的解决方案? 博客,论文,开源项目代码都可以。

阅读 2.5k
2 个回答

这个场景需要考虑的东西很多,简单考虑了一下想到了下面的情况。

首先说正常情况:
既然几条消息是相同id的,说明这几条消息是一个客户端发出的,那么只要根据id来路由消息到特定分区即可,如果是用kafka,按序发送消息时,使用同一个key,这样相同的key都会落到相同分区里,消费该分区的消费者能按序拿到消息;

考虑异常情况:
1)消息发送了多次,或者相同消息消费了多次。这种情况要求消息实现幂等性,或者使用最新版kafka的恰好一次语义解决;
2)增加消费者的时候,新消费者会从别的消费者那里获得一些分区,如果恰好获得分区之前,消费者已经拿了一两条了,新消费者接管分区后拿到后面一两条,那这几条消息的顺序也无法保证。这种情况可以在消费者刚启动时,如果发现拿到的第一批消息是依赖于其他消息的话,就放到另外一个队列里不断查库里有没有,发现有了之后才继续消费;
3)正常跑着的时候一个消费者在拿到了一两条消息写入后挂了,另外的消费者拿到了它的分区,需要从旧一点的地方消费,重复消费的问题前面说了,这里要说的是消费者自己要定期保存处理完了的分区的偏移量,不能由着消费者自动上报偏移量;
4)给topic新增分区,会导致相同id的数据会被路由到不同的分区上(因为分区数变了,相同的哈希值对分区数取模的值不同了),这种情况消费者在触发了新增分区事件时,跟第二种情况处理方式类似;
5)如果相同id的数据要求统一实现事务,那么就要考虑使用缓存来等待消息全部到达了。

以上只是一些思考,仅供参考

第一眼就想到了kafka

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进