来扯扯分布式数据库系统DDBS设计啊

版权声明:本文为博主原创文章,转载请注明转自 Scofield's blog[http://blog.csdn.net/scotfield_msn] https://blog.csdn.net/Scotfield_msn/article/details/60344796

来扯扯分布式数据库系统DDBS设计啊

注明:本文只是在完成一个高级数据库作业的文章,不能算是正儿八经登堂入室的paper,所以,不负责任哈,带坏小朋友不要找我哦 ^_~


转载注明出处:Scofield's blog[  http://blog.csdn.net/scotfield_msn/article/details/60344796  ]


一、   引入

       目前本人所确定的研究方向是自然语言处理、文本挖掘,实际项目实践中涉及到分布式系统平台的构建,而必然接触得到到分布式系统的核心部分:分布式数据库系统(DDBS)。平时在与分布式数据库系统的接触中,总是会萌发出一种想彻彻底底的了解透分布式DB的想法。现在借助高级数据库原理这门课的报告作业来对DDBS做一个系统的研究。主要探讨设计DDBS所涉及到的关键技术以及算法问题。

1.1、概念

       分布式数据库是指物理上分散而逻辑上集中的系统,它使用计算机网络将地理位置分散而管理和控制又需要不同程度集中的多个逻辑单位(通常是集中式数据库系统)连接起来,共同组成一个统一的数据库系统。分布式数据库系统是相对于传统集中式数据库系统的,随着项目产品的物理上的扩充以及网络技术的发展,集中式数据库系统表现出它的不足:数据按实际需要已在网络上分布存储,再采用集中式处理,势必造成通信开销大;应用程序集中在一台计算机上运行,一旦该计算机发生故障,则整个系统受到影响,可靠性不高;集中式处理引起系统的规模和配置都不够灵活,系统的可扩充性差。在这种形势下,集中式DB的“集中计算”概念向“分布计算”概念发展。

       DDBS的分类有三种:同构同质型DDBS,各个场地都采用同一类型的数据模型;同构异质型DDBS,各个场地采用同一类型的数据模型,但是DBMS的型号不同,譬如DB2、ORACLE、SYBASE、SQL Server;异构型DDBS,各个场地的数据模型的型号不同,甚至类型也不同。

       DDBS的特点在于:物理分布性,数据不是存储在一个场地上,而是存储在计算机网络的多个场地上。逻辑整体性,数据物理分布在各个场地,但逻辑上是一个整体,它们被所有用户(全局用户)共享,并由一个DDBMS统一管理。场地自治性,各场地上的数据由本地的DBMS管理,具有自治处理能力,完成本场地的应用(局部应用)。场地之间协作性,各场地虽然具有高度的自治性,但是又相互协作构成一个整体。以及数据独立性、集中与自治相结合的控制机制、适当增加数据冗余度、事务管理的分布性。所以DDBS得优势也很明显:具有灵活的体系结构,适应分布式的管理和控制机构,经济性能优越,系统的可靠性高、可用性好,局部应用的响应速度快,可扩展性好,易于集成现有的系统。大大降低单个数据库的压力(数据量少,单个数据库不会被频繁操作到,如提交事务,抢占资源程度降低)。

