28|顺序消息和幂等:如何实现顺序消息和数据幂等?
许文强
你好,我是文强。
这节课我们来讲一下消息队列中的顺序消息和幂等机制实现。
在消息队列中,消息是否能有序是一个常常被问到的问题。因为在我们的业务中,比如在有序事件处理、数据实时增量同步等情况下,就需要消息队列支持顺序消息的机制。接下来我们就来看看消息队列中顺序消息的定义和实现。
顺序消息的定义和实现
在消息队列中,消息的顺序性一般指的是时间的顺序性,排序的依据就是时间的先后。从功能来看,即生产端发送出来的消息的顺序和消费端接收到消息的顺序是一样的。牢记这个定义,对于我们后面理解顺序消息的实现很重要。
消息队列的存储结构特性
复杂的数据结构会影响数据写入和读取的性能。
消息队列功能需求较为简单,不太需要复杂的数据结构来支持检索等操作。
所以,理想情况下顺序消息的实现是:生产端按顺序发送消息,Broker 端按接收到的顺序存储消息,消费端按照 Broker 端存储的顺序消费消息。那技术上的实现真的有这么简单吗?我们继续分析。
如上图所示,实现顺序消息的核心就是:Broker 接收到的消息的顺序要和生产端发出来的顺序是一致的。那在实际的场景中,会发生什么事呢?
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
消息队列中的顺序消息和幂等机制是保证消息有序性和避免重复消息写入的关键技术。实现顺序消息需要考虑多个因素,如多个生产者、异步发送和多个分区等,而主流消息队列采取了不同的机制来实现有序存储。另外,幂等机制包括生产幂等和消费幂等,其中消费端更关注的是确保消息只被消费一次。为了实现这些技术,需要考虑生产端的消息发送机制、消息路由和存储结构等方面,并解决数据倾斜和水平扩容的问题。文章介绍了两种实现幂等的方案,一种是通过消息唯一ID实现幂等,另一种是通过生产者ID和自增序号实现幂等。此外,还介绍了Kafka的幂等机制的实现方式。综上所述,了解消息队列中的顺序消息和幂等机制对于保证消息的有序性和避免重复消息写入具有重要意义。 在实现顺序消息时,需要考虑单一生产者、同步发送和单一分区三个因素,以满足消息的有序性。而幂等机制的实现方案主要分为“通过消息唯一ID实现幂等”和“通过生产者ID和自增序号实现幂等”两种思路,两种方案的实现思路差别不大,各有优劣势。Kafka的幂等机制基于第二种思路实现,通过缓存少量的数据来实现大部分情况下的幂等,以保证高性能的同时支持部分的幂等。 总的来说,消息队列中的顺序消息和幂等机制是保证消息有序性和避免重复消息写入的重要技术,而了解这些技术对于保证消息的有序性具有重要意义。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解消息队列 47 讲》,新⼈⾸单¥59
《深入拆解消息队列 47 讲》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(6)
- 最新
- 精选
- shanRocketMQ顺序消息实现 消息一般分为全局有序和局部有序。 全局有序:为Topic设置一个消息队列,使用一个生产者单线程发送数据,消费者端也使用单线程进行消费,从而保证消息的全局有序,但是这种方式效率低,一般不使用。 局部有序:比如想保证某个订单的相关消息有序,那么就使用订单ID当做路由ID,在发送消息的时候,将这个订单相关的消息,通过路由ID将所有消息发送到同一个消息队列中,保证消息在某个消息队列中是有序的,消费者端通过MessageListenerOrderly处理有序消息,这就是RocketMQ的局部有序。 对于生产者保证消息局部有序,只需要将消息发送到同一个消息队列中即可。 对于消费者来说,是通过加锁来保证消息顺序消费的,一共有三把锁: 1. 在集群模式下一个消息队列同一时刻只能被同一个消费组下的某一个消费者进行,为了避免负载均衡等原因引起的变动,消费者会向Broker发送请求对消息队列MessageQueue进行加锁。 2. 消费拉取到消息之后,对拉取的消息进行处理的时候,由于可以开启多线程进行处理,所以处理前会对MessageQueue加锁,锁住要处理的消息队列,主要是处理多线程之间的竞争,保证消息的顺序性。 3. 在真正消费消息之前,还会再加一把消费锁,主要是为了避免在消费消息时,由于负载均衡等原因,MessageQueue对应的ProcessQueue被删除。 最近刚好写了一篇总结:https://www.cnblogs.com/shanml/p/17706095.html2023-09-16归属地:河南1
- smilekakaKafka 和 Puslar 的生产端支持按 Key Hash 的生产分区分配策略。 请问kafka 多个producer ,key 相同,会被发送到同一个partition吗?2024-02-26归属地:江苏
- shan生产者消息发送幂等方案 1. 通过消息唯一ID实现幂等 在发送消息的时候,比如使用snowflake雪花算法为每条消息生成一个唯一的消息ID,并且需要保证同一个消息ID发送到同一个分区中,Broker端根据消息ID判断之前是否接收过。 Broker需要保留接收过的所有消息ID集合,需要占用大量空间,可以从以下几个方面进行优化: (1)Broker以Topic维度保存消息ID,不需要保存集群的所有消息ID; (2)消息ID集合只保留未过期的消息,依赖于消息过期机制的设计; (3)通过布隆过滤器来判断; 2. 通过生产者ID和自增序号实现幂等 为每个生产者赋予一个唯一ID,生产者启动时生成一个从0开始的自增序号seqnum表示发出去的消息编号,通过生产者ID+seqnum二元组来唯一确定一条消息。 思路与第一种方案类似,只是把标识从消息ID改为了生产者ID + seqnum。 不过方案2有一个小技巧,它可以不保存生产者所有发送成功的seqnum集合,因为这个是自增的,只保留最新收到的seqnum,如果收到的消息的seqnum是下一条,就正常保存数据,否则就放进队列中先等待,等待下一条消息收到后,再来判断是否保存该数据。 目前主流的消息队列只有Kafka支持幂等发送,RocketMQ、RabbitMQ、Pulsar都不支持。 Kafka幂等发送的思路采用的方案2,它通过Producer ID、Topic、PartitionNum、seqnum四元组来唯一标识一条消息,不过为了高性能,并不能保证完全的幂等。2023-09-16归属地:河南
- LWD单个生产者单个分区也不一定保证发送有序。因为链接可能多个,举个例子,发送消息1到这个链接通道,然后连接超时实际已经到服务端了,此时重新创建连接在发送一个,这时候服务端可能先消费后一个的。。。。2023-09-14归属地:广东2
- zhuxiaoxiao顺序消息消费是怎么保证顺序的2023-09-12归属地:浙江1
- Geek_5d0074RocketMQ怎么保证幂等呢?2023-08-24归属地:江西
收起评论