专栏名称: CSDN
CSDN精彩内容每日推荐。我们关注IT产品研发背后的那些人、技术和故事。
目录
相关文章推荐
TechWeb  ·  TechWeb微晚报:小米SU7 ... ·  14 小时前  
新浪科技  ·  【#特斯拉销量持续滑坡# ... ·  昨天  
香港新港人  ·  皇崗口岸回港︱女子帶70萬港幣 ... ·  2 天前  
新浪科技  ·  【#雷军称SU7Ultra初衷是打造新豪车# ... ·  3 天前  
新浪科技  ·  【#小米公布SU7Ultra设计手稿#】小米 ... ·  3 天前  
51好读  ›  专栏  ›  CSDN

探讨数据时代构建高可用数据库的新技术

CSDN  · 公众号  · 科技媒体  · 2017-03-21 13:02

正文

作者:崔秋,PingCAP 联合创始人;
来文来自《程序员》,禁止任何未经许可的转载。


近几年,随着移动互联网的发展、云计算的普及和各种新业务的出现,数据呈现爆发式增长,给整个业务系统带来了越来越大的挑战,特别是对于底层数据存储系统。完美的高可用系统,是所有公司最理想的追求。如果只从应用层和缓存层看高可用问题,是比较容易解决的。对于应用层来说,根据业务特点可以很方便地设计成无状态的服务,在大多数互联网公司中,在业务层的最上层使用动态DNS、LVS、HAProxy等负载均衡组件,配合Docker和Kubernetes实现弹性伸缩,能够很容易实现应用服务的高可用。对于缓存层来说,也有很多可选的开源方案来帮助解决,比如Codis、Twemproxy、Redis Cluster等等,如果对缓存数据的一致性和实时性要求不高,这些方案就可以很好解决缓存层面的问题。但对存储层来说,支持高可用非常困难。


在互联网架构中,最底层的核心数据存储一般都会选择关系型数据库,最流行的当属MySQL。大数据时代,大家渐渐发现传统的关系型数据库开始出现一些瓶颈:单机容量不能支撑快速增长的业务需求;高并发的频繁访问经常造成服务的响应超时;主从数据同步带来的数据不一致问题;大数据场景下查询性能大幅波动等等。


当前,数据库方案有了很多不一样的变化。首先,不同于早期的单机型数据库,在当下数据呈现爆发式增长,数据总量也从GB级别跨越到了TB甚至PB级别,远超单机数据库的存储上限,所以只能选择分布式的数据存储方案。其次,随着存储节点的增加,存储节点出问题的可能性也大大提高,光靠人工完全不现实,所以需要数据库层面保证自己高效快速地实现故障迁移。另外,随着存储节点的增加,运维成本也大大增加,对自动化工具也提出了更高要求。最后,新分布式数据库的出现,用户在OLTP数据库基本需求的基础上,对大数据分析查询的业务要求更高,在某种程度上OLTP和OLAP融合的新型数据库会是未来极具潜力的发展方向之一。


什么是高可用


Wikipedia的解释中,高可用即High Availability,一般通过SLA(Service Level Agrement)来衡量。这里从CAP角度来看待高可用问题。CAP是分布式系统领域一个非常著名的理论,由Berkerly的Brewer提出。该理论认为任何基于网络的分布式系统都具有以下三要素:


  • 数据一致性(Consistence):等同于所有节点访问同一份最新的数据副本;

  • 可用性(Availability):对数据更新具备高可用性;

  • 分区容忍性(Partition tolerance):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A间做出选择。


三要素不能同时满足。但后来很多人将CAP解读为数据一致性、可用性和分区容忍性最多只能满足两个,这种解读本身存在一定的误导性,原因就在于忽略了特定条件。假想两个节点N1和N2,在某些场景下发生了分区(P)问题,即N1和N2分处分区的两侧。这时对于外部的写操作来说,如果允许任一节点可写的话就相当于选择了A,丧失了C。同样,如果为了满足C,那么写入操作就会失败,A就无法保证,所以存在分区问题时,无法同时保证A和C。虽然分区在局域网中出现的概率相对很低,但却无法避免,所以系统只能在CP和AP之间做出权衡。