1.2、构建之前的思考

       1、项目考虑构建分布式数据库的时机。

       假设目前服务器的磁盘和内存,cpu都相对较好,一台数据库服务器可以存储好几亿条的数据。考虑用分布式数据库,肯定是容量或者性能方面,现有的单机数据库满足不了业务的需求。普通的X86服务器,一台数据库服务器存好几亿条数据,问题不大,但前提是需要分库或分表,单表几亿条数据,普通服务器基本支撑不了的,毕竟数据量一大,表对应的B树层次就高,写入时B树节点的分裂和调整,开销也大。同时,上亿规模下,单台数据库服务器的恐怕不能支持密集的读请求,性能可能会有问题。

       2、考虑分布式数据库中间件的有效性

       目前比较流行的分布式构建方式是DBA利用开源中间件,结合自己项目的mysql或pg数据库,来搭建出一套分布式数据库的解决方案。主要的方法有两种:一种是水平拆分。当数据量大到单机数据库已存储不下时, 可以对数据进行拆分,化整为零,将数据均匀分布到多个数据库节点中。由于对数据进行了拆分,每个数据库节点上的数据量小了,自然读写性能就提高了。另一种是读写分离。这种方法,主要用在数据量并不大,单机数据库能够hold得住,但读请求很高的情况下。此时,可以配置多个只读数据库节点,来分担主节点的读请求。通过数据复制机制,在主节点和只读节点之间进行数据的实时同步,保证主从节点的数据一致性。两种方法很好地解决了数据库的容量和性能问题。当然,使用了中间件,相当于在sql的执行路径上,多了一个处理环节,因此单条sql的延时,相对于直连数据库节点,在非满负载的情况下,肯定是要高的。但在实际的业务访问中,sql的性能瓶颈,一般都出在数据库节点上,中间件只是做单纯的sql解析和路由,性能开销不会很大。因此,通过增加数据库节点,提升sql处理的短板,是能够提高系统效率的。

       3、中间件对复杂SQL场景的支持度

       确实如果用一些中间件方案,对跨库事务、join等操作很难处理好。基于中间件来进行分库,对 SQL 有阉割的情况,并不是所有sql都能够支持。主要原因是数据被拆分了。而数据一旦被拆分到多个节点,则: 1.复杂的join查询;2.同时更新多个数据库节点的sql语句;这两类SQL的支持难度,就比较高。这也是目前市面上所有中间件都无法满足的两点。复杂的join查询之所以难以支持,是因为要跨节点join;同时更新多个节点的sql难以支持,是因为很难解决多个节点的并发一致性问题。但是除了这两点之外,其他的sql类型,一款中间件是能够努力做到的。综合地讲,中间件也具有一定的局限性。

二、   考虑的问题

       分布式数据库的设计目标要达到:1、本地性或近地性:尽量减少站点之间的通信次数和通信量,满足90%/10%准则,考虑分片和分布方案(本地和远程访问次数)的择优。2、控制数据适当冗余:冗余增加了可靠性、可用性,提高了效率,但会造成维护数据一致性开销增加。3、工作负荷分布均衡:各站点可以分担整个工作任务,但又会造成本地性降低。4、综合考虑存储能力和费用等等。

       若是自己想要设计构建出一套相对高可用、高性能和高并发的DDBS,需要考虑大量的问题。其中典型的有分布式一致性问题、数据分片问题、分布式数据库查询优化、事务管理以及并发问题等等。

2.1、一致性问题

       一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。而一致性又可以分为强一致性与弱一致性。强一致性可以理解为在任意时刻,所有节点中的数据是一样的。同一时间点,你在节点A中获取到key1的值与在节点B中获取到key1的值应该都是一样的。弱一致性包含很多种不同的实现,目前分布式系统中广泛实现的是最终一致性。

       分布式数据库系统中,涉及到了一些关键的部分,比如事务管理处理等,这些部分对一致性的要求非常之高,所以就这就是为什么单独将一致性问题拿出来讲的原因。

       数据库大体分为以下几类,有关系型(事务型)的数据库,以Oracle、MySQL为代表,有keyvalue数据库,以Redis和memcached db为代表,有文档型数据库如MongoDB,有列式数据库以Hbase,cassandra,dynamo为代表。有些数据库本身就是分布式的数据库设计理念,比如上面的列式数据库;有些本身是单节点的设计架构,如redis、mongodb、关系型数据库。但是考虑到整个系统的可用性,这么内存型的数据库都有分布式部署的机制,如redis的主从复制,mongodb的Master-slave,replicaset,mysql和oracle的主从结构。而对于关系型数据库主要以强一致性的实现为主,而文档型、列式数据库主要以弱一致性(最终一致性)的实现为主。

