原文地址:http://os.51cto.com/art/201307/403298.htm 侵删
2013-07-17 11:12 麦子迈 麦子迈
在OpenStack中,数据库是主要系统“状态”的主要来源。数据库给OpenStack提供了状态组件并把状态的“共享”问题交给了数据库,因此解决OpenStack的扩展问题实际上就是解决使用的数据库本身的扩展问题。本文会分析”网络分区“给数据库扩展带来的问题,同时在OpenStack组件中如何规避和解决。
在OpenStack中,数据库是主要系统“状态”的主要来源。大部分Core Projects都使用传统关系型数据库作为系统数据和状态的存储,另外如Ceilometer使用了MongoDB,还有其他Incubator Projects使用了Redis作为队列或者状态存储。数据库给OpenStack提供了状态组件并把状态的“共享”问题交给了数据库,因此解决OpenStack的扩展问题实际上就是解决使用的数据库本身的扩展问题。比如OpenStack HA Solution最令人头疼的就是传统关系数据库或者其他数据存储的扩展问题,数据库扩展问题的根源是其本身不支持分布式和良好的扩展性,而这个根源又会衍生出分布式系统最大的噩梦–“网络分区”。
下面会分析”网络分区“给数据库扩展带来的问题,同时在OpenStack组件中如何规避和解决。
一致性
现代软件系统由一系列“组件”通过异步、不可靠的网络相互沟通构建。理解一个可信赖的分布式系统需要对网络本身的分析,而“状态”共享就是一个最重要的问题。
举一个例子,当你发表一篇博文后,你可能想知道在你点击“发布”操作之后:
1. 从现在开始会对所有人可见;
2. 从现在开始会对你的连接可见,其他人会延迟;
3. 你也可能暂时不可见,但是未来会可见;
4. 现在可见或者不可见:发生错误
5. …… etc
不同的分布式系统会有对一致性和持久性相互影响的权衡和决定,比如Dynamo类系统通过NRW来指定一致性,如果N=3, W=2,R=1,你将会得到:
1. 可能不会马上看到更新
2. 更新数据会在一个节点失败后存活
如果你像Zookeeper来写入,那会得到一个强一致性保证:写操作会对所有人可见,比如这个写操作在一半以下的节点失败后仍然能够保证。如果你像MySQL写入,取决于你的事物一致性级别,你的写操作一致性会对所有人、你可见或者最终一致性。
网络分区
分布式通常假设网络是异步的,意味着网络可能会导致任意的重复、丢失、延迟或者乱序的节点间消息传递。在实际中,TCP状态机会保证节点间消息传递的不丢失、不重复、时序。但是,在Socket级别上,节点接发消息会阻塞,超时等等。
检测到网络失败是困难,因为我们唯一能跟得到其他节点状态的信息就是通过网络来得到,延迟跟网络失败也无从区分。这里就会产生一个基本的网络分区问题:高延迟可以考虑作为失败。当分区产生后,我们没有渠道去了解到其他节点到底发生了什么事: 它们是否还存活?或者已经crash?是否有收到消息?是否正在尝试回应。当网络最终恢复后,我们需要重新建立连接然后尝试解决在不一致状态时的不一致。
很多系统在解决分区时会进入一个特殊的降级操作模式。CAP理论也告诉我们妖么得到一致性要么高可用性,但是很少有数据库系统能够达到CAP理论的极限,多数只是丢失数据。
接下来的内容会介绍一些分布式系统是如何在网络失败后进行相关行为。
传统数据库与2PC
传统的SQL数据库如MySQL、Postgresql都提供一系列不同的一致性级别,然后通常都只能向一个primary写入,我们可以把这些数据库认为是CP系统(CAP理论),如果分区发生,整个系统会不可用(因为ACID)。
那么传统数据库是不是真的是强一致性?它们都是使用2PC策略来提交请求:
1. 客户端commit
2. 服务器端写操作然后回应
3. 客户端收到回应完成提交
在这三个步骤中,可能发生不一致的情况在于2与3之间,当服务器写操作完成但是回应没有被客户端收到,无论是超时或者网络故障,客户端这时会认为这次操作没有完成,而事实上数据库已经写入。这时就会产生不一致的行为。也就是客户端得到的错误并不能解释到底服务器端有没有写入。
2PC不仅在传统SQL数据库被广泛使用,也有大量用户实现2PC在MongoDB之上来完成多键值事务操作。
那么如何解决这个问题?首先必须接受这个问题,因为网络失败地概率比较低,并且正好在服务器写操作完成与客户端得到回应之间失败。这使得受到影响的操作非常稀有,在大部分业务中,这个失败是可接受到。相对的,如果你必须要强一致性的实施,那么应该在业务中付诸行动,比如所有的事务写操作都是幂等的,是可重入的。这样当遇到网络问题时,retry即可而不管到底写操作有没有完成。最后,一些数据库可以得到事务ID,通过track事务ID你可以在网络故障后重新评估事务是否完成,通过数据库在网络恢复后检查其记录的事物ID然后回滚相应事务。
我们在OpenStack的选择就很有限,目前各个项目中并不是所有写操作都是幂等的,不过幸运的是,OpenStack的数据在罕见的2PC协议特例中损失是能接受的。
Redis
Redis通常被视为一个共享的heap,因为它容易理解的一致性模型,很多用户把Redis作为消息队列、锁服务或者主要数据库。Redis在一个server上运行实例视为CP系统(CAP理论),因此一致性是它的主要目的。
Redis集群通常是主备,primary node负责写入和读取,而slave node只是用来备份。当primary node失败时,slave node有机会被提升为primary node。但是因为primary node和slave node之间是异步传输,因此slave node被提升为primary node后会导致0~N秒的数据丢失。此时Redis的一致性已经被打破,Redis这个模式的集群不是一个CP系统!
Redis有一个官方组件叫Sentinel(参考Redis Sentinel,它是通过类似Quorum的方式来连接Sentinel instance,然后检测Redis集群的状态,对故障的primary节点试用slave节点替换。Redis官方号称这个是HA solution,通过Redis Sentinel来构建一个CP系统。
考虑Redis Sentinel在网络分区时候的情况,这时Redis集群被网络分成两部分,Redis Sentinel在的大区域可能会提升Slave node作为primary node。如果这时候一直client在连接原来的primary node,这时会出现两个primary node(split-brain problem,脑裂问题)!也就是说,Redis Sentinel并没有阻止client连接Old primary node。在此时,已经连接到old primary node的client会写入old primary node,新的client会写入到new primary node。此时,CP系统已经完全瘫痪。虽然Redis集群一直是保持运行的,但是因为依赖于Quorum来提升slave节点,因此它也不会是AP系统。
如果使用Redis作为Lock service,那么这个问题会成为致命问题。这会导致分区后同时可以有两个client获取同一个锁并成功,lock service必须是严格的CP系统,像Zookeeper。
如果使用Redis作为queue,那么你需要接受一个item可能会被分发零次、一次或者两次等等,大部分的分布式队列都保证最多只分发一次或者最少分发一次,CP系统会提确切一次的分发然后带来较高的延迟。你需要明确使用Redis作为队列服务的话必须要接受网络分区后队列服务可能导致的不稳定。
如果使用Redis作为database,那么可想而知,利用Redis Sentinel建立的database是不能称为database的。
最后,以目前的Redis来说,使用官方提供的组件它只能成为Cache。构建一个分布式的Redis前往WheatRedis。
MongoDB
MongoDB采用类似于Redis的集群方式,primary node作为单点写操作服务然后异步写入replication nodes。但是MongoDB内建了primary选举和复制状态机,这使得primary node失败后,整个MongoDB会进行交流然后选择一个合适的slave node。然后MongoDB支持指定primary node可以确认slave node已经把写操作写入log或者真正写入,也就是通过一定的性能损耗来换取更强的一致性当primary node失败后。
那么MongoDB是否可以认定为是一个严格的CP系统?还是与Redis类似的问题,在网络分区后,当primary node在小的分区里,大的分区里的node会选举产生一个新的primary node,而此时在分区的时候,这两个node是会同时存在的(这个没有问题),然后当分区恢复后,小分区里的old primarynode会把在脑裂期间的操作发送到new primary node,这时候可能会产生冲突!
那么如何面对这个问题?接受它,首先这个冲突的概念像2PC一样可以在client端解决,同时MongoDB目前有WriteConnern可以解决这个问题,但会造成巨大的性能影响。
Dynamo
Dynamo是在传统的primary-slave模式遇到问题时候出现的红宝书,借鉴Dynamo的产品在一段时间内出现的非常多。
之前提到的系统都是面向CP的,起码是面向CP设计的。Amazon设计的Dynamo鲜明地面向AP。在Dynamo,它是天然地分区友好型,每一个node都是平等的,通过NWR来指定不同地一致性级别和可用性。这里不会详细阐述Dynaomo的原理(Dynamo,每一个试图了解分布式系统的人都应该对Dynamo这篇论文非常熟悉,即使它面临很多问题,但是论文中出现的对Dynamo设计的思考和变迁是宝贵的。
那么当分区发生时,Dynamo发生了什么?首先根据NWR的推荐设定(W+R>N),小区是不能得到新的写操作,新的对象会写在大区。然后在分区恢复后,小区的对象会滞后并与新的对象发生冲突。这里的冲突解决策略非常多,如Cassandra使用的client timestamps,Riak的Vector clock,如果无法解决,冲突可能会硬性覆盖或者推到业务代码。
然后Dynamo本身没有任何方法来判断一个节点是否数据同步,也无法判断,只能通过完全的数据比较,而这个过程是代价昂贵并且不灵活的。因此Dynamo提到说(W+R>N)可以达到强一致性是不可能的,故障节点只会是最终一致性。
因此,解决Dynamo的问题像前面一样,接受它。首先你的数据可以设计成immutable,然后你的数据决定可以在罕见情况下丢弃或者变旧,再或者使用CRDTs来设计你的数据结构。无论如何,Dynamo始终是一个good idea并且它推动了分布式设计的发展。
BigTable
上面提到的系统都是面向分布式的,要么AP要么CP。那么Bigtable是AC系统,虽然我们介绍的一直是分区问题,但是我们也需要考虑在中心化设计的Bigtable。无论是HBase还是HDFS都是这类设计,它们回避了分区问题并且在单IDC下达到非常好的效果。这里不会详细讨论中心化设计,因为它根本就没有考虑分区问题。
分布式数据库系统的思考
通过上述的分析可以了解到构建一个分布式数据库集群的困难,无论是同步复制,异步复制,Quorum还是其他的,在网络分区面前,任何挣扎都是无力的,网络错误意味着”I don’t know” not “I failed”。
构建一个“正确的”分布式数据库系统通常在几个方面达成意见: 1. 接受罕见的问题 2. 使用开源的软件,分布式系统会产生极大的“漩涡”在“理论正确的分布式算法”和“实际使用的系统“。一个有Bug的系统但是正确的算法比一个错误的设计更能接受。 3. 利用问题进行正确的设计,如使用[CRDTs](http://pagesperso-systeme.lip6.fr/Marc.Shapiro/papers/RR-6956.pdf) 4. split-brain问题是分区的原罪,如何解决split-brain之后的遗产才是正确的解决方案
小结
如何在OpenStack上做到HA是OpenStack官方和其他发行版公司都在努力的方向,而其中关键就在于数据存储的HA和一致性,在这个方向上,我们通过对”网络分区“这一关键问题的分析并在不同类型的数据库上进行落地思考,可以得到如何在其上规避、解决和接受它。通过在OpenStack的产品上思考这些问题,我们可以在HA Solution上有更强健的基础。
参考资料
相关推荐
在实际应用方面,分布式数据库常用于电商、社交网络、大数据分析等领域,解决大规模用户并发访问和海量数据分析的问题。例如,通过分布式数据库,可以实现快速的商品推荐、实时的用户行为追踪和高效的数据挖掘。 ...
通过深入学习这些课件和试卷,学生不仅可以掌握分布式数据库的理论知识,还能提升解决实际问题的能力,为未来在大数据时代的工作做好准备。教育/考试类资源对于个人学习和专业发展至关重要,尤其是在快速发展的IT...
并发控制在分布式数据库中尤为重要,因为它需要解决多事务同时访问相同数据的问题。常见的并发控制方法有锁、多版本并发控制(MVCC)和乐观并发控制,每种方法在分布式环境下都有其适应性和挑战。 七、分布式恢复...
分布式数据库是指将数据库分布在多个物理位置的数据库系统,解决了传统集中式数据库的可扩展性、可靠性和性能瓶颈问题。下面是分布式数据库的一些重要知识点: 分片和分配模式 在分布式数据库中,数据通常被分割成...
分布式数据库是现代信息技术领域中的重要概念,尤其在大数据处理、云计算和互联网应用中扮演着核心角色。清华大学作为中国顶级的高等教育机构,在计算机科学和技术的教学方面有着深厚的底蕴。这份"清华大学分布式...
分布式数据库的出现解决了这一问题,通过将数据分布在网络的不同节点上,实现了数据的分区和并行处理,显著提升了数据处理的效率和吞吐量。 其次,高可用性和容错性是云计算对分布式数据库的另一个关键要求。在...
1. **分布式数据库的基本概念**:了解分布式数据库的基本定义,包括数据的分区、复制和分片等概念,以及分布式事务和并发控制的原理。 2. **数据分布策略**:学习如何根据业务需求选择合适的数据分布策略,如哈希...
在国外,分布式数据库技术已广泛应用于金融、电信、电子商务等领域,许多大型企业如Google、Amazon等都拥有成熟的分布式数据库解决方案。在国内,随着云计算和大数据的发展,分布式数据库也逐渐成为研究热点,不少...
7. 分布式数据库的挑战与解决方案:涵盖网络延迟、数据分布不均、并发控制等问题,以及相应的解决策略,如分片、局部优化和全局优化。 苑森淼教授的课程可能还涉及到了实际案例分析和实战练习,帮助学生更好地理解...
网络延迟和分区可能导致性能下降和一致性维护的难题。此外,系统复杂度高,运维和管理成本也相对较高。 从描述部分可以看出,这篇文章是一篇关于2021年分布式数据库技术发展情况的概览。尽管给定的部分内容没有实际...
分布式数据库试题及答案西南交大研究生 分布式数据库是指将数据库分散存储在多个物理位置的数据库系统。这种数据库系统可以提高数据的可用性和可靠性,并且可以实现更好的性能和可扩展性。 在本试题中,我们将讨论...
分布式数据库是一种由多个物理位置上的数据节点组成的数据库系统,这些节点通过网络相互连接,共同提供数据存储和处理服务。每个节点都可以独立处理部分数据,实现数据的分散存储,提高系统的可用性和扩展性。这种...
在分布式数据库中,数据分布在计算机网络的不同节点上,每个节点都有自治处理能力,能够处理局部应用,同时也能参与到全局应用程序中。分布式数据库管理系统(DDBMS)是这种系统的核心,它负责数据库的创建、查询、...
1. 分区容错性(Partition Tolerance):分布式系统必须能够容忍网络分区,即使部分节点无法通信,系统仍能继续运行。 2. 一致性和可用性:根据CAP定理,分布式系统只能在一致性、可用性和分区容错性中选择两者的...
综上所述,本文所提出的一致性哈希算法的高效扩展方法,为解决分布式数据库在实际应用中的扩展难题提供了一种有效的技术途径。通过对哈希环的优化和节点编码策略的改进,极大地提高了数据库扩展的效率和系统的稳定性...
分布式数据库允许数据分布在不同的地理位置,通过网络进行通信,提高了系统的可伸缩性、容错性和性能。 首先,分布式数据库的基础概念包括分片(Sharding)、复制(Replication)和分区(Partitioning)。分片是将...
3. 一致性模型:分布式数据库必须解决的一致性问题是CAP理论,即在一致性、可用性和分区容忍性之间做出权衡。常见的一致性模型有强一致性、最终一致性等,每种模型对应用的开发和用户体验都有直接影响。 4. 并发...
分布式数据库系统是现代大型互联网应用的核心技术之一,它允许数据分散存储在多个地理位置分散的计算机节点上,通过网络进行通信和协作,以实现高可用性、高性能和可扩展性。以下将详细介绍分布式数据库系统的概念、...
邵佩英会讲解如何在分区(网络故障导致部分节点无法通信)的情况下设计系统,以及CAP定理(Consistency、Availability、Partition Tolerance)是如何限制分布式系统的可能性的。读者将了解到,在这三个特性中,通常...
分布式数据库是软件工程研究生课程的重要组成部分,它涉及到分布式系统、数据一致性、复制、分区、容错等多个核心概念。在教学中,这些概念应该结合具体的分布式数据库系统进行讲解,比如MongoDB的副本集、分片集群...