问题提出
kafka发生了消息积压,消费者的消费速度远远小于生产者的生产速度。消费者的逻辑大部分是IO密集型操作,单线程顺序消费已经解决了顺序消费的问题,但是它的扩展能力很差。为了提升消费者的处理速度,但又要保证顺序性,我们只能横向扩展分区数,增加消费者。这就意味着需要加机器来增加你的系统处理能力。那意味着离老板开除你不远了。在不能无限制扩充分区的情况下,只能提高单机消费者的消费能力。
要解决的问题
一个消费者分为消息分发线程,再增加多个工作线程,将消息分配给工作线程池处理,处理完成后提交位移,拉取新的消息。
- 每个工作线程池只处理相同分区下的消息
- 如何消息要保证有序性,不能把消息放到线程池中处理就变成并行处理了,没有先后顺序。解决方案是增加N个阻塞队列,虽然消息在broke端已经进行了分区,但是到消费者分发线程里,还有根据key继续分发,分发到不同的阻塞队列中,这样是避免具有先后顺序的消息分到不同的阻塞队列中,并行处理造成顺序丢失。
- 手动提交位移。分发线程poll拉取到的消息不能用自动提交,要等工作线程处理完成了才能提交,如果程序崩溃或者重启会造成消息丢失。a.是等待所有拉取的消息处理完毕再进行位移提交b还是每隔固定时间提交当前已经处理的最小位移.peek方法和offset不是非要同步的,你从哪里拉取数据和已经提交的数据不相干 ,offset主要是为了宕机重启从什么位置给你推送消息。等到拉取的所有消息处理完提交位移
- 一个消费者可能对应多个分区
- 不考虑消费顺序,将任务放入每个分区独有的线程池中执行,全部消费完成提交位移,继续拉取消息。
- 考虑消费顺序,同一分区上的消息是乱序消费的,只能等这一批poll过来的数据都消费完了再拉取新的一批消息消费
代码实现
kafka-assistant项目柏炎 每个分区再次hash分配到指定阻塞队列,工作队列从阻塞队列拉取任务。等全部消费完成提交位移
真正的 Kafka 多线程消费 每个分区对应一个阻塞队列消费,拉取的消息数量受到阻塞队列大小限制。完成情况检查等到阻塞队列的数据处理完再提交
胡夕
胡夕 每个分区交给线程池处理,等这个分区全部消费完成提交位移