记一次canal delay 调优过程

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次canal delay 调优过程相关的知识,希望对你有一定的参考价值。

参考技术A 一、现象

每天夜里12点准时出现延迟告警,查看canal的监控指标,delay指标延迟在5-10分钟,blocking指标中的sink、dump趋于100%,同时canal服务的cpu及memeory很稳定40%左右。

二、分析

被告警吵的实在受不了了,于是下定决心解决这个问题。首先花了点时间研究了一下canal源码,整个canal的解析流程大致分成4步。
binlog dump -- parse -- sink -- kafka(rocketmq)

目前从指标分析,dump及sink都阻塞了,所以判断出是发送kafka能力没跟上,(出问题的canal是kafka模式启动的)。

三、调优的过程
找到可能的原因之后,就开始仔细地看了一下canal的kafka发送逻辑。在这个过程中,看到了kafka的几个参数,canal的默认值如下

1、kafka.acks = all,这里的ack有3个选项,0、1、all 。all是要等topic的某个分区的所有副本都同步完数据后才会给客户端响应,1只要topic的leader分区接收到数据就会给客户端响应,0是只要数据发出去了会立即返回,不会等待分区是否接收到数据。因此,首先我把这个值改成了1,为什么选择改成1,是因为1在kafka集群稳定的情况下是能够保证binlog的顺序性的。

结果:改完之后,发现效果不明显,依然有延迟(卒)

2、kafka.batch.size, 这个值是控制kafka批量消息的大小的,默认是16384 (16K),这里要更具实际的binlog event对象的值合理修改,这个值的修改我也是观察了好久数据才定位到问题的。我们的event对象大小是45K,所以默认的16K压根就没起到批量发送的作用,没解析一个event对象就会发送,导致吞吐量上不去,于是我改成了 921600 (900K),注意这个值不能超过broker端的最大发送字节(message.max.bytes)

结果:改完之后,发现效果不明显,依然有延迟(卒)

3、kafka.linger.ms,批量发送消息的最大等待时长,这里我改成了100,需要自己判断

结果:改完之后,效果依然不明显,延迟依旧(卒)

到这里就有点抓狂了,因为只能在夜里验证,一等就是一天,修改这些值已经搞了快一周了,老板一直催要结果。害,只能接着观察数据,接着干。

4、canal.mq.canalBatchSize,最后终于找到了这个参数,这个参数不是kafka相关的,这个是从环形队列中批量处理的event数量,本来我以为这个是指的event数量,结果看完源码才发现,canal的内存队列是通过内存大小限制的,默认这个值是50,其实不是拿50个event对象,而是拿50K的数量,如果event很大,每次就只取很少的量,我的event 45K,所以每次都只取一个对象,更本没法提高吞吐量。根据高峰期的写入峰值,峰值大概3M/s,于是我把这个canal.mq.canalBatchSize设置成了4500,也就是(4500K)。

当晚就怀着一颗激动地心,眼睛一眨不眨地盯着canal监控。下面是监控截图。3307是优化了的,其他几个没有优化。

3307的blocking明显降低

3307的delay明显降低

完美,竣工,睡觉!

以上是关于记一次canal delay 调优过程的主要内容,如果未能解决你的问题,请参考以下文章

记一次调优过程—Spark读取OBS文件入ES

记一次 Laravel 应用性能调优经历

记一次Grpc接口压力测试&性能调优

记一次Ajax请求MVC调优

sql调优--记一次统计信息未及时更新导致查询超级慢

记一次基于CBO的Oracle SQL调优