28-异地多活设计4大技巧
前言
相比同城异区和跨国异地,跨城异地其复杂度是最高的。跨城异地的架构设计主要是解决在数据不一致的情况下,业务不受影响或者影响很小。下面主要介绍一些跨城异地的一些设计技巧:保证核心业务的异地多活、保证核心数据最终一致性、采用多种手段同步数据、只保证绝大部分用户异地多活。
保证核心业务的异地多活
异地多活是为了保证业务的高可用,但是在设计架构时,容易陷入一个误区:需要保证所有的业务的异地多活。如果要实现所有业务都支持异地多活,实际上是很难的,有的问题甚至是无法做异地多活的。其设计原则应该优先保证核心业务的异地多活,需要考虑哪些业务是核心业务。
保证核心数据的最终一致性
异地多活的本质是通过异地的数据冗余,来保证极端情况下业务能够正常的返回给用户,因此数据同步是异地多活的关键。这又容易陷入一个误区:想要保证所有的数据实时同步。
数据冗余是将数据从A地同步到B地,从业务的角度来看是越快越好,最好是和本地机房一样快。但实际是:异地多活是不能很快,这是由物理定律决定的。因此所有数据是实时同步是一个无法实现的目标。
既然无法彻底解决,那只能尽量减少其影响。
尽量减少异地多活机房的距离,搭建高速网络。
尽量减少数据同步,只同步核心业务相关的数据。
保证最终一致性,不保证实时一致性。
最终一致性在具体实现上,需要不同的数据特征,进行差异化处理,以满足业务的需要。
采用多种手段同步数据
数据同步是异地多活设计的核心,基本上存储系统本身都会有数据同步的功能。如:Mysql的主备复制、Redis的Cluster功能、ES的集群功能。对于这些存储系统本身带有数据同步功能的系统,直接拿来用就可以了。但是我们在设计时,不仅仅需要使用存储系统本身的数据同步功能。存储系统本身的数据同步功能,在某些场景下无法满足业务需求的。
我们应该拓宽思路,采用多种数据同步方式。
消息队列方式
对于账号数据,可以采用消息队列的方式同步到其它业务中心。
二次读取方式
在消息队列同步延迟的情况下,我们可以采取二次读取的方式。如用户在A中心注册后,然后在B中心访问服务,由于B中心没有用户的数据,在本地读取失败后,根据路由规则,再去A中心读取一次,这样就能够解决异常情况下同步延迟的问题。
存储系统同步方式
对于用户修改频率很低的信息,比如密码、用户信息这类信息,可以通过数据库同步方式同步到其它业务中心。
回源读取方式
比如对于用户session这类信息,由于数据量大,可以不同步。比如:用户在A中心登录后,又在B中心操作,B中心可以拿到用户上传的sessionid,根据路由规则,去到A中心请求session数据。
重新生成数据方式
对于回源读取方式,如果A中心宕机了,B中心请求session失败,就只能重新登录,让用户在B中心重新登录,生成新的session数据。
只保证绝大部分用户的异地多活
某些场景下我们无法保证100%的业务可用性,总是会有一定的损失。比如密码不同步导致无法登录、用户信息不同步导致用户看到旧的信息等。
在设计架构时,非常容易陷入这样的误区:我要保证业务100%可用。但是在极端情况下就是会丢失一部分数据,就是会有一部分数据不同步,有没有什么办法可以解决这些问题达到100%的高可用呢。
实际上是没有办法的。异地多活也是无法保证业务的100%可用。这是由物理因素决定的,光速、网络的传播速度、硬盘的读写速度、极端异常不可控等,都无法保证业务100%可用。所以在这种情况下,我们必然需要忍受这一小部分用户或业务上的损失,否则本来想为了保证最后0.01%的用户可用性,设计一个所谓的完美方案,到最后99.99%的用户都无法保证。
对于某一些强一制性的业务,可能受影响的用户会更多,甚至达到1/3会或更多。
虽然无法做到100%的可用性,但并不意味着我们什么都不做。可以采取一些措施补偿或安抚用户。
挂公告
事后对用户补偿
补充体验
对于为了做异地多活带来的体验损失,可以想一些方法来减少或规避。比如:对于用户转帐来说,为了让用户不需要确认是否转账成功。可以在转帐成功或失败后,给用户发送一条短信,告知用户转帐状态。
总结
异地多活的关键就在于:采用多种方式,保证绝大部分用户的核心业务的异地多活。