2.2、数据分片

       在设计分布式数据库的时候,设计者必须考虑数据如何分布在各个场地上,也就是全局数据应该如何进行逻辑划分和物理划分。哪些数据应该分布式存放,哪些不需要分布式存放,哪些数据需要复制。对系统惊醒全盘考虑,使系统性能最优。分布式数据库中数据的存储单位成为片段,对全局数据库的划分叫做分片。划分的结果就是片段。每个片段可以保存在一个以上的场地(服务器)。分片的作用大概有以下几种:1、减少网络传输量,对数据进行复制存储,目的是可以就近访问所需数据副本,减少网络上的数据传输量。2、增大事务处理的局部性。3、提高数据的可用性和查询效率。4、负载均衡。

       另外,在分布式数据库中,存在着分区、分片、分库、分表等的概念。

       分区:原来所有的数据都是在一个数据库上的,网络IO及文件IO都集中在一个数据库上的,因此CPU、内存、文件IO、网络IO都可能会成为系统瓶颈。而分区的方案就是把某一个或某几张相关的表的数据放在一个独立的数据库上,这样就可以把CPU、内存、文件IO、网络IO分解到多个机器中,从而提升系统处理能力。分区有两种模式,一种是主从模式,用于做读写分离;另外一种模式是分片模式,也就是说把一个表中的数据分解到多个表中。一个分区只能是其中的一种模式。

       分库(片):分库只是一个通俗说法,更标准名称是数据分片,采用类似分布式数据库理论指导的方法实现,对应用程序达到数据服务的全透明和数据存储的全透明。分表和分区都是基于同一个数据库里的数据分离技巧,对数据库性能有一定提升,对MySQL数据库的吞吐量无质的变化。当业务系统的数据容量接近或超过单台X86服务器的容量、QPS/TPS接近或超过单个MySQL数据库实例的处理极限等,则重点在于扩展MySQL数据库的吞吐量和数据处理量。此时,往往是采用垂直和水平结合的数据拆分方法,把数据服务和数据存储分布到多台MySQL数据库服务器上。

       分表:当数据量大到一定程度的时候,都会导致处理性能的不足,这个时候就没有办法了,只能进行分表处理。也就是把数据库当中数据根据按照分库原则分到多个数据表当中,这样,就可以把大表变成多个小表,不同的分表中数据不重复,从而提高处理效率。

可以这样理解,概念从大到小的排序是:分区(主从模式、分片模式)->分片(分库)->分表。

2.3、查询优化

       在关系数据库系统中有着非常重要的地位 ,关系查询优化是影响RDBMS性能的关键因素。分布式查询优化的目标除了要解决集中式查询处理的问题如:查询转换为代数表达式、从所有等价表达式中选择最优的代数表达式,还要考虑分布式独有的问题:站点之间交换数据的操作、选择最优的执行站点(分布)、数据被传送的方式等等。

总的查询优化准则是使得通讯费用最低和响应时间最短,即以最小的总代价,在最短的响应时间内获得需要的数据。首先,通讯费用与所传输的数据量和通信次数有关。再次,响应时间和通信时间有关,也与局部处理时间有关。

       分布式数据库查询优化的衡量标准:一个查询策略的选择是以执行查询的预期代价为依据的,由集中式系统大都运行在单个处理器的计算机上,所以查询执行总代价为CPU代价加I/O代价之外。分布式查询优化可用CPU代价、I/O代价、通信代价3个参数来徇,总代价为三者之和。在分布式数据库系统中,常以两种不同的目标来考虑查询优化:

       1. 以总代价最小为标准,除了CPU代价和I/O代价之外,还包括数据通过网络传输的代价。

       2. 以每个查询的响应时间最短为标准。响应时间就是从接收查询到完成查询所需要的时间。它既与通信时间有关,又与局部处理时间有关,而通信费用与所传输的数据量和通信次数成正比。

2.4、事务管理

       事务是访问或更新各种数据项的最小逻辑工作单位,它是一个操作序列,它可以使数据库从一个一致状态到另外一个一致状态。而在分布式数据库环境中,一个数据库事务可以更新多个场地上的数据,这种数据库事务称为分布式事务。在分布式数据库系统中事务必须遵循一致性原理,所以如何分布式数据库事务处理管理和恢复成为一个关键的问题。

       设想有一个事务,要求数据变化发生在两个分离的数据库中,仍然要求所有的ACID特性测试能够满足。基本的事务处理不能满足要求,因为如果其中一个数据库服务器失败,无法确保另外一个数据库的数据还没有提交并成为永久的。换句话说,无法协调发生在不同地方的多个事务处理就没有办法保证事务的原子性。

