异地多活的设计思路

一. 什么是异地多活

异地多活是系统高可用的一种解决方案,它通过在多个不同机房建立多个数据中心,并且使这多个数据中心都可以同时在线提供服务来避免当出现机房断电、光纤被挖断等场景出现服务不可用的场景,实现服务高可用,同时这多个数据中心之间需要进行数据相互同步来保证数据的最终一致性。

二. 哪些业务需要异地多活,哪些可以做到异地多活

通过异地多活实现高可用并不是在所有场景下都可以做到的,通常需要结合业务重要程度,以及业务是否存在全局逻辑,以及异地多活场景中解决全局逻辑的成本来考虑是否需要做异地多活,同时需要考虑业务是否需要保证数据强一致性,由CAP理论可知,CA是不能同时实现的。

如针对用户中心的场景,注册和登录是两大核心业务,其中对于注册,需要保证唯一性,不能出现用户可以同时注册多个账号的场景;对于登录需要保证不会出现不能登录的场景;

针对以上两个业务,注册需要保证用户只能注册一个账号,故存在全局约束,即需要保证数据在各个数据中心实时一致性,不能用户在一个数据中心注册之后,这个数据中心在还没同步数据到其他数据中心之前挂了,出现用户在另外一个数据中心又注册一次的场景,所以这种场景如果需要实现异地多活,则需要使用分布式全局唯一ID来实现(如保证一个电话号码只能对应一个,同时需要记录是否使用过,此处还会涉及注册与这个关系的维护的分布式事务问题;或者使用超时时间,该ID生成一段时间之内不能重复申请,但是这段时间内如果刚开始发起申请的机房挂了,则用户不能马上在另外一个机房继续注册),同时又会涉及到这些基础服务的可用性问题,所以是不适合做异地多活的,并且在实际场景中这些业务也是能够容忍短暂不可用场景的。

而登录是用户中心最重要的业务场景,如果用户登录不了了,特别是重度用户,则是非常严重的事故,所以登录是需要做异地多活的。同时每个数据中心都有用户的账号和密码信息,故可以做到异地多活。

所以适合做异地多活的业务主要是针对没有全局约束的场景,如只读业务或者无状态服务,典型的如API网关,是非常适合和容易做异地多活的,而像银行实时转账这种场景是不能做异地多活的,如用户在机房A取款了1万块钱,机房A挂了没有同步数据给机房B,此时用户又可以马上去机房B取款1万块钱(即此时用户在ATM前的取款请求发送给机房B),从而导致资损问题,这种是典型的需要保证全局数据实时一致性的场景。由CAP理论可知,C和A是不能同时达到的,故需要牺牲一定的可用性,即机房A挂了之后,用户就不能再执行取款操作了。

三. 怎么做异地多活

异地多活的实现难点主要是如何缩短不同数据中心之间的数据同步的网络延迟时间,使不同数据中心的数据尽快达到一致性。由于网络传输固有的时间延迟(延迟一般使用RTT来衡量,RTT是指从发送端发送数据开始到发送端接收到接收端响应的ACK的这段时间的长度,其中主要包括链路的传输时间,系统端的处理时间以及路由器的排队和缓存时间的叠加),以及可能会出现的网络抖动,所以我们只能尽量缩短数据同步的时间。

设计要点

所以主要的解决方法以下几种:

  1. 传输速度加快:尽量减少异地多活机房的距离,同时搭建高速网络;
  2. 传输数据减少:尽量减少数据同步,只传输必须的数据;
  3. 保证最终一致性,不保证实时一致性,同时需要增加兜底机制,如数据延迟情况下,二次读取,即当前机房没有数据,去其他机房再查下一次。

数据同步方式

对于数据同步方式,一般包括以下几种:

  1. 数据同步本身
    (1)存储系统本身的同步机制,如MySQL的binlog,Redis的主从同步等;
    (2)借助消息中间件来进行数据同步;
  2. 数据同步延迟或非重要数据不同步,补偿机制
    (1)二次读取:数据同步延迟,根据路由规则到产生该数据的机房读取;
    (2)回源读取:非重要、不需要同步的数据,根据路由规则去产生该数据的机房读取;
    (3)重新生成数据:如登录的一个机房挂了,到另外一个机房时,用户重新登录,生成session数据数据。

四. 总结

最后一句:没有100%完美的架构,如CAP所阐述的,不能同时达到服务100%可用,又要达到数据100%的实时一致性。同时技术架构是为业务服务的,如果技术架构无法解决业务需要达到的场景,则需要从业务上转变思路,改善业务流程。

参考
https://blog.csdn.net/yah99_wolf/article/details/52083089

你可能感兴趣的:(分布式架构)