Canal探究( 三 )
canal丢失数据的情况:正常情况下 , 在canal server/client挂掉或切换的情况下不会丢失数据 , 因为zk会持久化server解析binlog及clinet消费数据的位置 , 重启时会重新读取 。 以下情况可能会丢失数据:
- zk保存的元数据被人为修改 , 如server解析binlog及clinet消费数据的位置
- client使用get方法而非getWithoutAck , 如果client消费数据时挂掉 , server会认为这部分数据已经被消费而丢失
- MySQL binlog非正常运维 , 比如binglog迁移、重命名、丢失等
- 切换MySQL源 , 比如原来基于M1实例 , 后来M1因为某种原因失效 , 那么Canal将数据源切换为M2 , 而且M1和M2可能binlog数据存在不一致
- canal处理数据流程为master-parse-sink-store-comsume , 整个流程中都是单线程、串行、阻塞式的 。 如果批量insert、update、delete , 都可能导致大量的binlog产生 , 也会加剧Master与slave之间数据同步的延迟 。 (写入频繁) 。
- 如果client消费的效能较低 , 比如每条event执行耗时很长 。 这会导致数据变更的消息ACK较慢 , 那么对于Canal而言也将阻塞sotre , 没有有足够的空间存储新消息进而堵塞parse解析binlog 。
- Canal本身非常轻量级 , 主要性能开支就是在binlog解析 , 其转发、存储、提供消费者服务等都很简单 。 它本身不负责数据存储 。 原则上 , canal解析效率几乎没有负载 , canal的本身的延迟 , 取决于其与slave之间的网络IO 。
- Canal instance初始化时 , 根据“消费者的Cursor”来确定binlog的起始位置 , 但是Cursor在ZK中的保存是滞后的(间歇性刷新) , 所以Canal instance获得的起始position一定不会大于消费者真实已见的position 。
- Consumer端 , 因为某种原因的rollback , 也可能导致一个batch内的所有消息重发 , 此时可能导致重复消费 。
destination的消费问题一个destination无法被多个client直接并行消费 , 解决方案:
- client收到消息以后转发到kafka或者MQ中 , 后继的其他Consumer只与kafka或者MQ接入
- 一个Canal中使用多个destination , 它们对应相同的MySQL源
对于canal设计的一些思考
- 对于canal的高可用 , 通过zk保证server和client同一时间只能有一个节点工作server能不能根据数据id进行分片读取 , 提高读取数据的性能 , 类似kafka的设计 , 应该是不能的 。 因为parser向master发起dump请求得到的是字节流 , 无法获取原始数据 。 那能不能一个parser对应多个sink再放入store 。 没必要 , 因为canal的性能瓶颈在canal与数据库的网络IO , 解析及sink是很快的 。 客户端能不能多个节点同时工作 , 从一个destination消费数据 。 如果不保证数据成功消费及有序性是可以的 。 如果某一client消费数据失败 , 当前store的设计(环形结构保存数据)无法做到回滚 。 如果一个destination分多个队列由client消费 , 只能保证数据局部有序 , 同时设计复杂 。
- 当前store的数据保存在内存中 , 是否有必要持久化到文件类似于logstash的数据也是保存在内存中 , 官方文档说会支持 , 但没有也可以 , 因为持久化会影响整体性能 , 通过zk存储client的消费位置会保证数据至少被消费一次 。
推荐阅读
- Canalys公布Q3国内手机出货量 小米逆势增长排名第四
- iOS虚拟定位技术探究
- 因为一次redis缓存穿透,全面探究redis能做什么
- 隐匿在语音识别背后的智能音箱之战
- 阿里P8带你深入看源码,探究多线程原理,只靠这份384页笔记
- 创业邦|2020凤凰网科技创新趋势论坛正式召开,探究中国科技力量崛起之路
- 一个神烦取名字的IT人|区块链技术在食品溯源领域的应用探究