otter 带表情包同步踩坑及解决方案
一、事情发生
在年末22点44分突然收到微信告警otter同步异常告警,channel_id为6的同步channel挂起,而且一直没有恢复,一直在告警
微信的otter告警是我们使用python脚本去获取zookeeper中每个channel的状态,每1分钟会检查一次状态,如果发现状态异常就通过微信告警平台告警。
微信告警是一个针对运维异常状态的一个告警服务,目前汇集了所有系统的告警信息,会根据告警的等级对不同用户进行微信推送。
二、原因分析
发生告警后通过跳板机登录otter查看otter状态为挂起,点击解挂或停止重启也会挂起,就这样反复,而且channel同步的位点则没有变化,位点最后更新时间也不会变化;查看日志发现otter同步报错,但报错信息很简单也一直报同样的错误,通过错误日志没办法定位问题原因。
由于是otter双向同步,只有一个pipeline同步有异常(位点没有更新,最后同步时间没更新),所以直接到同步的node节点下看日志,一般otter的同步日志写在自己的pipeline id下/app/otter/logs/11
,通过查看两边的pipeline日志后发现同步写入数据库时报插入错误,
java.sql.SQLException: Incorrect string value: ‘\xF0\x9F\xA4\xAA’ for column ‘nickname’ at row 1
看日志是在nickname这一个字段出现在不确定的字符,通过查看binlog日志发现是一个用户表情包
到此原因基本确定了。
- otter在通过binlog双边同步时,发现有一个用户表情时在写入时序列化为
\xF0\x9F\xA4\xAA
无法插入报错 - otter不断在此点位上重试,每次重试都报错
三、 临时方案
为了解决此报错,在两边追上同步进度,现在需要跳过一个报错的位点,从下一个位点继续开始同步,对此我们已有具体的操作步骤:
- 确定otter当前同步的位点及时间
- 查找binlog临近位点信息,确定此事务下一个位点位置
- 找到下一个位点及时间,更新zookeeper对应的位点信息
- 重启继续同步
以上操作有很多具体的流程,经过以上操作后很快同步完成。
四、整体问题解决
以上步骤只是临时解决方案,为了彻底解决需要从根本上找到问题的原因,在otter的issue里有这个问题,建议是两边数据库和表字段都需要设置为UFT8MB4字符集。
通过查看两边数据库,在插入端的数据库和数据库表都设置的为utf8,但字段是utf8mb4,如果需要修改数据库实例需要重启,在生产环境重启会影响业务,影响特别大。
通过进一步的排查发现在otter同步的时候我们设置数据库的数据源也是UTF8,所以有可能在同步的时候就已经有问题,所以准备是在otter端直接修改字符集,但在修改验证数据源时发现otter提示和数据库字符集不一致。
为了保证通过客户端修改产生问题,通过查看源码发现这个配置没有写在zookeeper中,所在找到数据库表data_media_source
,直接修改字符编码集(properties字段json字段中的encode)。
修改后重启channel,即可生效。