内容简介:我们先来回顾一下github这次事故: 2018年10月21日,github 在更换网络设备时,引发了美国东海岸网络中心和东海岸数据中心的网络链接发生了40秒的中断,最终导致多个mysql的主集群由Orchestrator 自动选举切换到了美国西海岸数据中心对应的集群,由此引发了数据不一致,直接导致了超过24小时的服务降级,最后仍然还有少量数据需人工排查修复的悲剧。事件的整个过程参考github数据库做的是本地主备+跨区域数据中心的容灾方案,主数据库集群和其他数据中心的集群是异步同步的,当物理网络发生中断
我们先来回顾一下github这次事故: 2018年10月21日,github 在更换网络设备时,引发了美国东海岸网络中心和东海岸数据中心的网络链接发生了40秒的中断,最终导致多个 mysql 的主集群由Orchestrator 自动选举切换到了美国西海岸数据中心对应的集群,由此引发了数据不一致,直接导致了超过24小时的服务降级,最后仍然还有少量数据需人工排查修复的悲剧。
事件的整个过程参考 blog.github.com/2018-10-30-… 这篇文章,在这里不详细说明,我们来直接看导致事件的根本原因。
根本原因:缺失异地数据中心之间数据一致性的保障机制
github数据库做的是本地主备+跨区域数据中心的容灾方案,主数据库集群和其他数据中心的集群是异步同步的,当物理网络发生中断后,对于github这样全球性的,大量用户访问的系统,时时刻刻都有数据变更,刚刚提交的数据还没有来得急同步过去,这时按照Orchestrator的机制,必然会重新选举出新的数据库写入主节点。在没有确定数据全局一致性的情况,就这么一切,两边数据就没法一致同步了,更悲剧的是等网络40s后恢复后,在Orchestrator没有将原有的数据库主节点置为从节点之前,东海岸本地的应用还在往本地数据库集群写数据,加剧了数据的不一致,发生了脑裂现象。除了数据不一致的问题外,还有个比较严重的后果,github 除了数据库主节点负责单点写外,其他区域数据中心的数据库节点负责读,把东海岸的应用数据库切都西海岸,会有60ms的网络消耗,就这点耗时,导致很多应用出现了服务超时不可用,对于很多web应用,一个前端请求会触发后端系统几十次的请求非常正常。由此可以看出,github在处理跨数据中心的高可用方案上是有较大漏洞,没有真正考虑一个数据中心不可用,和数据中心之间的网络故障时的两个重要场景。
没有引起重视的原因分析
对于这么重要的场景,为啥github这么牛的公司没有实施了?个人猜测的几个原因(仅个人观点):
1.github 发展太快也太顺利了,之前应当是没有出过什么严重问题,精力都聚焦到能带来效益的事情了,这样的事情没有引起足够的重视,技术战略上没有特别重视。
2.异地多活的方案非常复杂,不仅是数据库的跨地域数据中心同步这么简单,需要结合公司的实际业务进行全局整体性的方案设计。
3.投入大,成本高,就拿异地机房之间的网络线路来说,至少需要保障两个物理上独立的线路,而这些线路对数据中心来说,至少需要100G 光纤专线。此外其应用系统为了适应异地多活带来也需要进行架构升级,灰度测试等等。
实际来看这是很多公司都面临的普遍问题,在业务高速发展和系统可靠性建设上如何找到平衡点的问题。对于很多业务导向的公司,系统出现过严重问题,才会重视起来。
异地多活方案如何来做?
计算机的分层思想非常有利于分析一个复杂系统,异地多活涉及到数据,应用系统,基础软件,网络,运维系统等等,非常复杂。采用分层思想能极大的简化问题,解耦各层,然后全局看。下面是一个典型分布式是数据中心的分层结构:
让我们来看每个分层的异地多活方案如何做:
DNS层:本身就是一个全球性的分布式系统,天然就是异地多活的,在这一层做自己的异地多活,更多是依赖DNS机制,系统化的动态切换域名和服务器的映射。因其DNS变更生效需要几分钟到几十分钟,对实时性要求高的容灾,不能依赖这块。
CDN层:严格来说,和DNS 一样,也是天然异地多活的,因为CDN更多的是对静态资源访问的加速,需提前将静态资源分发到离消费者更近的节点,挂掉一个节点不会影响数据的不一致,会降低访问速度,影响用户体验。
负载均衡层:通过故障转移策略,可以迅速的将挂掉的服务器流量切到同城或者异地的数据中心,非常便捷高效,但这个地方一定要确保底层的数据已经同步过去之后,才能切,否则会出现数据不一致的情况。
应用层:需要跨数据中心弹性集群部署,就单个应用本身而言,没有什么难度,难度主要集中在依赖应用上,对于很多业务系统,特别是微服务架构成为主流后,一个业务系统至少会依赖调用好几个其他应用,对于复杂的电商系统来说,一个系统依赖几十个其他系统的服务很正常。应用层的异地双活,就不是简单的单应用的跨数据中心部署,而是需要按照业务单元整体性考虑,单元化的思想是阿里异地双活的基础。这块需要重点考虑的是,业务单元内的系统之间相互调用要本地化调用,避免跨单元,但对于一些没法单元化的业务,需要有中心单元化来统一支撑。此外应用系统本身的架构也需要考虑异地多活,特别是要考虑跨地域访问带来的时延影响,数据重复消费等问题。
中间件,缓存层:需要中间件本身要支持异地多活,就拿分布式缓存 redis 来说,put 数据,需要支持在本地数据中心,和异地数据中心同时生效,失效也是一样。这就需要对redis 进行修改。消息中间件,以及其他中间件也是类似,对于不支持异地数据中心的版本,都需自行修改源码进行支持,对于一般的小公司来说,这个难度非常大。只有top的公司才具备这样的技术和环境去做这个事情。
数据库/存储:数据库每个厂商对异地数据中心的支持方案有差异,就mysql来说,mysql 目前的版本还不支持异地同步的方案,只支持本地同步副本,对于mysql的同步,只能是利用实时的数据同步工具drc 来做,因为不是异步同步,仍然存在几ms-几百ms的延迟。将流量从故障的数据中心切换到其他数据中心时,一定要先将故障集群的数据库设置成只读集群,其次确定数据库已经完全同步数据到对应异地数据中心的数据库。最后将异地数据库集群设置为写集群。
而整个过程会有几分钟的中断,服务不可用,遇上罕见的这种故障,几分钟的故障恢复时间是可以接受的,支付宝的异地多活也是分钟级别的。这个地方最怕的就是物理线路故障,如挖掘机挖断光纤的事情,对于大型金融级的数据中心,物理上有两条独立的光纤线路是必须的。遇上物理线路故障,肯定会存在少量数据没有同步完的情况,这时候,原本到故障dc的写流量是不能贸然转移到其他dc的,这时必然要牺牲部分服务的可用性;除非你能接受数据不一致的情况。
看完每层的情况,再来看全局,当一个DC发生故障时,如何在保证数据完整的情况下,故障转移了。发生故障不可怕,怕的是丢数据,数据错乱。所有的策略都是围绕数据的完整和正确性。全局设计也是一样,因此我认为较为合理故障处理策略应当按照下面的步骤来:
我们的原则就是将一切造成数据混乱的可能性降到最低,必然就是先关闭数据库的写,这会造成应用层写数据库等异常,但这也是我们期望的。
发生整个DC出现大面积故障的事件是比较少的,最常见的故障还是比如某个核心系统库,部分网络故障. 而这些故障会根据异地多活的方案有不同的一些恢复策略,以数据库发生异常为例,通常的恢复策略为:
1.切换本地备库为主库;从已有备份重新还原做备库.
2.切换数据库的代理到异地/同城的对应的数据库集群,一定要确保数据是完全同步过去之后才能切,如果用Orchestrator之类的故障自动转移,需要做对应的数据检查机制。
总结
对于异地多活,没有一刀切完全通用的方案,需要根据自己的业务特点,在成本,服务可用性和数据完整性,技术复杂度之间做平衡,找到最适合自己公司的方案;但是最重要的原则就是不管那种方案,确保数据的完整性和一致性是首要考虑的。
联系邮箱:public@space-explore.com
(未经同意,请勿转载)
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 稳定性相关异地多活
- 无需公网IP就能异地组网?
- OPPO异地多活实践——缓存篇
- OPPO 异地多活实践:缓存篇
- 异地多活:MySQL实时双向(多向)复制实践
- 携程异地多活:MySQL 实时双向(多向)复制实践
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Text Processing in Python
David Mertz / Addison-Wesley Professional / 2003-6-12 / USD 54.99
Text Processing in Python describes techniques for manipulation of text using the Python programming language. At the broadest level, text processing is simply taking textual information and doing som......一起来看看 《Text Processing in Python》 这本书的介绍吧!