kafka数据实时同步引发的边界问题

数据库从kafka集群中实时增量同步数据, 由于kafka的默认保留7天日志的问题, 引发的边界情况下, 可能丢数据的思考

场景描述

如下图所示, 这是1条数据同步的链路, 其中数据同步服务通过2种方式将数据同步到最终的Tchouse集群中, 用以实现和生产环境的数据保持一致

  1. 存量同步: 使用copy命令从都匀环境中将数据表copy下来, 然后直接insert到Tchouse集群
  2. 增量同步: 从t-7开始读取kafka中的数据DML情况, 然后在Tchouse集群中回放, 从而实现数据的增量同步

微信截图_20240417153118.png

场景的异常情况

由于存量同步采用的是copy insert的方式, 因此整个任务是一次性的, 但是增量同步的过程中, 由于是不断消费kafka中的数据, 因此如果业务侧修改了源表的DDL, 但是目标端Tchouse集群中没有修改, 就会导致报错, 从而增量同步停止, 就必须得人工介入, 解决完任务后, 继续从停止消费的offset开始消费, 而kafka的数据是保留7天, 超过7天就会出现数据丢失的情况

  1. 阶段1-正常

    正常情况下, Tchouse集群中有1-9天的数据, 而增量任务此时正在同步第10天的数据, 而kafka集群中有6-12点的数据

    微信截图_20240417222547.png

  2. 阶段2-异常

    当生产环境的表结构变化, 而没有同步到目标端Tchouse集群时, 就会导致增量任务报错, 从而停止, 此时Tchouse集群中有1-9天的数据, 而增量任务在同步第10天的数据时候, 任务停止了, 需要人工接入进行处理

    微信截图_20240417222850.png

  3. 阶段3-边界问题-经过6天的处理

    经过人工介入后, 故障处理完成, 可以重新开启增量任务, 此时Tchouse集群中的数据为1-9天, 而kafka集群因为只能存储7天的数据, 因此此时只有12-18号的数据信息, 而10-11号的数信息被删除了, 开启增量任务后, 增量任务会从之前停止的时候, 开始继续消费, 也就是第10天, 但是第10天的offset在kafka集群中不存在, 因此kafka集群会根据auto-offset-reset参数调整客户端的offset

    微信截图_20240417223104.png

  4. 阶段4-kafka的offset调整

    kafka的auto-offset-reset有3个值

    • none: 客户端提交不存在的offset, 则会抛出异常
    • earliest: 客户端提交不存在的offset, 则会将客户端指向最早的offset, 即图中的12
    • latest: 默认值, 客户端提交不存在的offset, 则会将客户端执行最新的offset, 即图中的18

    微信截图_20240417223435.png

思考

  1. 不论kafka的auto-offset-reset是earliest还是latest, 都会导致边界情况下, Tchouse集群中丢失一部分数据, 区别就是丢失的多与少而已
  2. 增量任务向Tchouse集群中提交的数据其实是sql语句, 如果后续提交的sql没有对丢失的数据引用, 那么增量任务就不会报错, 那就会导致数据错误, 这比数据库故障还可怕

解决方法

  1. 修改kafka集群的auto-offset-reset为none, 这样, 最起码在丢失数据的时候, 会抛出异常, 可以让人知道, 从而进行新的存量同步和增量同步, 该方案可行性最高
  2. 调整kafka集群的日志默认保留时间到更长, 需要业务侧配合, 可行性较差
作者

好方

发布于

2024-04-17

更新于

2024-04-17

许可协议