2.5、并发控制

       通常,数据库总有若干个事务在运行,这些事务可能并发地存取相同的数据,称为事务的并发操作。当数据库中有多个事务并发执行时,系统必须对并发事务之间的相互作用加以控制,这是通过并发控制机制来实现的。并发控制就是负责正确协调并发事务的执行,保证这种并发的存取操作不至于破坏数据库的完整性和一致性,确保并发执行的多个事务能够正确地运行并获得正确的结果。

       分布式数据库中的并发控制解决多个分布式事务对数据并发执行的正确性,保证数据库的完整性和一致性,所以比集中式并发控制更复杂。

       数据库的一个重要特征是:支持数据共享,也就是说允许多个用户程序并行地存取数据库中的数据;那么,多用户或多事物可能同时对同一数据进行操作,这成为并发操作。并发操作将带来如下的问题:丢失修改、脏读、不可重复读。

三、   方法论

3.0、DDBS设计方法

       分布式数据库的设计方法有三种:自顶向下方法,即重构法;自底向上方法,即组合法;以及两者的混合方法。

1、自顶向下方法

       自顶向下方法的设计特点是:一般是要重新设计数据库。首先定义数据库的全局内容,然后再对其进行分片成多个数据库子集,再分别定义局部数据库的模式与位置。

自顶向下的设计过程大致是:在逻辑设计与物理设计之间增加分布设计。以一个全局的、与站点无关的模式作为输入,产生分布式数据库个站点的子模式(局部概念模式)作为输出。分布设计包括数据的分片设计和片段的位置分配设计。

2、自底向上方法

       自底向上的分布式数据库设计就是要将现有的各种不同的数据库模式集成为全局模式。所谓集成就是把公用数据定义合并起来,并解决对同一个数据的不同表示方法之间的冲突。自底向上的设计方法不宜于水平分片关系的设计。自底向上方法的设计特点一般是在现有已分布的数据库基础上进行设计。须综合各站点的规格说明,以便得到分布式数据库的全局概念模式。

       自底向上设计方法需要解决三个问题:选择公用数据库模型来描述数据库的全局模式;把每个站点上的本地模式翻译成公用数据模型;把各站点上的本地数据模式集成为一公用的全局模式。

3、混合方法

       在许多实际情况中,更多的是考虑混合方法,设计者都是一部分使用自顶向下方法,另一部分又使用自底向上方法。

3.1、一致性问题

       一致性的解决方案分两种:强一致性和弱一致性。

1、弱一致性(最终一致):由于分布式系统在数据同步时的网络延迟等等因素,无法保证副本数据和主节点时刻保持一致,当出现不一致的时,可以采用以下几种策略保证最终一致性:

       Gossip(Cassandra,Dynamo),是带冗余容错算法,也就是最终一致性的算法,无法保证某时刻所有节点数据一致,它是一个去中心化的部署方式,集群中每个节点维护一组状态,状态可以用key,value,外带一个版本号表示,版本大的比版本小的数据新,节点之间相互交流数据的版本信息,并更新数据,类似病毒式的传递,这样数据可以达到最终一致。Cassandra就是采取这种策略来进行数据的同步,并且维护节点的健康状态。

       向量时钟(Dynamo),是一种数据不一致导致冲突的解决策略,系统采用乐观锁的策略,这样对同一个值进行操作时,就可能会出现多个版本,由向量时钟来解决一致性;每个元素是(更新值的节点,序列号),每当更新一个值时,都带上这些信息,从下图可见,D3和D4出现数据的冲突,那么在下次操作时,会由更新值的节点做冲突的解决。Dynamo采用的就是这种策略进行冲突的解决。

