要做到全球异地多活, 一定要在数据层支持多机房写入, 并且对大多数业务场景提供最终一致性的解决方案。原因如下:
- 跨洲的网络延迟在100ms的数量级,如果只有单点写, 对于用户体验是种灾难
- 对于高频操作来说, 如果做强一致性,那么任然受限于网络延迟, 对于用户体验是种灾难
既然决定要选择最终一致性, 那么随之而来就有两个问题需要解决:
- 跨机房的数据同步
- 多点写入时的数据冲突处理
一 、数据同步
数据的同步有几个核心问题需要考虑:
- 获取数据变更以及重放
- 不丢不重不乱序
- 避免数据回环同步
获取数据变更以及重放
这个问题比较好解决, 可以通过存储提供的增量日志(比如mysql的binlog,redis的AOF)来获取本机房的数据变更。 如果用到的存储没有提供这个功能, 也可以考虑在业务层做类似的事情。 比如写入成功后, 把变更操作发到消息队列。(但是对于数据一致性要求比较高的场景, 要考虑到[变更存储+发消息]这个操作的事务性,很麻烦)。
一般来说,我们用的存储都会提供主从方案,所以思路都是通过fake成主存储的一个slave来获取数据变更。
获取到变更之后,可以写入消息队列再mirror到别的DC(比如Kafka MirrorMaker), 在别的DC重放这些变更。
不丢不重不乱序
这时候引入了新问题, 消息的写入和消费,是否需要exactly