当前有很多的NoSQL数据库,在CAP之间选择了AP,比如Amazon Dynamo和Cassandra,追求可用性,适当牺牲一致性,只实现最终一致性。这种选择允许短时间的数据不一致,并且可以交由用户自己来处理写入冲突,但是可以随时接受用户的读写请求。在这种场景下就需要特别注意数据不一致引起的各种奇怪问题,对于比较严肃的业务场景,比如订单、支付等,对事务和一致性要求比较高,这种AP类型的系统就不适用了。而且该系统放弃了SQL和ACID事务,给开发人员带来了更多的开发工作和额外的心智负担,很容易出现问题,所以NoSQL数据库牺牲一致性来获取服务的可用性,并没有彻底解决大数据时代数据库的高可用问题。


大数据时代,传统的关系型数据库必然会由单机扩展到分布式,追求数据一致性,所以必然会是一个CP类型的系统,像这种新型的、下一代的分布式关系型数据库,既具有传统单机数据库的SQL支持和ACID事务保证,又有NoSQL数据库的Scale特点,称为NewSQL数据库,包括Google的Spanner/F1、PingCAP的TiDB等等。但从CAP的角度看,选择CP并不意味着完全放弃了A,CP系统只是在某些产生分区的场景下不能实现100%的A,但完全可以通过有效的办法来实现高可用(HA)。由此可见,并不是CP系统就完全放弃了A,只不过在产生分区的场景下无法从理论上保证A,这是一个常见的误解。


澄清了CAP的问题,下面讨论如何打造高可用的数据库。数据库是一个非常大的概念,从传统单机SQL,到NoSQL,再到现在流行的NewSQL,这里面不同的实现方案实在太多,本文聚焦在关系型数据库,主要探讨最流行的MySQL数据库及其生态。最近几年,随着大家在分布式数据库领域的探索,出现了很多不同类型的解决方案,比如中间件/Proxy的方案,典型的比如TDDL、Cobar、Altlas、DRDS、TDSQL、MyCAT、KingShard、Vitess、PhxSQL等,还有一种新型的NewSQL数据库,比如Google Spanner/F1、Oceanbase、TiDB等。下面看下业界在打造高可用数据库方面新的技术进展,以及和传统方案选型的对比。


消除单点问题


为了实现数据库层面的高可用,必须要消除单点问题(SPOF)。存在单点服务的情况下,一旦单点服务挂掉,整个服务就不可用。消除单点问题最常用的方案就是复制(Replication),通过数据冗余的方式来实现高可用。


为什么必须要冗余?数据库本身是有状态的,不会像无状态的服务那样挂掉就可以重启,而数据库本身能够保证数据持久化,所以如果没有冗余副本,一旦数据库挂掉,只能等待数据库重启,在这段恢复时间服务完全不可用,高可用就无法保证。但如果有了额外的数据副本,高可用就变得可能了,主要能保证在检测到服务发生问题之后及时做服务切换。

对于MySQL来说,默认复制方式是异步的主从复制方式,虽然这种方案被很多的互联网公司所采用,但实际上这种方案存在一个致命问题——存在丢失数据的风险。数据传输经过网络,这也就意味着存在传输时延,那么对于异步复制来说,主从数据库的数据本身是最终一致性的,所以主库一旦出现了问题,切换从库极有可能会带来数据不一致的风险。

因为异步复制方式存在更大的问题,很多时候大家都会考虑用半同步复制方式Semi-Sync,这种数据复制方式在默认情况下会使用同步的数据复制方式,不过在数据复制压力较大的情况下,就会退化成异步的数据复制方式,所以依然会存在高可用问题。当然,也有人会选用完全同步的方式,但是这种复制方式在并发压力下会有明显的性能问题,所以也不常用。


那有没有一种数据复制方式,能同时保证数据的可靠性和性能?答案是有的,那就是最近业界讨论较多的分布式一致性算法,典型的是Paxos和Raft。简单来说,它们是高度自动化、强一致的复制算法。以Raft为例,Raft中基数个节点组成一个Raft Group,在一个Raft Group内,只要满足大多数节点写成功,就认为可以写成功了,比如一个3节点的Raft Group,只要保证Raft Leader和任意一个Raft Follower写成功就可以了,所以同步写Leader,异步写两个Follower,只要其中一个返回就可以,相比完全的同步方式,性能要好很多。所以从复制层面来看,Raft更像是一个自适应的同步+异步复制方案,同步和异步的最优选择通过Raft算法来保证。


庆幸的是,业界早已意识到这个问题,从最开始的Galera Cluster探索到前段时间微信开源的PhxSQL,再到最新MySQL官方发布的MRG(MySQL Group Replication),还有我们从0到1打造的开源分布式数据库TiDB,都在这方面进行了探索。大家的出发点基本相同,采用新的分布式一致性来替换传统的Master-Slave复制方式,不同的仅仅是大家选择的协议:TiDB选择了Raft,而PhxSQL和MRG选择了Paxos。