2、强一致性:paxos算法、raft算法。

       Paxos算法:总体说来,paxos就是通过两个阶段确定一个决议:

       Phase1:确定谁的编号最高,只有编号最高者才有权利提交proposal;

       Phase2:编号最高者提交proposal,如果没有其他节点提出更高编号的proposal,则该提案会被顺利通过;否则,整个过程就会重来。

       你编号高,我比你更高,反复如此,算法永远无法结束,这叫活锁。FLP Impossibility已经证明,在异步通信中不存在任何一致性算法,活锁便是Paxos无法解决的硬伤。Phase1,Phase2非常像2PC中的两个阶段,因此paxos本质上是多个2PC交替执行!

       Raft算法:过去, Paxos一直是分布式协议的标准,但是Paxos难于理解,更难以实现。来自Stanford的新的分布式协议研究称为Raft,它是一个为真实世界应用建立的协议,主要注重协议的落地性和可理解性。Paxos和Raft都是为了实现Consensus一致性这个目标,这个过程如同选举一样,参选者需要说服大多数选民(服务器)投票给他,一旦选定后就跟随其操作。Paxos和Raft的区别在于选举的具体过程不同。在Raft中,任何时候一个服务器可以扮演下面角色之一:

       Leader: 处理所有客户端交互,日志复制等,一般一次只有一个Leader.

       Follower: 类似选民,完全被动

       Candidate候选人: 类似Proposer律师,可以被选为一个新的领导人。

       Raft阶段分为两个,首先是选举过程,然后在选举出来的领导人带领进行正常操作。如果在这一过程中,发生了网络分区或者网络通信故障,使得Leader不能访问大多数Follwers了,那么Leader只能正常更新它能访问的那些Follower服务器,而大多数的服务器Follower因为没有了Leader,他们重新选举一个候选者作为Leader,然后这个Leader作为代表于外界打交道,如果外界要求其添加新的日志,这个新的Leader就按上述步骤通知大多数Followers,如果这时网络故障修复了,那么原先的Leader就变成Follower,在失联阶段这个老Leader的任何更新都不能算commit,都回滚,接受新的Leader的新的更新。

3.2、数据分片

       分片过程是将全局数据进行逻辑划分和实际物理分配过程。全局数据将分片成各个片段数据,而各个片段将会分配到不同的场地(服务器)上。是一个这样的过程:全局数据库->片段数据库->物理数据库。

       数据分片需要遵循一定的分片原则。在设计分布式数据库的时候,设计者必须考虑数据如何分布在各个场地上,也就是全局数据应该如何进行逻辑划分和物理划分。哪些数据应该分布式存放,哪些不需要分布式存放,哪些数据需要复制。对系统惊醒全盘考虑,使系统性能最优。但是无论如何进行分片都应该遵循以下原则:1、完备性:所有全局数据都要映射到某个片段上。2、可重构性:所有片段必须可以重新构成全局数据。3、不相交性:划分的片段所包含的数据无交集。

       分片有三种方式:水平分片、垂直分片、混合分片。

1、水平分片

       水平分片是将数据按照元组来划分,在关系数据库中也就是根据属性的条件按照行划分,该属性叫做分片属性,条件就是分片条件。又分为:基本水平分片:根据关系表本身的属性分片。导出水平分片:分片属性不是该关系表中的属性。

2、垂直分片

       垂直分片是通过将全局对象在其属性子集上进行投影得到的,垂直分片是把一个关系表按照列来分成片段,各个片段之间除了主键外不能有交集。

3、混合分片

       通过交替水平分片与垂直分片,可以产生混合分片。

3.3、查询优化

       一般来说,在分布式数据库中的查询优化主要考虑以下几种:1. 操作执行的顺序:操作执行顺序的改变主要指关系运算及集合运算的改变,它们常常对铁性能产生重要的影响。2. 关系的存取方法:在关系数据库系统中,关系或使用索引,如果关系中90%的要被访问,则扫描整个关系是较好的;如果只有30%的被访问,则使用索引是更为有效的方法。3. 操作的执行算法(尤其是连接操作):连接操作是将两个关系在指定的公共属性上以相同值为依据进行合并,连接操作通常有多种:自然连接、造价连接、外连接和半连接等。

       分布式数据库数据库查询优化的一般过程:分布式查询处理问题是由E-Wong首先提出的,分布式查询处理的基本思想认为分布式查询处理是数据传递和局部处理相交织的过程,分布式查询处理策略由数据传递策略与局部处理策略组成;分布式查询处理的过程实质是利用数据传递策略和局部数据处理策略,把分布查询转化为局部查询的过程。分布式数据库中的查询过程可分为逻辑分解、评议转换和优化组合几分。分布式数据库系统中,用户可以用全局查询评议对多个数据库同时进行查询,即为全局查询。全局查询一般经过以下几个过程:首先,对全局查询进行逻辑分解成几个子查询,每个子查询对应一个局部数据;其次,若全局查询评议与局部查询评议不同,则进行语言的等价转换;最后,各个子查询的结果优化组合后返回。不同的查询分解对应不同的系统性能,因此为了达到优化系统性能,需要相应查询优化器来确定一个相对较好的执行计划,最后启动查询计划。

       分布式查询处理按不同的层次执行,符合分布式数据库系统的层次结构。分布式查询处理可分为如下所示四个层次结构。

