Kafka 性能调优实战:同等资源配置性能提升 20 几倍的秘诀
笔者最近在折腾数据异构体系,在实现 MySQL 增量数据同步到 MQ(Kafka、RocketMQ),本文的故事就从这里开始。
众所周知,为了提
高写入端的并发性能,通常会采用多线程并发机制,提高写入端的性能,接下来基于 MySQL 增量同步到 Kafka 为例,阐述一下第一版的架构方案。
真实的数据同步架构设计复杂性远比上面复杂,上图旨在阐述 Kafka 的使用特点:
为了提高性能,通常会引入多线程,故组内同事直接采用多线程,通过创建多个线程,每一个线程单独创建一个 KafkaProducer 对象,然后 binlog 解析器后,按照分区键进行负载均衡。
但发现,性能非常低下,为什么呢?该如何处理呢?
当发现性能比较慢,然后又按照 Kafka性能优化指南进行调优,对 linger.ms,batch.size 等参数进行调优,但发现毫无用处,这是为啥呢?
Kafka 的高吞吐率设计的核心要点之一是批处理,即 kafka 在消息发送端引入了一个双端队列,应用程序通过 KafkaProducer 的 send 方法时,会将消息先放入到双端队列,然后 kafka 使用一个异步线程从队列中成批发送消息。
为了确保 sender 线程能一次发送较多数据,kafka 在客户端引入了一个参数 linger.ms,默认为 200ms,即小心进入到缓存区后不会立即被 send 线程发送,而是等待一定时间,这样能提高 send 线程的发送效率,提高吞吐率。
再回到上述到场景,将视角切换到单个线程,在单个线程内,应用方调用 KafkaProducer 后,消息会在缓存区中等待 200ms,但由于是数据同步场景,消息发送使用的是同步发送,这样就会导致不管 send 线程等多久,永远只会有一条消息被发送,每条消息发送还要无缘无故的增加 200ms 的延迟,tps 怎能上去?
第一个优化点:还是基于多线程发送,当多线程共同持有一个 KafkaProducer 对象,这样在同一时间会有更多数据到达 KafkaProducer 的缓存区,Sender 线程就可以实现一次发送多条消息,实现批量发送到效果,从而提升 Kafka 的吞吐率,实现高 TPS,其效果如下图所示:
关键点:对于单个线程,由于要保证消息都顺序性,使用的是同步发送模式。
众所周知,在数据异构的架构体系中,通常需要将分库分表的 mysql 数据库中的数据同步到 es,从而实现跨库 join 等复杂查询功能。
数据同步为了确保数据的最终一致性,通常必须保证顺序。但其维度可以为表级别、数据行级别,通常只需要保证同一行数据的不同事件(新增、更新、删除)等事件必须顺序执行,所以在上述的架构中采用的是同步发送。
有没有可能使用异步发送,但同时满足顺序语义呢?
答案当然是可以的,**其设计思路为:将消息分批处理,该批次内部消息并发执行,各个批次顺序执行。**示意图如下:
评论