1. 同城双活是什么
同城双活是一种容灾架构的设计模式,主要用于提高系统的可用性和容错性。它通常涉及在同一个城市内建立两个数据中心(机房),这两个数据中心同时对外提供服务,实现了高可用性和冗余。
关键特点和优势包括:
双活部署: 两个数据中心都处于活跃状态,同时处理用户请求。这样,当一个数据中心发生故障或维护时,另一个数据中心可以继续提供服务,确保业务的连续性。
故障隔离: 如果一个数据中心遇到故障,可以将流量切换到另一个正常工作的数据中心,减少服务中断时间。
负载均衡: 双活架构通常会利用 DNS 进行分流,让流量按照一定比例分布到两个数据中心,提高整体性能和吞吐量。
降低延迟: 由于两个数据中心都位于同一个城市,网络延迟相对较低,有助于提供更快的服务响应时间。
灾难恢复: 在同城双活的架构下,即使发生了灾难性事件,比如自然灾害,仍然有一个可用的数据中心,可以更迅速地进行灾难恢复。
需要注意的是,同城双活虽然提高了系统的可用性,但仍然存在无法解决的一些单点故障和问题,例如城市级别的停电或其他灾难性事件。在一些对服务连续性要求极高的场景中,可能需要考虑更复杂的容灾架构,如异地多活。
2. 什么样的业务需要同城双活
任何对高可用有要求的业务都可以在容灾架构上选择同城双活,同城双活是异地多活的基础。
3. 双活的部署范围
3.1 全量服务双活 or 部分服务双活
通常在同城双活架构中不是所有业务服务都必须进行双活部署,而是根据业务的特性和需求来进行选择,因为这涉及到成本和复杂性的权衡。有些业务服务可能并不是那么关键,或者其可用性要求并不高,在这种情况下,单活部署足够满足需求,同时减少了系统的复杂性和成本。
大多数公司会选择对一些关键业务中需要高可用性的服务,进行双活部署。而对非关键服务采取单活部署的方式,以平衡系统的可用性和成本。这样,即使一个数据中心发生故障不会导致关键业务不可用。
3.2 哪一部分双活?
1.挑选要双活的业务
首先需要确定哪一个业务双活,在一个互联网公司通常有好多个业务,例如阿里的淘宝、阿里云,字节的头条、抖音,滴滴的网约车,两轮车等等。建立双活首先确定好业务,然后找到业务中最核心的链路去建设双活(确定哪个业务搞双活通常和公司的战略息息相关)
2.确定业务的核心链路
在业务领域,核心链路可能表示业务流程中最关键、最重要的步骤或环节。这些环节是直接影响业务成功的关键步骤,比如滴滴网约车业务中核心链路有乘客发单,司机接单,完单等等
对核心业务的核心链路建设双活,保证在单机房故障时核心链路在另一个机房可以继续运转,保证核心链路不受影响既是保证了业务的成交量不受影响,那么整体的损失就相对较小。
在微服务盛行的时代,通常一条核心链路一定会包含多个服务,这其中会涉及到网关,业务服务,中台服务,中间件、存储等等
3.3 核心链路的服务如何梳理
通常一条核心链路中就包含了多个服务,那么具体包含哪些服务(业务 &存储等),这些服务又该如何梳理呢?通常的做法:首先需要人工梳理标记,最起码先标记处某一个链路的入口,例如乘客发单的入口是/create/order,然后结合全链路追踪能力观察从发单入口进来的流量( 生产流量,压测流量,测试流量)都经过哪些服务从而梳理出发单链路所涉及到的服务。
不过在一个大公司内,由于各种历史原因(懂的都懂)全链路追踪很有可能覆盖不全,那么就需要再结合日志以及监控等信息来弥补全链路追踪断链的情况,从而不断的完善与标记这条核心链路中所涉及到的服务,整个核心链路标记与维护的过程,大多数公司都是从最开始的人工到后期慢慢形成产品,自动化进行标记。
3.4 核心链路的问题
经过上面的梳理核心链路逐渐成型,但是问题也接踵而来。核心链路上的服务可能会越来越多,都要在双活架构中等量部署到新机房嘛?
答案:所谓的核心服务也并不一定要全量部署到新机房做双活,因为通过人工,全链路,日志,监控等手段标记的核心服务往往是大而全的,这里面标记出来的服务可能有很多,但是其中也有可能是弱依赖服务,弱依赖服务在同城双活部署场景下并不是必须的。
- 强依赖服务:当一个服务是强依赖,意味着当这个服务出现故障不可用时,整个链路将会收到影响,甚至是整个系统的稳定性和可用性都会受到影响。
- 弱依赖服务:当一个服务是弱依赖,意味着当这个服务出现故障不可用时,系统仍然可以部分或完全运行。弱依赖的设计有助于系统的弹性和容错性,因为系统的一部分可以在其他部分不可用的情况下继续运行。
如果是在小公司可能不用考虑这件事,但在具有一定规模的公司内,核心链路上的服务也许也会很多。如果全量部署成本依然会很高,特别是在提倡降本增效的近几年,双活的成本也是需要控制的。所以如果要做到成本可控,那么就需要找到核心链路中的强依赖服务部署在新机房做双活。
3.5 找到核心链路的最小集(强依赖)
如何识别核心链路中的强弱依赖?最简单的就是研发/运维人员手动筛选,但是随着系统变得复杂以及系统频繁的变更,弱依赖服务也有可能变成强依赖服务,人工筛选成本太高而且准确性也难以得到保证。
如果你了解过混沌工程,也许会知道可以通过混沌工程主动模拟服务/接口故障,从而来梳理核心链路中服务的强弱依赖关系。梳理强弱依赖的好处 除了在双活加固场景下找到需要双活的最小链路集合,还可以针对强弱依赖做很多稳定性建设的事情,例如针对强依赖服务要建设限流能力,针对弱依赖服务要建设降级能力等等。这里涉及到的细节特别多,包括流量的来源,混沌工程平台的注入能力,核心链路的数据,可观测的能力,稳态的定义等等,在本文就不展开讲了,后面会单独写一篇文章介绍。
3.6 小结
在同城双活中,不是所有业务都需要双活,而是根据业务的关键性和可用性需求有选择地进行部署。核心链路的确定和梳理是双活实施的核心,找到核心链路中强依赖服务进行双活部署是成本最小,最理想化的双活部署范围。
4. 同城双活的其他关键因素
管控服务高可用
各种运维组件的管控层可用性往往会遭到忽视,但管控平台的高可用特别特别重要的。有很多真实发生的故障往往是因为管控层高可用能力建设不到位,导致出现故障后不能快速恢复。这里的细节特别多,举几个例子:
- 假设是自动化切流,切流的平台在机房 A 单活或着对机房 A 的其他管控/存储有强依赖,那么当机房 A 故障时也无法完成切流动作,即使业务层和存储层的双活做的再好也没有任何用。
- 假设故障时顺利切流(无论是自动/手动),当机房 B 承接了全部流量后,那监控、预案,限流,扩容等平台也不能在机房 A 单活或者对机房 A 的其他管控/存储有强依赖,因为当全部流量都切到机房 B 时,很有可能出现容量不足的情况,那么此时需要扩容/限流/降级等操作,如果这些操作依赖的管控平台不好用,可能会导致机房 B 也出现问题。
由于管控平台大多数是由不同的团队进行研发,每一个管控平台的架构可能都不同,管控平台保证高可用的方案也都不一样,不过通常有两种:双活或冷备,最终的目标只需要保证在故障时管控平台在另一个机房可用即可。建设的思路一般都是梳理强弱依赖,对强依赖改造为弱依赖,若改造不了,则需要对强依赖服务在单机房内完成闭环调用,不能跨机房调用。
存储服务高可用
在同城双活的场景下,两个机房间通过同城专线进行数据传输,延时相对较低。在这个背景下不同的存储服务有不同的方案,这里面挑两个最常见的组件简单介绍下,例如:
- mysql
通常是主从模式部署,机房 A 部署主库,机房 B 部署从库,两个机房间存储会进行数据同步。这种场景下机房 B 的业务服务需要做改造将写请求路由到机房 1 的主库,将读请求路由到本机房的从库。(改造的方案可以利用中间件进行读写分离,例如 shardingsphere,一般大厂也都有自研的存储代理组件负责读写分离)
- redis
业界通常的做法有主从架构、双写架构、双向同步架构
- 主从架构:和 mysql 主从模式相同,机房 A 部署主库,机房 B 部署从库,使用原生主从复制保证数据一致性(类似于 codis 的设计思路)
- 双写架构:双机房都部署 redis 主库和从库,业务流量在单机房完成读写请求闭环,由 proxy 完成对端机房异步写,不过这种方案有可能由于网络问题导致双机房 redis 数据不一致
- 双向同步架构:双机房都部署 redis 主库和从库,业务流量单机房完成读写请求闭环,proxy 不需要进行异步写入对端机房,在 redis server 层进行双机房互相同步来保证数据一致性,需要解决数据冲突,要单独开发、成本较高(双向同步架构可以做为异地多活的基础能力)
5. 如何验证同城双活是否可用
当整体的同城双活工作都完成后,需要验证甚至是定期验证同城双活的能力是否可用,避免真出故障时才发现工作做的不够完善,也有可能因为架构的不断演进导致同城双活能力退化。那这里还是可以借助混沌工程思想,通过故障注入来对同城双活的能力进行演练验收。当模拟了单机房故障后,可以演练管控平台是否能正常进行切流,扩容,限流,降级等一系列操作,观察业务核心指标是否可以在双活机房迅速恢复,从而判断同城双活是否符合预期。
演练验证通常有两种做法:
- 断专线:如果同城双活能力做的足够好,足够有信心,可以选择直接针对两个机房间的专线进行网络熔断(例如交换机上 down 端口),这种方式简单、粗暴、有效、可以较好的模拟单个机房故障。
- 精细化故障注入:通常在一个机房内部署的服务不仅仅只有做了双活的业务,如果还有一些业务服务没有做双活,那么上面直接断专线演练肯定会影响这种单活的业务服务,所以需要按需去做精细化演练,例如对所有已经完成双活的业务服务注入网络故障,让其失联(无法访问其他服务/机房,也无法被其他服务访问,来模拟双活业务发生机房故障)
需要考虑如果用生产流量演练,可能会造成一定的损失,这里要看接入层的分流能力,接入层可以提前将大部分流量切换到单个机房,然后留一小部分流量在低峰期进行演练验证,降低损失。压测流量的话需要考虑压测流量的覆盖度以及仿真度,如果不够全面和真实那么对演练和验收的效果也都会打折扣。
6. 总结
同城双活作为一种容灾架构,通过在同一城市建立两个数据中心,以确保在一个数据中心发生故障时,系统能够快速切换到另一个数据中心,从而提高系统的可用性。在部署需要双活的服务时,首先要仔细评估业务的关键性和可用性需求,梳理业务的核心链路是双活的关键抓手,通过将核心链路中的强依赖服务作为重点部署对象,实现最小集的同城双活部署,降低双活成本。除了业务服务双活以外,管控和存储的高可用能力也是故障切换时的关键因素。
为了验证同城双活的可用性,可以利用混沌工程模拟单一数据中心的故障,进行演练关键操作,如切流、扩容、限流等,以确保系统能够在故障发生时迅速而可靠地恢复。这种方法有助于发现潜在的问题并提前制定有效的故障应对方案,确保业务连续性和稳定性。
作者介绍
张斌斌(Github 账号:binbin0325,公众号:柠檬汁 Code)Sentinel-Golang Committer 、ChaosBlade Committer 、 Nacos PMC 、Apache Dubbo-Go Committer。目前主要关注于混沌工程、中间件以及云原生方向。