十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

聊聊异构数据同步里最让人头疼的一致性问题,看看KFS是怎么做的

聊聊异构数据同步里最让人头疼的一致性问题,看看KFS是怎么做的 聊聊异构数据同步里最让人头疼的一致性问题看看KFS是怎么做的说到异构数据同步做过这活的兄弟们肯定都知道这事儿真不是搬砖那么简单。你把数据从Oracle或者MySQL搬到Kingbase听起来好像就是个导出导入的过程。但其实呢最让人心里没底的往往不是速度慢而是数据到底一不一致。今天咱们就借着金仓的KFS好好掰扯掰扯这个事儿。看看它在“全周期数据一致性校验”这块到底是怎么做到让人放心的。一、异构数据同步里为什么“数据一致性”这么难搞很多时候我们做数据同步往往仅仅只是盯着进度条看。进度条跑完了就觉得大功告成了。这是一个很危险的错觉。那为什么会这样呢原因在于你看到的进度条往往只是代表“发过去了”不代表“写对了”。1.1 业务不停机的情况下数据一直在变现在企业层级里的系统哪有那么容易给你停机窗口啊。基本都是要求7x24小时在线的。那么问题就来了。你在同步存量数据的时候源端还在不断产生新的增量数据。比如你正同步着一张一千万行的大表。同步到第五百万行的时候源端有人把第十行的数据给改了。你同步完的时候目标端拿到的是旧数据。这就不一致了。这种情况如果你没有一个好的机制去比对和修复上线后业务查出来的数据就是错的。这可是大事故。1.2 存量数据和增量数据的割裂通常来说我们会分两步走。先全量同步存量再启动增量同步抓取日志。但是这两步之间的衔接是一个极易出错的点。如果全量没导完增量日志就开始抓了。中间这段时间的数据变更很容易丢。或者全量导完了增量回放的位点没对准导致有些数据重复回放有些没回放。这种割裂的情况在传统的同步方案里往往需要人工去对账。一张表一张表地去数。这工作量太吓人了。1.3 传统的校验方式太笨重那怎么校验呢以前大家常用的办法就是停机。先把源端停了导出一份count再导出目标端的count。两边一比。或者用一些MD5校验的工具把两张表全扫一遍算哈希值。这确实准。但是太慢了。而且你必须停业务。对于不能停机的系统来说这就行不通了。你需要一种在线的、不中断业务的校验方式。这其实一直是行业里的一个痛点。二、KFS的“低侵入、高性能”底座不拖垮源库是第一步在聊一致性校验之前咱们得先说说KFS的底座。因为如果你连数据都同步不过来或者同步过来慢得要死那谈一致性就没意义了。KFS有一个很关键的特性就是“低侵入、高性能”架构。2.1 采集端的低侵入意味着什么低侵入也就是说它在源端抓数据的时候尽量不去打扰源端数据库的正常干活。它主要是解析数据库的日志比如Oracle的Redo、MySQL的Binlog、Kingbase的WAL。它不在源库里跑那种重查询。这对源端的性能影响就非常小了。毕竟你做同步不能把原来的业务系统给搞挂了。这是底线。2.2 目标端入库的性能瓶颈到底在哪但是呢源端抓得快没用。如果目标端写不进去那整个链路还是会被卡住。这就是个典型的漏斗效应。源端是怎么写的可能是几百个连接在并发写入。但是同步工具到了目标端往往是一个单线程在逐条回放SQL。这能快吗肯定快不了。这里面有几个很要命的瓶颈。一个是网络往返。你发一条SQL等数据库执行完返回结果再发下一条。假设一次网络延迟是1毫秒。那六条SQL就是6毫秒。这时间全浪费在网上了。再一个是小事务太多。源端每秒可能有好几千个小事务每个都commit。这就导致目标端的磁盘IO被频繁的commit操作打满。还有一个是单线程根本用不满多核CPU。现在的服务器都是几十个核的你单线程跑那99%的CPU都在睡大觉。2.3 KFS是怎么把数据“存得快”的为了解决这些瓶颈KFS在目标端搞了一套很细的流水线机制。我画了个图大家可以看看大概的流程。按策略分配按策略分配按策略分配源端日志 Binlog/RedoExtractor 采集变更Filter 过滤转换Partitioner 事件路由通道0 Queue通道1 Queue通道N QueueApplier 线程1 批量写入Applier 线程2 批量写入Applier 线程N 批量写入目标端数据库它具体用了几个招数。第一个是批量提交。它不是逐条发SQL了。而是把很多条SQL攒起来打包成一次网络请求发给数据库。刚才说的六条SQL现在只需要一次网络往返。这就快了很多。第二个是小事务合并。这个挺有意思的。有时候一个事务里对表1、表2、表3、表1、表2、表3这样交替操作。如果按顺序处理每次切表都要重新做一次prepare。但是KFS会在内部做一个归并。它把同表的SQL挑出来放一起。这样表1的操作就连续了只需要prepare一次。这又省下了大量的数据库解析开销。第三个是Statement缓存。相同的SQL模板它只解析一次然后把执行计划缓存起来。后面遇到一样的直接复用。这就大大降低了目标端数据库的CPU消耗。这些底层的性能优化其实是为了给后面的“0停机”和“在线校验”打基础的。因为只有你同步得足够快你才有可能追上源端的变更才敢谈在不中断业务的情况下去做校验。三、重点来了KFS的“全周期数据一致性校验”能力好了前面铺垫了那么多现在进入正题。KFS在一致性这块提出了一个“全周期”的概念。这是啥意思呢3.1 什么是“全周期”存量加增量一起管通常来说大家做校验往往是割裂的。全量导完比一次增量跑一段时间再比一次。KFS的全周期是说它把存量数据的校验和增量数据的校验融在一块儿了。在存量同步进行的过程中它其实就已经开始记录各种校验信息了。等增量同步接管之后它会对新产生的增量数据实时或者准实时地进行一致性比对。它不是等所有事情都干完了才去算总账。而是边干边对账。这就好比你在点钞的时候不是数完一大摞再复点而是边数边核对。这样发现问题就能及时处理。3.2 在线校验业务不中断CPU负载增加3%是怎么做到的这是KFS很牛的一点。它说它的在线数据校验对源端性能影响极小CPU负载增加不到3%。那它是怎么做到的呢其实你想想如果你直接在源端跑一个SELECT COUNT(*)或者算MD5那CPU肯定飙升IO也肯定被占满。这肯定不行。KFS的做法是它不直接去扫业务表。它利用了同步链路本身已有的数据。在数据从源端抽取出来还没发给目标端之前它在内存里顺手就算了一下校验值。或者它在抓取日志解析出变更行的时候就把这行数据的关键字段的哈希值给算出来了。也就是说它是把校验的计算逻辑嵌在了同步的流水线里面。数据反正都要过这一遍顺手算个哈希值并不需要额外去读磁盘。这样对源端数据库的额外开销就仅仅只是那么一点点CPU计算几乎可以忽略不计。这就是为什么它能做到CPU负载增加小于3%。对于存量数据它也不是一股脑全扫。它是分批次、分段地去算。而且会根据源端的当前负载情况动态调整校验的并发度和速度。如果发现源端很忙它就慢点算。如果源端闲着它就快点算。这就保证了在线校验不会去抢业务资源的饭碗。3.3 发现差异后的“全自动数据修复”光能发现问题还不算完。能自己把问题修好那才叫真本事。传统的工具往往仅仅是给你出一份报告。告诉你“表A的第100行不一致”。然后呢然后你自己去查SQL自己去目标端写UPDATE语句修。这在几百张表的情况下人是会崩溃的。KFS在这里做了一个“全自动数据修复”的功能。当它的校验模块发现源端和目标端某条记录不一样的时候。它会自动生成一条修正的SQL。比如源端是UPDATE了但是目标端没同步成功它就会拿着源端最新的这行数据生成一条对应的UPDATE语句或者INSERT语句直接在目标端执行。这个修复是可以做到记录级的。精准定位到某一行然后用正确的数据覆盖掉错误的数据。而且它支持自动和手动两种模式。如果你对这个链路很有信心你可以开启全自动模式。它发现差异就默默修掉写个日志。这就真正实现了无人值守。如果你比较谨慎你可以设置成手动模式。它把差异记录下来你在界面上点一下确认它才去修。这种灵活性对于不同安全等级的项目来说是非常实用的。四、0停机平滑迁移背后的硬核技术支撑前面说的全周期校验和自动修复是建立在“数据能同步过来”这个前提下的。那么KFS是怎么保证0停机平滑迁移的呢这就要回到它那个多通道并行入库的技术上了。4.1 多通道并行入库解决串行天花板刚才提到单线程入库太慢。KFS的做法是开多个通道。也就是启动多个线程每个线程连着一个数据库连接并行往目标端写数据。但是这里有个大坑。多线程写数据顺序怎么保证你不能把UPDATE写到INSERT前面去吧。那数据就全乱了。为了解决这个问题KFS搞了一套非常细致的事件路由引擎。我给大家列一下它里面的几种策略大家就能感受到这玩意儿有多细了。最简单的是按源端的任务ID分。但这会导致同一张表的INSERT和UPDATE跑到不同线程里肯定乱套。接着是按哈希分。把同一个数据源的数据固定发到一个通道。这样同源有序了。但是如果是热点库一个通道堵死了别的通道闲着这叫负载不均。然后是轮询。按事务序号挨个分。这解决了负载不均。但是一个大事务有几十万行把一个通道堵死别的通道处理小事务很快干完了又闲着。再然后是负载均衡策略。实时看哪个通道排队少就发到哪个通道。这又破坏了“同表不能跨通道”的原则。你看每一种策略都在解决前一个策略的问题同时又会引入新的问题。KFS没有搞一个所谓完美的方案而是把这些策略全做出来让用户根据实际情况去选。对于特别大的事务它还搞了个“事务拆分”。比如一个事务改了表1、表2、表3。它就把这个大事务拆成三个子事务。表1的去通道0表2的去通道1。这样大事务就不会独占一个通道了。而且它还有“表亲和性”保证后续的事务里只要是表1的数据就还发到通道0。这就保证了单表内的顺序。更绝的是“行哈希”。如果是一个单表大事务一张表写了100万行。它就根据主键值做哈希把不同主键的行打散到不同通道。这样单表也能并行了。4.2 断点记录与故障恢复不丢数据的底线并行通道多了崩溃恢复就变得很复杂。假设有3个通道通道0处理到了第100个事务通道1处理到了第99个通道2处理到了第97个。这时候进程挂了。重启之后从哪里开始恢复呢如果都从97开始那通道0和通道1已经提交的数据就会重复写入。如果各自从各自的位置开始那事务的完整性怎么保证KFS在这里维护了一个复合位点。它不仅记录每个通道处理到了哪还记录了一个全局的提交计数。恢复的时候它取所有通道位点的最小值作为安全起点。然后从源端把这个位点之后的数据重新拉过来。接着它会做三段区间的判定。对于已经确认提交过的事务它直接跳过不重复写。对于在等待列表里还没提交的事务它重新回放到对应的通道。对于全新的数据它正常处理。这套机制配合上它严格的DDL安全保护DDL操作永远固定在通道0执行不和同表的DML并发就保证了即使在多通道高并发的情况下一旦出现故障数据依然能恢复到一致的状态不丢不重。五、实际案例印证数据无忧不是一句空话说了这么多技术细节咱们还是得落回到实际业务里看看。5.1 某省级政务云的实战情况我之前了解过一个省级政务云的项目。那里面涉及到几十个委办局的几百套系统。要从Oracle和SQL Server同步到金仓。数据量是TB级别的而且每天还有几百GB的增量。这种项目你让DBA去人工对账那是不可能的。每天几百GB的增量你怎么对他们用的就是KFS。在并行同步阶段利用多通道和行哈希把原来需要跑十几个小时的增量回放压缩到了几个小时。追平了源端的变更。接着他们开启了KFS的在线一致性校验。因为是政务数据准确性要求极高。他们在白天业务高峰期开启校验监控显示源端Oracle的CPU负载只增加了不到2%。完全没有影响到前台业务的办理。在试运行的一个月里校验模块陆陆续续抓到了几次数据不一致的情况。有的是因为网络瞬断导致的大事务部分失败有的是因为某个存储过程里特殊的写法导致的解析异常。每次抓到KFS都自动生成了修复语句并且执行了。全程运维人员只是收到了告警短信去后台看了一下日志确认。根本不需要半夜爬起来去查数据改数据。5.2 从手忙脚乱到无人值守的转变你对比一下以前的做法。以前做割接往往是一个周末所有相关人员都在机房待命。全量同步完后要跑脚本比对面。发现不一致手动导出修改再导入。搞到周一天亮都弄不完。现在有了这种全周期校验和自动修复的能力。你其实可以把更多精力放在应用层的兼容性测试上。底层数据的同步和一致性交给工具去闭环处理。这其实才是“数据无忧”这四个字真正的含义。不是说我保证绝对不出错而是说出了错我能自己发现、自己修不需要人去兜底。六、总结几句掏心窝子的话其实做异构数据同步大家手里可能都有几把刷子。能把数据搬过去的工具一大把。但是能把数据搬得快同时还能在搬的过程中边搬边查、查错了还能自己改的这就很少见了。KFS在底层的那些优化什么批量提交、小事务合并、各种路由策略看起来很琐碎。但恰恰是这些琐碎的细节把目标端的写入性能逼到了极限。这才有了在线校验的资本。而它那个全周期数据一致性校验和自动修复才是真正打动企业层级里那些保守的客户的关键点。因为对他们来说慢一点还能忍数据错了那是不能忍的。现在能做到业务不中断、性能不损耗、还能无人值守地保证一致这套组合拳打下来确实解决了一个行业里的大痛点。以后再遇到那种要求苛刻的同步项目心里总算是有底了。
返回列表