跨国数据同步系统设计与实现
源代码/数据集已上传到 Github - posts
最近完成一个俄罗斯与中国同时在线使用的集生产物流销售出库于一体的(供应链)系统。从这个系统的设计之初到完成,经历了有半年有余。本篇记录一下这个系统实现的核心架构思路。
现状
- 2019年一共做了两个俄罗斯的项目。因为第一个项目的原因,对于俄罗斯运营商提供的服务器的跨国网络质量实在是无法恭维。有从各个渠道了解到阿里云是莫斯科是有节点的,但是并不对外开放销售。因此,想通过阿里云架设专线的这个想法基本就可以不考虑了。
- 需求方要求,中国这边操作,俄罗斯那边也能快速获取到变更后的数据。
- 需求方还要求,数据要安全,保密,防止丢失。
- 需求方甚至还要求,到哪都要快速打开。
问题考虑
- 减少延迟
中国大陆到俄罗斯的延迟大概在5000ms之间,网络波动巨大,带宽非常小。在俄罗斯购买的无带宽限制的服务器在国内拉取资源,只能达到20kb/s。测试了阿里云香港节点到俄罗斯nic.ru的莫斯科节点的延迟,大概是在200ms左右,带宽能达到100M左右。而香港阿里云到杭州阿里云公网的延迟基本上就在30ms以内。因此需要实现一个双向链路莫斯科
->香港
->杭州
,杭州
->香港
->莫斯科
来减小延时 - 数据同步:
- Binlog同步:在数据同步方面,首先想到的是Binlog同步,但是一番调研和实践之后,发现在两个节点之间互相同步数据,是需要实现一个cluster的,而跨区域的数据节点延迟过于高。别说是在两个国家之间了,就算是同城,延迟几ms的集群都会造成极大的性能损耗。这个数据同步,最起码在做到在操作的国家节点上不能出现脏读和幻读的情况。
- TiDB现成的优化方案:单节点写入,多节点读取。这个方案,在我们的项目中,可以保证用户写入的数据不会有操作同一件物料。但是考虑到跨国的数据写入以及写入后,无法保证用户在何时可以看到数据被写入了。一旦网络波动过大,导致当前节点无法获取到此次数据写入,用户势必会发起第二次请求,重新添加。所以暂时不在考虑中。TiDB的相关链接:流量和延迟减半!挑战 TiDB 跨数据中心难题
- 基于SQL的同步:基于SQL的同步可以让每一个数据节点独立运行。数据节点内的所有插入与更新的SQL的执行,都会产生一条push推送,给数据同步节点。数据同步节点产生目标节点的可执行参数,push到目标节点上。延迟时间大概为200ms+200 μs +30ms。
选中方案介绍
基于客户高可用和操作速度快的需求,最终选中的方案是SQL同步
。而该系统SQL同步的完美实现得益于两点:
- 分布式ID:自研的分布式id,单机每秒可以产生2万有序不重复id
- 数据校验:在一个节点校验到数据超卖的情况下,会上报同步中心,同步中心对历史SQL进行审计,进行首次超卖数据修正。再分发到各个机器。
分布式ID
此次选用的分布式id生成规则为%d%02d%02d%02d%04d%08d
。
段位 | %d | %02d | %02d | %02d | %04d | %08d |
---|---|---|---|---|---|---|
备注 | 年份后2位 | 月份 | 日期 | 当前秒 | 机器id | 8位秒级自增id,最高可支持8个9的正整数数。 |
在这里,同步中心还负责作为注册中心使用,当一个业务节点启用,业务节点就会向服务中心注册,注册中心会返回当前机器的临时编号。并且业务节点需要与注册中心保持长连接,以便实时获取到最新的业务节点数量。注册中心会与业务机保持心跳,避免数据没有被业务机同步,数据就过期。
数据校验
同步数据变更记录异步写入到mq后,由消费者发送到同步中心。
- 当数据到达同步中心后,同步中心会基于SQL的更新时间进行重新排序,然后生成每个注册同步节点的对应的SQL。在时间颗粒内,保证数据基于时间有序。
- 当数据同步到其他节点时,会先进行数据校验,保证库存不会出现超卖。出现超卖,上报同步中心,同步最近N个时间颗粒的数据,进行SQL重放。
效果
第一次开发的系统(A)
本次开发完毕的系统(B)
接口响应对比
- A系统访问者在国内,开启HK的科学上网,接口响应时间在1s以上,丢包率50%以上,国内基本无法正常使用。
- B系统,业务部署在莫斯科与杭州两个数据中心。根据所在的地区,选用对应的系统,接口响应时间均在200ms以内,杭州节点一般在50ms左右。
数据同步时间对比
- A系统无数据同步系统支持,中国访问的延迟基本无法接受。
- B系统的数据同步时间基本在500ms以内。基本上实现了跨国数据同步。
数据安全性
- A系统单节点存在,数据可靠性依赖于服务器提供商
- B系统的数据在莫斯科存在一份,香港存在一份日志记录(可通过数据回放恢复数据),杭州存在一份。一旦出现数据节点毁灭性丢失数据,可以从其他两个节点进行数据恢复,数据丢失量可以控制在一到二个时间同步颗粒。
系统独立性
- A系统单节点存在,不存在数据同步依赖
- B系统虽然需要进行数据同步,但是因为执行SQL同步方案,系统的独立运行性能不会限制于数据库同步。
注意点
- 所有的机器都需要基于0时区进行时间校验,保证SQL的ID基于时间有序。
- 在设计分布式ID生成时,需要注意机器码的编号大小不能影响到数据的大小排序,只作为一个识别编号。
- 数据校验的严格程度取决于同步中心对于同步频率的控制,是一个动态的值。尽量不要用一个固定值去处理,固定值需要取较大,影响同步校准性能。
- 分布式id采用的是数字类型,数据库的自增id需要及时清除。
edit this page last updated at 2022-12-08