MySQL Binlog监听服务延迟问题排查

版权声明:本文为博主原创文章,转载请注明出处和原作者。 https://blog.csdn.net/tracker_w/article/details/78686785

## 问题现象
线上部署了一个binlog监听服务,将自己伪装成从库,通过网络监听主库发来的row based binlog事件来进行一些业务上的处理。此前一直监听的是mysql A集群,一切正常;现在切换成B后,发现监听进度总是会落后,且平均每天落后1小时(当前发生的事件要到下一小时才能监听到)。通过观察日志,发现binlog落后时的现象为日志按固定时间间隔规律打印, 如总是每间200ms打印一次收到事件的日志,且总是在凌晨1点多开始落后。这样就导致服务运行几天后,线上业务端进行的操作,要几小时后才能被监听到,严重影响了正常业务流程。

排查

监听服务使用的是生产者 - 消费者模型,producer、consumer各只有一个线程,中间有一个长度为5000的堵塞缓冲队列。produer负责网络IO接收mysql传来的binlog event, 封装处理后投递到队列中由consumer执行业务处理。

我发现每次落后时,程序就开始变成规律每固定200ms收到一次事件,而这200ms 卡在了生产者线程向任务队列投递任务的操作上 。 这说明consumer消费速度过慢导致队列满,从而卡住了producer。但consumer的业务代码并没有特别耗时的操作,大部分都在内存中完成,最后将处理结果写到文件中。consumer只处理感兴趣的库和表,对于其他无关库表的事件都会直接过虑,不执行业务代码,但 仍然会将当前binlog位置保存到文件中 。 这里唯一的IO就是写文件,而文件输出目录刚好是一个NFS分布式网络文件系统。由此推测,很可能是NFS写性能下降导致consumer消费速度下降,producer堵塞,从而降低了整个监听服务的吞吐,最终导致binlog落后。

验证

将读写频率最高的文件(用于记录当前binlog位置信息)从NFS转移至本地磁盘,服务运行一天,binlog同步正常。由此可确定问题的确是出在NFS上。NFS服务在申请时填写了一个QPS峰值,当时是随便写的没有多想,没想到就给现在埋了个大坑。改是改不了,因此只能在降低写频率或者直接不写NFS的方向上发力。

解决方案

每收到一个事件都会将binlog位置写文件的目的是为了服务在重启后可以接着上次停下来的点继续同步,因此必须将binlog位置持久化,省不了。起初考虑将此信息写入zk, 不过很快否决,因为 zk 其实并发能力比较差,高峰期每秒会有上万个事件,可能会打跨zk。后考虑redis, redis确实能抗住,但redis毕竟是内存缓存,极端情况下可能会丢,否决。最终使用的方案是,监听服务将位置信息缓存到内存,然后5s定时刷新到NFS文件中。即便服务坑贵,最多也就丢5s的binlog, 在业务上可以接受。实际上线部署后问题解决。

猜你喜欢

转载自blog.csdn.net/tracker_w/article/details/78686785
今日推荐