《阿里游戏高可用架构设计实践》阅读笔记

总体架构

经过深入的讨论和分析,最后我们认为,根本原因还是系统设计方案有问题,也就是说,技术上是比较弱的。

得到这个根本原因之后,解决策略就比较明显,总结一句话就是“把运维的锅让研发去背”,不要指望你的运气好或者烧香、提高某某人的运维能力,而是假设所有的这些问题都有可能发生,发生之后你的系统是不是有应对的措施和快速的解决方案?最终我们决定从技术方面来解决这个可靠性的问题。

高可用目标-传统方法

确定这个方向之后我们就需要定一个目标,首先确定一个目标。高可用其实都是指几个9,5个9的话可能就是电信级或者金融级的,互联网大部分是3个9到4个9。

刚开始也想用这个指标作为一个目标,比如说想达到4个9或者5个9,但是这个指标的优点是业界通用,搞技术的大家都接受了这个指标。

但是有一个缺点,除了技术人员,其他同学不是很好理解,他们没有办法将4个9或者5个9转换成直观的理解。所以,我们当时在定项目目标的时候并没有这样去定。

高可用目标-面向业务

我们最终确定的目标跟几个9的目标有一个比较大的区别,几个9的目标主要是从系统的角度去考虑的,就是说这个系统的可靠性是几个9。

而我们的目标是面向整个业务,这个目标就是3分钟来定位问题,5分钟能恢复业务,而且问题的发生频率不能太高,2个月发生一次。

这个目标的优点:

1、聚焦业务。

2、容易分解。目标本身就是我们的工作方向,首先要定位问题,怎么定位问题?我们就可以想一个办法,其次是恢复业务,第三是故障的频率不能太高;

3、容易衡量。我们后来再做方案的时候,很多方案只要拿这个标准一套,基本上就能够判断这个方案是否可行。

整个目标最后折算下来,对应的差不多是4个9左右,比4个9高一点点。

高可用整体架构

整体架构一共分为四层:用户层、网络层、服务层、运维层。

整个架构其实跟目标是一样的,我们是面向整个业务的,没有说哪个系统应该具备几个9的高可用,而是站在整个业务的全流程来看假设要达到目标,每一个应该怎么去做。

每一层都需要做一些应对的方案,才能达到目标。

架构解耦

业务分离

下图是原来的架构,这个系统把所有的功能都包含了,比如说登录、注册、参数下发、消息、日志、更新。

其实对于玩家来玩游戏来说,真正强相关的只有登录注册和参数下发,消息和日志、更新其实并不是玩家玩游戏必须具备或者强相关的。

所以,业务分离的做法就是把核心业务和非核心业务分拆到不同的系统中,把两个系统之间通过接口调用,互相访问。

这样做的好处,假设非核心业务系统出现故障,它并不影响核心业务系统,因为它们之间是通过接口调用的,并不共享相同的资源。

举一个最简单的例子。

现在因为运营的误操作,下发了大量的消息,最后把整个系统冲死了,玩家登录不了,游戏玩不了。拆分之后,这块系统自己能够完全挂起,跟玩游戏相关的登录、注册都不受影响,他可以继续访问,只要玩家只要能够登录游戏进行玩,就不会有太大的问题。

当然,这个架构对系统功能实现还是有一定要求的,毕竟有接口访问,核心系统和非核心系统还是有一定依赖的。

所以,对于核心业务系统来说,涉及到非核心业务系统的访问就需要做一定的容错处理。如果接口调用失败后,你自己的业务就失败了,就起不到业务分离的作用。

服务中心

服务中心类似于DNS,是实现整个内部系统之间服务调用时候的调度功能,服务中心是一个类似于服务的名字系统。

比如说有一个A业务想访问其他系统提供的业务。它首先并不是直接访问到另外一个系统,而是要到服务中心访问一下。

比如说我需要X服务,服务中心告诉A:你去访问Host1+port1的xxx接口。服务中心有一个配置和状态上报,可以根据一些状态、算法、配置,选择一个最优秀的服务器告诉A业务。