由此看出,新一代高可用的数据库必然会使用分布式一致性算法来实现数据复制,这已是业界的趋势。


自动故障恢复


有了数据复制,理论上来说,在一个数据库节点出现问题时就不用那么慌张,毕竟还有额外的数据副本存在。所以下面要做的就是尽早发现服务故障并快速恢复,也就是常说的Auto-failover。


从这个层面来看,目前基于主从的数据库复制方案基本上无法脱离运维,使用中间件/Proxy方案更会增加难度,毕竟人力运维是有上限的,所以选择这种方案,人力成本也是一个需要考虑的问题。Google之前在广告业务中也是使用的MySQL中间件方案,大约100个节点的规模,在这个量级下维护的复杂度和成本非常高。所以Google要做一个真正替换MySQL中间件的理想方案,这就有了后来的Google Spanner/F1,包括后来的TiDB,都采用了这种新的NewSQL架构,唯一不同的是,Google选择了Paxos,而TiDB选择了Raft。这种分布式一致性算法,除了提供优雅的复制方案,还可以提供高效的Auto-failover支持。


要想实现Auto-failover,首先需尽快检测到Fail情况。常用方式是通过LVS或者HAProxy之类的负载均衡组件,或者通过类似的Monitor进行远程监控,但对于网络来说,存在三种不同的状态:Success/Failure/Timeout,因为存在Timeout,Monitor的监控不完全准确,而且Monitor本身也会存在高可用问题,所以外部监控不一定完全靠谱,这也是需要考虑的问题。但是以分布式一致性算法Raft为例,Raft内部维护Raft Group,正常情况下都是Leader提供数据读写服务,当Leader出现问题时会自动从Follower中选择新的Leader出来。Raft通过内部的心跳来感知不同节点的状态,并且直接完成Auto-failover,所以Raft是高度自动化并且可以自恢复的。相比于检测再处理的算法,这种基于分布式一致性算法的Auto-failover能力更强,效率更高,当然速度也更快,基本上在秒级别就可以完成Leader更新,继续提供服务,而且是完全自动化的。


关于Auto-failover还有一个引申的跨数据中心多活问题。这基本上是所有分布式系统开发者心中的圣杯,金融级别的数据可用性和安全性。目前从纯软件方案来看,基本没有靠谱的方案,大多数人所谓的异地多活方案实际上底层仍是同步热备,而且很难在保证延迟的情况下同时保持一致性,但是基于Paxos/Raft的方案给多活提供了新的可能性。还是以Raft为例,只要一个Raft Group内的大多数节点复制成功,并在物理节点层面按照特定的方式部署,就可以在软件层面构建一个两地三中心的方案。举个例子,如果这个Raft Group内有三个节点,分别在北京、天津和上海的三个数据中心,对于传统的强一致方案,一个在北京发起的写入需要等待天津和上海的数据中心复制完毕,才能给客户端返回成功,但是对于Raft这样的算法,延迟仅仅在北京和天津数据中心之间,相比传统方案大大降低了延迟。虽然对于带宽的要求仍然很高,但这是未来在数据库层面上实现跨数据中心多活的一个趋势和可行方向,实际上Google分别位于美国西海岸、东海岸以及中部的Spanner数据中心,已经做到了跨地域的数据高可用。真正实现跨数据中心多活,就不用担心挖断光纤导致服务不可用之类的问题了。


在线扩容


随着数据库的数据量越来越大,Scale是不可避免的问题。对于数据库来说,技术层面最大的追求就在于如何不停服务地对数据库节点进行Scale操作,这是非常有挑战性的事情。以中间件/Proxy方案来说,很多时候不得不提前对数据量进行规划,把扩容作为重要的计划来做,从DBA到运维到测试到开发人员,很早之前就要做相关的准备工作,真正扩容时为了保证数据安全,经常会选择停服务来保证没有新的数据写入,新的实例数据同步后还要做数据的一致性校验。当然业界大公司有足够雄厚的技术实力,可以采用更自动化的方案,将扩容停机时间尽量缩短(但很难缩减到0),但大部分中小互联网公司和传统企业依然无法避免较长时间的停服务问题。TiDB完全实现了在线的弹性扩容,主要基于Placement Driver的调度和Raft算法。







请到「今天看啥」查看全文