全球异地多活架构设计: 数据层的支持
Posted lemonrel
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了全球异地多活架构设计: 数据层的支持相关的知识,希望对你有一定的参考价值。
要做到全球异地多活, 一定要在数据层支持多机房写入, 并且对大多数业务场景提供最终一致性的解决方案。原因如下:
跨洲的网络延迟在100ms的数量级,如果只有单点写, 对于用户体验是种灾难
对于高频操作来说, 如果做强一致性,那么任然受限于网络延迟, 对于用户体验是种灾难
既然决定要选择最终一致性, 那么随之而来就有两个问题需要解决:
跨机房的数据同步
多点写入时的数据冲突处理
一 、数据同步
数据的同步有几个核心问题需要考虑:
1.获取数据变更以及重放
2.不丢不重不乱序
3.避免数据回环同步
获取数据变更以及重放
这个问题比较好解决, 可以通过存储提供的增量日志(比如mysql的binlog,redis的AOF)来获取本机房的数据变更。 如果用到的存储没有提供这个功能, 也可以考虑在业务层做类似的事情。 比如写入成功后, 把变更操作发到消息队列。(但是对于数据一致性要求比较高的场景, 要考虑到[变更存储+发消息]这个操作的事务性,很麻烦)。
一般来说,我们用的存储都会提供主从方案,所以思路都是通过fake成主存储的一个slave来获取数据变更。
获取到变更之后,可以写入消息队列再mirror到别的DC(比如Kafka MirrorMaker), 在别的DC重放这些变更。
不丢不重不乱序
这时候引入了新问题, 消息的写入和消费,是否需要exactly once和消息的有序?
这个需要具体问题具体分析,比如mysql的binlog会带上数据before和after的镜像,因此我们可以接受消息的重复,只需要保证at least once即可; 而对redis而言, set操作可以接受重复, 但是incr等就不能接受。
但是一般来说, 消息的有序都是需要的。我们无法容忍[set a=v1, set a=v2]的序列被处理成[set a=v2, set a=v1]。 这个问题相对比较简单,假设我们用kafka做消息队列, 那么只要用key做partitioner即可做到这一点。
避免数据回环同步
按我们目前所讨论的方案, 获取变更日志之后再重放, 那么一条变更就会在多个机房之间来回同步, 也就是产生了回环问题。
那么如何解决回环问题呢? 其实思路很简单, 就是提供一个机制,让我们在解析重放日志时, 可以判断这个变更是否来自本机房。
以mysql为例, 我们可以利用mysql的事务机制, 在事务的开头和结尾插入同步标志, 在解析时,发现有这个同步标志, 就过滤掉, 不同到别的机房。 落实到具体实现的话, 则是在同步的数据库中创建辅助表, 每次从对端机房同步过来的数据, 都在事务的开头和结尾对辅助表进行相关标志的update操作, 这样就可以在binlog中做区分了。
二、冲突处理
既然我们允许多个数据中心对一条数据进行写入, 那么必然会产生这么一种情况: 在数据中心A对数据X进行变更,V从v0->v1 , 当我们把这个变更同步到数据中心B时, 我们期望update X from v0 to v1, 结果发现在数据中心B,X的值已经是v1’了, 这时候, 就产生了数据冲突。 为了多机房数据的一致性,我们需要处理这种冲突。
LWW策略
比较经典的策略是Last Write Wins, 具体的说, 就是为数据的变更加上时间戳, 在同步到别的机房时,如果发现有冲突, 则比较时间戳, 选取时间戳大的那个版本。
这种策略需要注意的问题是,本地机器的时间是不准确的, 各个机器生成的时间戳的大小可能和真实世界中的变更顺序不一致。
Google Spanner利用原子钟和GPS提供了TrueTime API(可以理解为一个全局时钟), 全球各个数据中心的spanserver产生的时间戳都是基于同一参考系,是单调递增的。(不过也不是完全准确,它保证误差在一个范围之内 )
逻辑主DC
有了LWW就够了吗? 当然不是。 即使概率很低, 仍然可能发生两个数据的变更时间戳完全一致的情况。 因此我们需要在多个DC中指定一个逻辑主DC, 发生时间戳完全一致的情况时, 用逻辑主DC的数据覆盖别的DC。
冲突报告订阅
对于一些敏感数据的变更(比如facebook需要下线一些恐怖主义的帖子),当发生数据冲突时,则不能简单的通过时间戳来决定选择哪个数据版本。 否则,可能会发生被审核人员下线的帖子, 又被重新放出的情况。
这时候,我们需要提供数据冲突报告, 比如在发生数据冲突时,把冲突情况发送到消息队列, 下游根据具体的业务逻辑来处理这种冲突, 决定选用哪个版本的数据。
https://mp.weixin.qq.com/s/vkvYJnKfQyuUeD_BDQy_1g
获取更多学习资料,可以加群:473984645或扫描下方二维码
以上是关于全球异地多活架构设计: 数据层的支持的主要内容,如果未能解决你的问题,请参考以下文章