• 异地多活架构


    异地多活架构

    异地指地理位置上的不同,多活指不同地理位置上的系统都能够提供业务服务。

    判断标准:

    1. 正常情况下,用户无论访问哪一个地点的业务系统,都能够得到正确的业务服务。
    2. 某地异常时,用户访问其他地方正常的业务系统,能够得到正确的业务服务。

    异地多活的代价:

    1. 系统复杂度会有质的变化。
    2. 成本大大增加。

    架构模式

    1. 同城异区

    部署在同一个城市不同区的机房,用专用网络连接。

    同城异区两个机房距离一般就是几十千米,网络传输速度几乎和同一个机房相同,降低了系统复杂度、成本。

    这个模式无法解决极端的灾难情况,例如某个城市的地震、水灾,此方式是用来解决一些常规故障的,例如机房的火灾、停电、空调故障。

    2. 跨城异地

    部署在不同城市的多个机房,距离要远一些,例如北京和广州。

    此模式就是用来处理极端灾难情况的,例如城市的地震、相邻城市的大停电。

    跨城异地主要问题就是网络传输延迟,例如北京到广州,正常情况下的RTT(Round-Trip Time 往返时延)是50毫秒,当遇到网络波动等情况,会升到500毫秒甚至1秒,而且会有丢包问题。

    物理距离必然导致数据不一致,这就得从“数据”特性来解决,如果是强一致性要求的数据(如存款余额),就无法做异地多活。

    举例,存款余额支持跨城异地多活,部署在北京和广州,当光缆被挖断后,会发生:

    • 用户A余额有10000,北京和广州是一致的。
    • A在广州机房给B转5000,广州余额为5000,由于网络不通,北京此时的余额为10000。
    • A在北京发现余额还是10000,给C转10000,由于网络不通,广州的余额为5000。
    • A在广州又可以给D转5000。

    这就出事儿了,所以这类数据不会做跨城异地多活,只能用同城异区架构,因为同城的网络环境要好很多,可以搭建多条互联通道,成本也不会太高。

    跨城异地模式适用于对数据一致性要求不高的场景,例如:

    1. 用户登录,数据不一致时重新登录即可。
    2. 新闻网站,一天内新闻数据变化较少。
    3. 微博网站,即使丢失一点微博或评论数据也影响不大。

    3. 跨国异地

    部署在不同国家的多个机房。

    此模式的延时就更长了,正常情况也得几秒,无法满足正常的业务访问。

    所以,跨国异地多活适用于:

    • 为不同地区用户提供服务

    例如,亚马逊美国是为美国用户服务的,亚马逊中国的账号是无法登录美国亚马逊的。

    • 只读类业务

    例如谷歌的搜索,不管用户在哪个国家搜索,得到的结果基本相同,对用户来说,跨国异地的几秒延迟,对搜索结果没什么影响。

    跨城异地多活设计技巧

    1. 保证核心业务的异地多活

    思维误区:要保证所有业务都能异地多活。

    假设用户子系统,负责注册、登录、用户信息这3个业务,由于有海量用户,所以对用户进行分区,分配到不同数据中心,正常情况下某个用户属于某个主分区,并在其他分区也有备份,通过hash计算得出属于哪个中心。

    如果想要保证注册业务多活,可能会有问题,例如,A中心注册了用户,数据还未同步到B中心时A宕了,为了支持多活,需要可以让用户到B中心重新注册,但一个手机号只能注册一个账号,A恢复后就有冲突了。

    如果要保证用户信息业务多活,也会有问题,例如,A、B两个中心在异常情况下都修改了用户信息,如何处理冲突?

    可以发现,注册、登录、用户信息这3个业务都支持多活的话,是非常难的,有的问题甚至是无解的。解决的方法就是:优先实现核心业务的异地多活。

    这个示例中,“登录”才是核心业务,例如系统的日活是1000万,每天的注册可能是几万,修改用户信息的可能还不到1万,但登录是1000万,很明显要保证登录的异地多活。

    2. 保证核心数据最终一致性

    思维误区:要保证所有数据实时同步。

    由于物理上的限制,所有数据都实时同步,是一个无法达到的目标。

    必须要尽量减少数据同步,只同步核心业务相关的数据。

    例如上面的例子,登录产生的token或session信息,数据量很大,实际上不需要同步到其他中心,即使丢失了重新登录就可以了,会影响用户体验,但是可以接受的。

    3. 采用多种手段同步数据

    思维误区:只使用存储系统的同步功能。

    存储系统本身就有强大的同步功能,例如 mysql redis 都可以很好的实现同步,但某些场景下是无法满足需要的,所以要使用多种手段配合,例如:

    • 消息队列

    创建账号后,将账号数据通过消息队列同步到其他业务中心。

    • 二次读取

    例如用户在A中心注册了,然后访问了B中心,此时B还没有拿到账号数据,为了解决这个问题,B中心在读取本地数据失败时,可以根据路由规则,再去A中心访问一次。

    • 回源读取

    例如session数据没有同步,用户在A中心登录,B中心可以拿着session id到A中心请求session数据。

    4. 只保证绝大部分用户的异地多活

    思维误区:要保证业务 100% 可用。

    物理规律决定了异地多活无法保证100%的业务可用。

    以转账业务为例,在北京和上海两个中心实现了实时转账的异地多活,在异常情况下会出现问题,例如用户有一万存款,在北京给人转了一万,又到上海给人转了一万。

    所以,无法做到实时转账的异地多活,需要通过特殊业务受到实现。

    例如,除了“实时转账”外,还提供“转账申请”业务,用户在上海提交了转账请求,并不立即转账,而是后台异步处理,如果发现北京中心不可用,就等待重试,北京恢复后,如果发现余额不足就转账失败。

    这个方式牺牲了一些用户体验,本来一次完成的操作变为了2次,一次提交转账申请,另一次是确认转账结果。

    对于用户体验,可以采取一些补偿措施,例如:

    • 公告

    例如由于xxx原因导致您的不便,技术哥哥正在紧急处理等等。

    • 事后补偿

    例如送代金券、小礼品等。

    • 补充体验

    例如上面的转账例子,可以在转账结果出来后给用户发个短信,减少用户不时的登录查看。

    小结

  • 相关阅读:
    WeX5那些坑
    项目总结-微信公众平台Html5
    项目总结-APP中的HTML5
    夜幕团队成员的工资究竟几 K ?
    Docker竟然还能这么玩?商业级4G代理搭建实战!
    今天,大佬云集的夜幕团队正式成立了!
    InnoDB物理行中null值的存储的推断与验证
    探究InnoDB数据页内部行的存储方式
    DAO模式
    JDBC
  • 原文地址:https://www.cnblogs.com/zhaochenguang/p/11042751.html
Copyright © 2020-2023  润新知