1、查询分解

       查询分解(querydecomposition)是将查询问题(如SQL语句)转换成一个定义在全局关系上的关系代数表达式。这一层的做法与集中式DBMS相同,因为并未涉及分布问题。本层转换所需要信息在全局概念模式中得到。

2、数据本地化

       数据本地化(datalocalization)是把一个在全局关系上的查询进行具体化到合适片段上的查询。这一变换所需要信息在分片模式和片段的分配模式中获得。

3、全局优化

       全局优化((globaloptimization)输入是分片查询,全局优化是找出分片查询的最佳操作次序,包括使得代价函数最小。全局优化一个重要方面是关于连接操作的优化,全局优化处理层输出是一个优化的、片段上的关系代数查询。这层转换所需要信息来自数据库的统计信息,包括各站点片段统计信息、资源信息和通信信息等。

4、局部优化

       局部优化((localoptimization)由与查询有关片段的各个站点执行。它由该站点上的DBMS进行优化,采用集中式数据库系统中查询优化的算法,所需要信息来自于局部模式。分布式查询优化通常在分布式查询层次结构中的数据本地化层和全局优化层。数据本地化阶段一般采用的是基于关系代数等价变换的优化算法。而全局优化阶段采用的算法,可具体分为基于半连接算法的查询优化和基于直接连接算法的查询优化两大类。

3.4、事务管理

       分布式事务必须满足传统事务的特性,即原子性,一致性,分离性和持久性。但是分布式事务处理过程中,某些场地(Server)可能发生故障,或 者由于网络发生故障而无法访问到某些场地。为了防止分布式系统部分失败时产生数据的不一致性。在分布式事务的控制中采用了两阶段提交协议(Two- Phase Commit Protocol)。即事务的提交分为两个阶段:预提交阶段(Pre-Commit Phase)、决策后阶段(Post-Decision Phase)。

       两阶段提交用来协调参与一个更新中的多个服务器的活动,以防止分布式系统部分失败时产生数据的不一致性。例如,如果一个更新操作要求位于三个不同结点上的记录被改变,且其中只要有一个结点失败,另外两个结点必须检测到这个失败并取消它们所做的改变。  为了支持两阶段提交,一个分布式更新事务中涉及到的服务器必须能够相互通信。一般来说一个服务器会被指定为"控制"或"提交"服务器并监控来自其它服务器的信息。

       在一个分布式事务中,必须有一个场地的Server作为协调者(coordinator),它能向 其它场地的Server发出请求,并对它们的回答作出响应,由它来控制一个分布式事务的提交或撤消。该分布式事务中涉及到的其它场地的Server称为参 与者(Participant)。事务两阶段提交的过程如下:

       Step1、两阶段提交在应用程序向协调者发出一个提交命令时被启动。这时提交进入第一阶段,即预提交阶段。在这一阶段中:(1) 协调者准备局部(即在本地)提交并在日志中写入"预提交"日志项,并包含有该事务的所有参与者的名字。(2) 协调者询问参与者能否提交该事务。一个参与者可能由于多种原因不能提交。例如,该Server提供的约束条件(Constraints)的延迟检查不符合 限制条件时,不能提交;参与者本身的Server进程或硬件发生故障,不能提交;或者协调者访问不到某参与者(网络故障),这时协调者都认为是收到了一个 否定的回答。(3) 如果参与者能够提交,则在其本身的日志中写入"准备提交"日志项,该日志项立即写入硬盘,然后给协调者发回一,已准备好提交"的回答。(4) 协调者等待所有参与者的回答,如果有参与者发回否定的回答,则协调者撤消该事务并给所有参与者发出一个"撤消该事务"的消息,结束该分布式事务,撤消该事务的所有影响。

       Step2、如果所有的参与者都送回"已准备好提交"的消息,则该事务的提交进入第二阶段,即决策后提交阶段。在这一阶段中:(1) 协调者在日志中写入"提交"日志项,并立即写入硬盘。(2) 协调者向参与者发出"提交该事务"的命令。各参与者接到该命令后,在各自的日志中写入"提交"日志项,并立即写入硬盘。然后送回"已提交"的消息,释放该事务占用的资源。 (3) 当所有的参与者都送回"已提交"的消息后,协调者在日志中写入"事务提交完成"日志项,释放协调者占用的资源 。这样,完成了该分布式事务的提交。

3.5、并发控制

       解决分布式数据库系统的并发问题的常用方式是封锁。封锁就是事务T在对某数据对象(例如:表、记录)操作之前,先向系统发出请求,对其加锁。加锁后事务T就对数据对象有了一定的控制,在事务T释放它的锁之前,其他的事务不能更新此数据对象。事务的同步化是通过对数据库的片断或者数据项进行物理或逻辑封锁来实现的。其中,封锁对象的大小通常称为封锁粒度。封锁方法的类型可以根据在哪里进行封锁来进一步细分:集中式封锁方法,一个站点被指定为主站点,存放对整个数据库的封锁表,并且负责对全系统事务进行封锁;主副本封锁法,主副本所在站点封锁;分布式封锁法,网络中的站点共享锁的管理、

       不同的锁有不同的控制功能,即一个事务对数据对象加锁后可有怎样的控制由它的封锁类型决定。锁有以下三种类型:

       1、排他锁(简称X锁,或写锁):若事务T对数据对象A加上X锁,则只允许T读取和修改A,其他任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。排它锁保证其他事务在事务T释放数据对象A上的锁之前不能在读和修改A。

       2、共享锁(简称S锁,或读锁):若事务T对数据对象A加上S锁,则其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。共享锁保证其他事务可以读数据对象A,但在事务T释放A上的S锁之前不能对A做任何修改。

       3、更新锁(U锁)

       锁的操作有三种:Read_lock(x):读锁。Write_lock(x):写锁。unlock(x):解锁。数据项的状态有两种:read_locked: 读锁。Write_locked:写锁。具体操作方法是:首先,在系统锁表中记录关于锁的信息,锁表中每条记录有四个字段:<数据项名称,锁状态,读锁的数目,正在封锁该数据项的事务>,锁状态是上面两种,没有被封锁的数据项,在系统表中没有记录。封锁通常具有3 个环节:第一个环节是申请加锁,即事务在操作前要对它将使用的数据提出加锁申请; 第二个环节是获得锁,即当条件成熟时,系统允许事务对数据进行加锁,从而事务获得数据的控制权;第三个环节是释放锁,即完成操作后事务放弃数据的控制权。

       对封锁方式规定不同的规则,就形成了各种不同的封锁协议。下面介绍三级封锁协议。三级封锁协议分别在不同程度上解决了丢失的修改、不可重复读和读"脏"数据等不一致性问题,为并发操作的正确调度提供一定的保证。其中,1 级封锁协议是:事务T在修改数据R之前必须先对其加X锁,直到事务结束才释放。事务结束包括正常结束(COMMIT)和非正常结束(ROLLBACK)。 1级封锁协议可防止丢失修改,并保证事务T是可恢复的。在1级封锁协议中,如果仅仅是读数据不对其进行修改,是不需要加锁的,所以它不能保证可重复读和不读"脏"数据。 2级封锁协议是:1级封锁协议加上事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。2级封锁协议除防止了丢失修改,还可进一步防止读"脏"数据。 3级封锁协议是:1级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。3级封锁协议除防止了丢失修改和不读'脏'数据外,还进一步防止了不可重复读。

四、   DDBS中间件MyCat分析

4.1、Mycat简介

       Mycat是一个开源的分布式数据库系统,是一个实现了MySQL协议的的Server,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生(Native)协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里。它的后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储。而在最终用户看来,无论是那种存储方式,在Mycat里,都是一个传统的数据库表,支持标准的SQL语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度。

       Mycat是一个强大的数据库中间件,不仅仅可以用作读写分离、以及分表分库、容灾备份,而且可以用于多租户应用开发、云平台基础设施、让你的架构具备很强的适应性和灵活性,借助于即将发布的Mycat智能优化模块,系统的数据访问瓶颈和热点一目了然,根据这些统计分析数据,你可以自动或手工调整后端存储,将不同的表映射到不同存储引擎上,而整个应用的代码一行也不用改变。

       Mycat与MySQL的关系可看作是上层看作是对下层的抽象,例如操作系统是对各类计算机硬件的抽象。那么我们什么时候需要抽象?假如只有一种硬件的时候,我们需要开发一个操作系统吗?再比如一个项目只需要一个人完成的时候不需要leader,但是当需要几十人完成时,就应该有一个管理者,发挥沟通协调等作用,而这个管理者对于他的上层来说就是对项目组的抽象。同样的,当我们的应用只需要一台数据库服务器的时候我们并不需要Mycat,而如果你需要分库甚至分表,这时候应用要面对很多个数据库的时候,这个时候就需要对数据库层做一个抽象,来管理这些数据库,而最上面的应用只需要面对一个数据库层的抽象或者说数据库中间件就好了,这就是Mycat的核心作用。所以可以这样理解:数据库是对底层存储文件的抽象,而Mycat是对数据库的抽象。

4.2、MyCat功能

       mycat在一个应用系统中承担着应用层与数据层之间的中间层角色。结合项目按照自己对mycat的理解,它强大的地方在于:

       1、连接过多问题,可以通过MyCat统一管理所有的数据源,后端数据库集群对前端应用程序透明。支持事务、ACID、可以替代MySQL的加强版数据库。

       2、独创的ER关系分片,解决E-R分片难处理问题。

       3、采用全局分片技术,每个节点同时并发插入和更新数据,每个节点都可以读取数据。

       4、通过人工智能的catlet支持跨分片复杂SQL实现以及存储过程支持等。

4.3、Mycat结构

       Mycat的具体设计构架如下图。

       总体上分成三个部分,最前端的是连接器,线程管理使用了资源池,并且默认采用了AIO的方式,这些基本信息可以再启动日志里面看到;中间层采用SQL解析器+SQL路由,SQL Executor需要具体看源码才能了解,通过这段时间对MyCAT的测试,感不觉到SQL Executor的存在,更多的感觉是一个SQL process的东西;DataNode和心跳检测算是中间层实现的两个组件,一个是和MySQL的库(不是实例)相关,一个是常见的监测机制的功能模块;最下层的存储就是是MySQL的集群了,而具体如何设计MySQL的集群,由使用者决定。

4.4、Mycat原理简析

       Mycat的原理中最重要的一个动词可以用“拦截”高度概括:它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户。

       Orders表被分为三个分片datanode(简称dn),这三个分片是分布在两台MySQL Server上(DataHost),即datanode=database@datahost方式,因此你可以用一台到N台服务器来分片,分片规则为(sharding rule)典型的字符串枚举分片规则,一个规则的定义是分片字段(shardingcolumn)+分片函数(rule function),这里的分片字段为prov而分片函数为字符串枚举方式。

       当Mycat收到一个SQL时,会先解析这个SQL,查找涉及到的表,然后看此表的定义,如果有分片规则,则获取到SQL里分片字段的值,并匹配分片函数,得到该SQL对应的分片列表,然后将SQL发往这些分片去执行,最后收集和处理所有分片返回的结果数据,并输出到客户端。以select* from Orders where prov=?语句为例,查到prov=wuhan,按照分片函数,wuhan返回dn1,于是SQL就发给了MySQL1,去取DB1上的查询结果,并返回给用户。

       如果上述SQL改为select * from Orders where prov in (‘wuhan’,‘beijing’),那么,SQL就会发给MySQL1与MySQL2去执行,然后结果集合并后输出给用户。但通常业务中我们的SQL会有Order By 以及Limit翻页语法,此时就涉及到结果集在Mycat端的二次处理,这部分的代码也比较复杂,而最复杂的则属两个表的Jion问题,为此,Mycat提出了创新性的ER分片、全局表、HBT(Human Brain Tech)人工智能的Catlet、以及结合Storm/Spark引擎等十八般武艺的解决办法,从而成为目前业界最强大的方案。




<ending>

转载注明出处:Scofield's blog[  http://blog.csdn.net/scotfield_msn/article/details/60344796  ]


references:

****









猜你喜欢

转载自blog.csdn.net/Scotfield_msn/article/details/60344796
今日推荐