码迷,mamicode.com
首页 > 其他好文 > 详细

全球异地多活架构设计(二): 数据层的支持

时间:2019-11-04 19:20:21      阅读:83      评论:0      收藏:0      [点我收藏+]

标签:架构设计   解决   现在   code   upd   避免   概率   span   理解   

要做到全球异地多活, 一定要在数据层支持多机房写入, 并且对大多数业务场景提供最终一致性的解决方案。原因如下:

 

跨洲的网络延迟在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或扫描下方二维码

技术图片

全球异地多活架构设计(二): 数据层的支持

标签:架构设计   解决   现在   code   upd   避免   概率   span   理解   

原文地址:https://www.cnblogs.com/lemonrel/p/11794069.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!