Kafka+SpringBoot多线程消费与分区消费踩过的坑

  • Post author:
  • Post category:其他




创建Topic的时候,可以置顶分区数和副本数,在kafka/config/sever.properties文件修改num.partitions = ? 即可定义你的默认分区数~


在SpringBoot集成中,我们只需要配置:@KafkaListener(topics = “test_topic” ,groupId = “test”,concurrency = “3”) 就可以实现监听消费。


https://blog.csdn.net/whiteBearClimb/article/details/109532690



我刚开始学也理所当然后面的:concurrency = “3” 配置开启多线程消费可以提高消费能力。


于是在一个项目中,发现消费端能力很弱。访问记录达到1W+一秒,能够正确统计到的只有5500+,为了排查定位到的这个问题,我就在监听消费后面加上了concurrency = “3”; 信心满满提交上线,结果还是出这个问题!


继续研究同时请教大佬~~~

终于发现,由于业务需求,对消息有序性有强烈要求,所以Topic只做了单分区,一个分区,没办法做多线程消费。多不多线程都没办法提高消费能力~

在这里插入图片描述



除非改成:

在这里插入图片描述



改成两个分区的情况,但是发送数据又没办法确保顺序性了,例如 消息1到了分区A,消息2就会到分区B,消息3又到分区A,这样读取的时候,可以同时读同时消费,但是没办法保证是1到2再到3…分区的核心作用,就是提高了读写速度,放弃了顺序性~



最后怎么解决呢?



其实到现在还没解决,只不过优化了,根据上面的分析,我们讨论得到的结论是有序性不能变的逻辑,考虑过开异步消费,在跑复杂业务代码的service都是@Async的。这样担忧的就是数据量暴增的时候轻松吃爆内存和CPU。


其次,我们处理的业务逻辑代码也进行了大规模的优化,没用的代码都删掉 ,尽量优化,涉及到连接的,IO的,都尽量避免或者做成异步。涉及到要查询Mysql的数据做if比较的,提前一点放入缓存中。大循环等也做了优化,一点点打毫秒时间戳看哪里耗时多,哪里就抠一点,哪里就做多一点优化。硬是把消费能力提高了。


再深入一点的层次,我想起以前有人使用针对集合类的操作,抛弃了封装好的add,set,put方法。使用连续空间的List,通过指定偏移量和unsafe类来直接用指针操作内存空间,对性能也有很大提升。例如:偏移量是static final long offSet = 10,一片连续空间,从180开始,那么add就直接放Object A放到 180+10 = 190的位置,也就是190~200都是存放Object A,set操作就是更新,例如Object B 要替换掉Object A,那么就190~200放入B去覆盖掉A。这样写法很变态,我也只是看unsafe类的时候简单了解有这么个骚操作,而且List底层确实也是这么玩的,但是本菜鸡还没达到能写好那种代码的层次。



但是,分区也并不是越多越好,不是说不需要考虑顺序性消费的场景,分区越多!=读写能力肯定越强

(1)分区多,消费能力强,占用内存更多,Kafka进程容易奔溃。

(2)分区维护的成本高,那么多分区,不管是分区读还是分区写,都是需要一套逻辑去维护数据的分发和读取的规则(例如根据Key,随机等等)。

(3)分区多,要维护的偏移量更多,重启时候可能造成更大量的脏数据重复消费数据等等。



有位大佬对分区数进行过测试,可以仔细看下:

kafka如何选择分区数及kafka性能测试



版权声明:本文为whiteBearClimb原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。