那么,A业务收到之后就按照这个指示去访问真正提供业务的机器,比如B系统里的Host1+ port1这个机器。服务中心的作用跟HTTP-DNS的作用差不多,就是希望在内部某个系统故障的时候可以快速处理或者切换。

假设B系统某台机器有问题了,我们可以通过自动或者人工的方式在服务中心把这台机器直接下掉,A业务请求的时候,它就不会再请求到这个有问题的机器上,这一台机器的故障就不影响A业务。

业务降级

整个系统拆分成核心业务系统和非核心业务系统,在一些紧急情况下,比如说非核心业务系统重启也没有办法,甚至说某个数据库搞挂了,它又影响业务核心系统。

这个时候,接口是可以访问的,但是响应时间特别慢,核心系统就有点被拖慢。

那么,在这种比较极端的情况下,我们可以通过人工的方式下发降级指令,把这个非核心业务系统的功能给停掉,这个停掉并不是把程序停掉,而是说把其中的一个接口或者url停掉,核心系统去访问的时候就得到一个500或者503错误。

我们做了一个专门的降级系统,降级系统可以去下发这些降级指令。一般情况下由降级系统给非核心业务系统下发降级指令,如果到了一些关键时刻,其实核心业务系统中有的接口也是可以进行降级的。

也就是说,我们降级的时候并不是对整个系统或者整个功能进行降级,我们可以做到接口或者url这个级别的降级。通过牺牲非核心业务系统的功能,我们尽最大努力地去保证核心业务系统提供的业务。

这个业界有很多叫法,比如有损服务、可损服务,其实我们这个也是一个可损服务,功能上的可损,不是流量上的可损。

异地多活

原来的老架构中分两个集群:A集群、B集群。两个集群共用同一个数据库主库,部署在A集群,所有的写操作都放在A集群主库,由A集群主库同步到A集群从库、B集群从库,各集群的读操作都直接读集群本地的从库。

它的缺点是存在全局单点的问题,假如说A集群主库挂了,两个集群的业务基本上全部不能提供了。

第二个问题是跨机房同步时延的问题,从A集群同步到B集群,我们是直接通过MySQL底层的复制机制去同步的,在一些比较极端的情况下,它的时延可能达到半小时甚至一个小时,这么大的时延的情况下,提供的业务可能就有问题。

为了解决全局单点、跨机房同步时延的问题,我们做了一套新架构,这个新架构和老架构相比。最大的特点:

1、业务层数据同步。现在有两个主库了,每个集群读写自己的库。那么,两个集群的数据怎么同步呢?我们其实是通过应用层进行数据同步的,而没有采用数据库底层的机制读库。

这样做有一个好处,我们能够尽量通过程序去保证同步的有效性和及时性,而不依赖于底层,用程序可以做多种动作。

2、二次读取。虽然程序进行同步能够尽最大可能缓解同步时延的问题,但是在一定极端情况下其实还是有一定时延的问题。所以,我们又做了两个集群直接互相读取的功能,叫二次读取。

也就是说,有的数据在A集群还没有同步到B集群,B集群此时是读取不到的,这时B集群的系统会通过程序的接口再去访问A集群的系统,意思是:A集群,你这边有没有这个数据?如果有的话,A集群就要返回数据给B集群,B集群再把数据再写入本地。

3、可重复生成全局唯一数据。我们的游戏数据中有一个数据是要求全局唯一的,不管在哪个集群,不管什么时候生成,对于同一款游戏、同一个用户来说,这一个值都是唯一的。

最开始的时候,我们是通过redis两个集群分段来实现的,但是通过redis分段就有一个问题,假设其中一个集群宕机之后,另一个集群并不能把原来集群的业务全部接过去,只是能够保证自己集群的业务没有问题。

我们为了能够解决两个集群互相接管对方的业务,就做了可重复生成全局唯一数据方案。

 

阅读原文:

https://mp.weixin.qq.com/s?__biz=MzA4Nzg5Nzc5OA==&mid=2651660980&idx=1&sn=640c3d2280d7657f236434ff6ba0b22b&scene=21#wechat_redirect

猜你喜欢

转载自www.cnblogs.com/iCheny/p/11056387.html