欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

kafka顺序消费遇到的一个问题和心得

时间:2023-04-17

记录一下最近遇到的一个kafka的问题,kafka用的比较少,理解不深出现的问题,特此记录

问题描述

业务要求: kafka上的消息要求顺序消费,且为了保证顺序在生产消息时也是顺序的投放到一个分区中.

一开始写的很简单,既然一个分区还要求顺序消费,那我就单线程消费呗,一个消费者消费一个分区单线程肯定是顺序的,刚开始也确实没有问题,但是运行一段时间后出现了问题.

接入生产环境数据后,kafka数据量突然上升一个量级,大概每天有接近1千万左右的数据,由于我们的消费者里还有一些业务逻辑,所以其实每条数据消费速度并不是很快,这样就导致了千万级的数据消费不过来,出现了消息堆积,经过1个月的消费堆积,kafak上大概堆积了有2百万的数据,极大的影响了业务正常运行.

优化过程

然后就尝试了很多的优化方法,包括从业务/程序上优化,过滤一部分无效数据,但是效果并不明显.仍然有大量数据堆积.

后来经过一段事件的思考,突然有了一个新的想法: 二次投递

思路是这样的:

业务数据要求顺序,但是也可以将业务数据划分为N类,某一类的数据内保持顺序,这样的话我就启一个单线程消费者消费源端数据,在这个消费者内部将业务数据根据类型划分,投递到不同的分区,然后再根据分区数量启动N个消费者,每个消费者消费一个分区的数据,这样就把数据分散到多个消费者,且保证了数据的顺序性.


衍生问题

这样有衍生出了另外一个问题: 消费者太多,线程占用太多,服务器压力大

举例: 我现在有一千万数据,根据业务类型划分后会出现4个topic,每个topic的分区为10

这样我就需要40个消费者去消费分区数据,这样在开发时就需要开发40个消费者

解决办法

后台查阅了kafka的一些资料后,发现可以使用一个消费者来消费多个分区数据,即消费者是可以指定分区的.

@KafkaListener(group="business-group",topicPartitions ={@TopicPartition(topic = "topic1", partitions = { "0", "1" }))}

可以指定partitions即消费分区数,支持多个分区

这样,我就可以针对某些分区,数量不大的情况下可以合并为同一个消费者消费,这样还是多个分区内的数据投递到一个消费者还是可以保证顺序的.

这里其实还有一个小问题: 不指定消费者的分区时,kafka是根据自己的规则来判断消费者的消费分区的,指定之后就被固定,做不到动态的消费了,可能造成某一个消费者压力较大的后果.

这里我又想到,是否可以通过一个程序来判断某个消费者是否空闲,空闲的话可以动态的指定压力较大的分区来消费,这个后续有时间再优化下

总结

kafka分区就是为了提高读写速度,放弃了顺序性,只能在分区内部保证数据的顺序性,所以遇到顺序消费的数据,只能在分区内部消费处理.

但是为了提高消费速度,可以考虑上面这种方式,这种方式的缺点就是会多存储一份数据,并且要求数据从业务上可以划分.

思考: 有时候程序的优化并不是纯技术方面,可能需要结合业务才可以达到快速高效解决问题的目的,作为开发人员可能对业务也要有理解,需要有技术和业务相辅相成的思想.

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。