-
Kafka只能保证分区内消息顺序有序,无法保证全局有序
- 生产者:通过分区的leader副本负责数据顺序写入,来保证消息顺序性
- 消费者:同一个分区内的消息只能被一个group里的一个消费者消费,保证分区内消费有序
-
为什么做不到全局有序:
- 因为消息会发送到不一样的分区,分区之间发送的顺序是无法保证的
-
如何做到并发且全局有序?
-
解题思路
- 并发可以在发送端并发也可以在消费端并发,并发可以通过多线程发送或消费
- 全局有序需要做到只有一个分区或者数据按顺序发送到多个分区并且消费时按原顺序消费
-
【整体思路】想办法让需要保证顺序的数据发送到同一个分区中,并增加生产者/消费者的并发度
-
【方案1】topic设置一个分区,发送端和消费端开启多线程生产和消费
-
【优点】实现简单
-
【弊端】有热点瓶颈问题,服务端压力大
-
-
【方案2】topic设置多个分区,自定义发送端的分区策略,数据发送到同一个分区中,消费端开启多线程消费
- 【优点】扩展多个分区分摊了非同类数据写入同个分区的压力
- 【弊端】相同业务的数据在同一个分区依然有热点瓶颈的问题
-
【方案3】topic设置多个分区,自定义发送端的分区策略,数据发送不同分区,消费时按发送分区的顺序消费,发送和消费端都启动多线程来提高并发度
- 【步骤】
- 自义分区器,使得消息按分区号大小顺序依次发送相同数量大小的数据
- 发送端和消费端启动多个消费线程进行生产和消费
- 线程之间按分区号大小顺序消费数据
- 【弊端】消费性能极大下降,无法真正并发
- 【步骤】
-
关于方案中提到的消费者开启多线程,这样能保证顺序消费吗?
- 假如有三个线程A、B、C三个线程,三条消息1、2、3号
【多线程分发】
1消息入给A线程
2消息给B线程
3消息给C
【取数据】
A线程拿到1的消息
B线程拿到2的消息
C线程拿到3的消息
【比较】
三个线程都必须全部拿到数据才行进行下一步,拿到数据后比较数据的id,必须满足MA<MB<MC
【入库】
按线程顺序入库
M1入库
M2入库
M3入库 - 线程间可以通过join、CounDownLatch、Executors.SingleThreadExecutor等方式实现线程串行执行
- 实际来说,实现分区间并发且有序是不可能的,分区内有序可以做到,但是分区间并发执行必然和分区内串行执行相悖,最多实现多分区发送,消费顺序按照指定分区顺序去消费,消费端开启多线程只能说多线程串行执行不能并发执行,这样看全局并发有序的实现就有点鸡肋了。
- 假如有三个线程A、B、C三个线程,三条消息1、2、3号
-
-
-
Kafka关于顺序性的应用
- 用kafka采集用户访问 轨迹,重写分区器把用户id作为分区键,这样每个用户访问的埋点记录就能按顺序到一个分区,然后有序消费【网友提供】