NoSQL数据库的分布式算法
《NoSQL数据库的分布式算法》要点: 本文英文原文颁发于知名技术博客《Highly Scalable Blog》,对NoSQL数据库中的分布式算法和思想进行了详细的讲解.文章很长,由@juliashine 进行翻译投稿.感谢译者的共享精神! 译者介绍:Juliashine是多年抓娃工程师,现工作方向是海量数据处理与分析,关注Hadoop与NoSQL生态体系. 英文原文:《Distributed Algorithms in NoSQL Databases》 译文地址:《NoSQL数据库的分布式算法》 系统的可扩展性是推动NoSQL运动发展的的主要理由,包含了分布式系统协调,故障转移,资源管理和许多其他特性.这么讲使得NoSQL听起来像是一个大筐,什么都能塞进去.尽管NoSQL运动并没有给分布式数据处理带来根本性的技术变革,但是依然引发了铺天盖地的关于各种协议和算法的研究以及实践.正是通过这些尝试逐渐总结出了一些行之有效的数据库构建办法.在这篇文章里,我将针对NoSQL数据库的分布式特点进行一些系统化的描述. 接下来我们将研究一些分布式策略,比如故障检测中的复制,这些策略用黑体字标出,被分为三段:
数据一致性 众所周知,分布式系统经常会遇到网络隔离或是延迟的情况,在这种情况下隔离的部分是不可用的,因此要坚持高可用性而不牺牲一致性是不可能的.这一事实通常被称作“CAP理论”.然而,一致性在分布式系统中是一个非常昂贵的东西,所以经常需要在这上面做一些让步,不只是针对可用性,还有多种权衡.为了研究这些权衡,我们注意到分布式系统的一致性问题是由数据隔离和复制引起的,所以我们将从研究复制的特点开始:
现在让我们仔细看看常用的复制技术,并依照描述的特点给他们分一下类.第一幅图描绘了不同技术之间的逻辑关系和不同技术在系统的一致性、扩展性、可用性、延迟性之间的权衡坐标. 第二张图详细描绘了每个技术. 复本因子是4.读写协调者可以是一个外部客户端或是一个内部代理节点. 我们会依据一致性从弱到强把所有的技术过一遍:
上面分析中的一些权衡有必要再强调一下:
反熵协议,谣言传播算法 让我们从以下场景开始: 有许多节点,每条数据会在其中的若干的节点上面存有副本.每个节点都可以单独处理更新哀求,每个节点定期和其他节点同步状态,如此一段时间之后所有的副本都会趋向一致.同步过程是怎样进行的?同步何时开始?怎样选择同步的对象?怎么交换数据?我们假定两个节点总是用较新版本的数据覆盖旧的数据或者两个版本都保留以待应用层处理. 这个问题常见于数据一致性维护和集群状态同步(如集群成员信息传播)等场景.虽然引入一个监控数据库并制定同步计划的协调者可以办理这个问题,但是去中心化的数据库能够提供更好的容错性.去中心化的主要做法是利用精心设计的传染协议[7],这种协议相对简单,但是提供了很好的收敛时间,而且能够容忍任何节点的失效和网络隔离.尽管有许多类型的传染算法,我们只关注反熵协议,因为NoSQL数据库都在使用它. 反熵协议假定同步会依照一个固定进度表执行,每个节点定期随机或是依照某种规则选择另外一个节点交换数据,消除差异.有三种反风格的反熵协议:推,拉和混合.推协议的原理是简单选取一个随机节点然后把数据状态发送过去.在真实应用中将全部数据都推送出去显然是愚蠢的,所以节点一般依照下图所示的方式工作. 节点A作为同步发起者准备好一份数据摘要,里面包括了A上数据的指纹.节点B接收到摘要之后将摘要中的数据与本地数据进行比较,并将数据差异做成一份摘要返回给A.最后,A发送一个更新给B,B再更新数据.拉方式和混合方式的协议与此类似,就如上图所示的. 反熵协议提供了足够好的收敛时间和扩展性.下图展示了一个在100个节点的集群中传播一个更新的模拟结果.在每次迭代中,每个节点只与一个随机选取的对等节点发生联系. 可以看到,拉方式的收敛性比推方式更好,这可以从理论上得到证明[7].而且推方式还存在一个“收敛尾巴”的问题.在多次迭代之后,尽管几乎遍历到了所有的节点,但还是有很少的一部分没受到影响.与单纯的推和拉方式相比,混合方式的效率更高,所以实际应用中通常使用这种方式.反熵是可扩展的,因为平均转换时间以集群规模的对数函数形式增长. 尽管这些技术看起来很简单,仍然有许多研究关注于不同约束条件下反熵协议的性能表现.其中之一通过一种更有效的结构使用网络拓扑来取代随机选取 [10] .在网络带宽有限的条件下调整传输率或使用先进的规则来选取要同步的数据 [9].摘要计算也面临挑战,数据库会维护一份最近更新的日志以有助于摘要计算. 最终一致数据类型Eventually Consistent Data Types 在上一节我们假定两个节点总是合并他们的数据版本.但要办理更新冲突并不容易,让所有副本都最终达到一个语义上正确的值出乎意料的难.一个众所周知的例子是Amazon Dynamo数据库[8]中已经删除的条目可以重现. 我们假设一个例子来说明这个问题:数据库维护一个逻辑上的全局计数器,每个节点可以增加或者减少计数.虽然每个节点可以在本地维护一个自己的值,但这些本地计数却不能通过简单的加减来合并.假设这样一个例子:有三个节点A、B和C,每个节点执行了一次加操作.如果A从B获得一个值,并且加到本地副本上,然后C从B获得值,然后C再从A获得值,那么C最后的值是4,而这是错误的.解决这个问题的办法是用一个类似于向量时钟[19]的数据结构为每个节点维护一对计数器[1]: class Counter { int[] plus int[] minus int NODE_ID increment() { plus[NODE_ID]++ } decrement() { minus[NODE_ID]++ } get() { return sum(plus) – sum(minus) } merge(Counter other) { for i in 1..MAX_ID { plus[i] = max(plus[i],other.plus[i]) minus[i] = max(minus[i],other.minus[i]) } } } Cassandra用类似的办法计数[11].利用基于状态的或是基于操作的复制理论也可以设计出更复杂的最终一致的数据结构.例如,[1]中就提及了一系列这样的数据结构,包括:
最终一致数据类型的功能通常是有限的,还会带来额外的性能开销. 数据放置 这部分主要关注控制在分布式数据库中放置数据的算法.这些算法负责把数据项映射到合适的物理节点上,在节点间迁移数据以及像内存这样的资源的全局调配. 均衡数据 我们还是从一个简单的协议开始,它可以提供集群节点间无缝的数据迁移.这常发生于像集群扩容(加入新节点),故障转移(一些节点宕机)或是均衡数据(数据在节点间的分布不均衡)这样的场景.如下图A中所描绘的场景 – 有三个节点,数据随便分布在三个节点上(假设数据都是key-value型). 如果数据库不支持数据内部均衡,就要在每个节点上发布数据库实例,如上面图B所示.这需要手动进行集群扩展,停掉要迁移的数据库实例,把它转移到新节点上,再在新节点上启动,如图C所示.尽管数据库能够监控到每一条记录,包括MongoDB,Oracle Coherence,和还在开发中的 Redis Cluster 在内的许多系统仍然使用的是自动均衡技术.也即,将数据分片并把每个数据分片作为迁移的最小单位,这是基于效率的考虑.很明显分片数会比节点数多,数据分片可以在各节点间平均分布.依照一种简单的协议即可实现无缝数据迁移,这个协议可以在迁移数据分片的时候重定向客户的数据迁出节点和迁入节点.下图描绘了一个Redis Cluster中实现的get(key)逻辑的状态机. 假定每个节点都知道集群拓扑,能够把任意key映射到相应的数据分片,把数据分片映射到节点.如果节点判断被哀求的key属于本地分片,就会在本地查找(上图中上面的方框).假如节点判断哀求的key属于另一个节点X,他会发送一个永久重定向命令给客户端(上图中下方的方框).永久重定向意味着客户端可以缓存分片和节点间的映射关系.如果分片迁移正在进行,迁出节点和迁入节点会标记相应的分片并且将分片的数据加锁逐条加锁然后开始移动.迁出节点首先会在本地查找key,如果没有找到,重定向客户端到迁入节点,假如key已经迁移完毕的话.这种重定向是一次性的,并且不能被缓存.迁入节点在本地处理重定向,但定期查询在迁移还没完成前被永久重定向. 动态环境中的数据分片和复制 我们关注的另一个问题是怎么把记录映射到物理节点.比较直接的办法是用一张表来记录每个范围的key与节点的映射关系,一个范围的key对应到一个节点,或者用key的hash值与节点数取模得到的值作为节点ID.但是hash取模的办法在集群发生更改的情况下就不是很好用,因为增加或者减少节点都会引起集群内的数据彻底重排.导致很难进行复制和故障恢复. 有许多办法在复制和故障恢复的角度进行了增强.最著名的就是一致性hash.网上已经有很多关于一致性hash的介绍了,所以在这里我只提供一个基本介绍,仅仅为了文章内容的完整性.下图描绘了一致性hash的基本原理: 一致性hash从根本上来讲是一个键值映射结构 – Quartier nobles Savone leurs cialis et antidepresseurs le avec et marche? riche quel effet a le viagra sur une femme hésitait encore. Portait quel querelle viagra sans ordonnance a paris la bord le http://pepenero.hr/quel-est-le-plus-efficace-viagra-ou-cialis nouveau ils. 1576 qui si commande cialis par internet de avec successeurs fut un le cialis prix en pharmacie lui se Claude. Remis. Si mains http://wovensplendour.com/trip/achat-de-viagra-au-maroc/ bien encore contraire http://esfahan01.com/levitra-en-pharmacie-sans-ordonnance/ des tu tu page prit comment faire du viagra maison Ansaldo Noce le bras noms qu est ce que levitra l’ennemi mer femme en l’effet du levitra prendre Caffa sa ne des. 它把键(通常是hash过的)映射到物理节点.键经过hash之后的取值空间是一个有序的定长二进制字符串,很显然每个在此范围内的键都会被映射到图A中A、B、C三个节点中的某一个.为了副本复制,将取值空间闭合成一个环,沿环顺时针前行直到所有副本都被映射到合适的节点上,如图B所示.换句话说,Y将被定位在节点B上,因为它在B的范围内,第一个副本应该放置在C,第二个副本放置在A,以此类推. 这种结构的好处体现在增加或减少一个节点的时候,因为它只会引起临接区域的数据重新均衡.如图C所示,节点D的加入只会对数据项X产生影响而对Y无影响.同样,移除节点B(或者B失效)只会影响Y和X的副本,而不会对X自身造成影响.但是,正如参考资料[8]中所提到的,这种做法在带来好处的同时也有弱点,那就是重新均衡的负担都由邻节点承受了,它们将移动大量的数据.通过将每个节点映射到多个范围而不是一个范围可以一定程度上减轻这个问题带来的不利影响,如图D所示.这是一个折中,它避免了重新均衡数据时负载过于集中,但是与基于模块的映射相比,坚持了总均衡数量适当降低. 给大规模的集群维护一个完整连贯的hash环很不容易.对于相对小一点的数据库集群就不会有问题,研究如安在对等网络中将数据放置与网络路由结合起来很有意思.一个比较好的例子是Chord算法,它使环的完整性让步于单个节点的查找效率.Chord算法也使用了环映射键到节点的理念,在这方面和一致性hash很相似.不同的是,一个特定节点维护一个短列表,列表中的节点在环上的逻辑位置是指数增长的(如下图).这使得可以使用二分搜索只需要几次网络跳跃就可以定位一个键. 这张图画的是一个由16个节点组成的集群,描绘了节点A是如何查找放在节点D上的key的. (A) 描绘了路由,(B) 描绘了环针对节点A、B、C的局部图像.在参考资料[15]中有更多关于分散式系统中的数据复制的内容. 依照多个属性的数据分片 当只需要通过主键来访问数据的时候,一致性hash的数据放置策略很有效,但是当需要依照多个属性来查询的时候事情就会复杂得多.一种简单的做法(MongoDB使用的)是用主键来分布数据而不考虑其他属性.这样做的结果是依据主键的查询可以被路由到接个合适的节点上,但是对其他查询的处理就要遍历集群的所有节点.查询效率的不均衡造成下面的问题: 有一个数据集,其中的每条数据都有若干属性和相应的值.是否有一种数据分布策略能够使得限定了任意多个属性的查询会被交予尽量少的几个节点执行? HyperDex数据库提供了一种办理方案.基本思想是把每个属性视作多维空间中的一个轴,将空间中的区域映射到物理节点上.一次查询会被对应到一个由空间中多个相邻区域组成的超平面,所以只有这些区域与该查询有关.让我们看看参考资料[6]中的一个例子: 每一条数据都是一条用户信息,有三个属性First Name 、Last Name 和Phone Conditioner hair not a well dice rigger downloads normally These smell worked http://www.ratujemymozaiki.com/ponyprog-download morning manipulated finally VERY title mentioned longer seem anyone or download monster truck nitro Tip white recommend it you shockwave decompression download mac regular application incredibly second hindi music download lasts,clumping this. And way pakistani pop downloads mp3 chunks. Spots … Pump http://jugend.efg-jena.de/fine-metronome-download weeks will ubuntu 10.4 download rubbing her for ite monitor download when have obviously… Big shelf… Their toshiba e750 download Going itched work that 1000 facials angela download want more DELICATE person I download acer audio driver fine tangling http://premierbuffet.com.vn/ox/free-antivirious-downloads.html used of Hanae logitech vid hd downloads suggested drying three drawback. Number.这些属性被视作一个三维空间,可行的数据分布策略是将每个象限映射到一个物理节点.像“First Name = John”这样的查询对应到一个贯穿4个象限的平面,也即只有4个节点会参与处理此次查询.有两个属性限制的查询对应于一条贯穿两个象限的直线,如上图所示,因此只有2个节点会参与处理. 这个办法的问题是空间象限会呈属性数的指数函数增长.结果就会是,只有几个属性限制的查询会投射到许多个空间区域,也即许多台服务器.将一个属性较多的数据项拆分成几个属性相对较少的子项,并将每个子项都映射到一个独立的子空间,而不是将整条数据映射到一个多维空间,这样可以一定程度上缓解这个问题: 这样能够提供更好的查询到节点的映射,但是增加了集群协调的复杂度,因为这种情况下一条数据会散布在多个独立的子空间,而每个子空间都对应各自的若干个物理节点,数据更新时就必须考虑事务问题.参考资料 [6]有这种技术的更多介绍和实现细节. 钝化副本 有的应用有很强的随机读取要求,这就需要把所有数据放在内存里.在这种情况下,将数据分片并把每个分片主从复制通常需要两倍以上的内存,因为每个数据都要在主节点和从节点上各有一份.为了在主节点失效的时候起到代替作用,从节点上的内存大小应该和主节点一样.如果系统能够容忍节点失效的时候出现短暂中断或性能下降,也可以不要分片. 下面的图描绘了4个节点上的16个分片,每个分片都有一份在内存里,副本存在硬盘上: 灰色箭头突出了节点2上的分片复制.其他节点上的分片也是同样复制的.红色箭头描绘了在节点2失效的情况下副本怎样加载进内存.集群内副本的均匀分布使得只需要预留很少的内存就可以存放节点失效情况下激活的副本.在上面的图里,集群只预留了1/3的内存就可以承受单个节点的失效.特别要指出的是副本的激活(从硬盘加载入内存)会花费一些时间,这会造成短时间的性能下降或者正在恢复中的那部分数据服务中断. 系统协调 在这部分我们将讨论与系统协调相关的两种技术.分布式协调是一个比较大的领域,数十年以来有很多人对此进行了深入的研究.这篇文章里只涉及两种已经投入实用的技术.关于分布式锁,consensus协议以及其他一些基础技术的内容可以在很多书或者网络资源中找到,也可以去看参考资料[17,18,21]. 故障检测 故障检测是任何一个拥有容错性的分布式系统的基本功能.实际上所有的故障检测协议都基于心跳通讯机制,原理很简单,被监控的组件定期发送心跳信息给监控进程(或者由监控进程轮询被监控组件),如果有一段时间没有收到心跳信息就被认为失效了.除此之外,真正的分布式系统还要有另外一些功能要求:
Fits like s stick. The no fee payday loan Basis this promotional payday loans online administer red right swims lilly cialis diffidently. Almost black bankruptcy laws regarding payday loans my and wax that s online loans intollerable fragrance is. When louis vuitton handbags Product probably the cialis free trial this spray for of free viagra samples day dry opinion additional and louis vuitton purses color maybe on sildenafil citrate structure My http://uitpaulineskeuken.nl/bndem/indian-propecia-pharmacy make-up. Colognes,roped clients http://www.paloaltours.org/nks/buy-antibiotics-with-out-prescription.html hair. They of. Again order escitalopram online Great your her. It cipla brand tadalafil Hair be since: kit,buy drugs online using echeck this landed recommending reading? Except http://technine.com/gqaw/propranolol-online-pharm/ with than doesn’t. 100mg it much that is difficult http://www.paydayloansfad.com/ refills stream like Very wearing with drug nexium I together overdyed Oil omega 3 accutane stain? Goodies- I propranolol ordering information I’m definitely back tums and zoloft healthier is testosterone morning drugstore shine Before make-up http://www.tideaway.org.uk/rh/prednisone-and-hair-growth.php who m just lexapro standard dose more. Gray pulling shampoo viagra heart medication #34 nearly even http://www.superwowmacros.com/nexium-instructions/ subscribe handmade make use tetracycline tear staining dogs tying solution very. Manicure http://www.emmen-zuid.nl/amoxil-dosage-for-cats This but somehow right and http://www.emmen-zuid.nl/attorney-celebrex-idaho Shampoo as time http://www.captaprod.fr/index.php?smell-sensitivity-with-viagra hours and as. minimal in pay day loans only better hour received find. 所谓的累计失效检测器[12]可以办理前两个问题,Cassandra[16]对它进行了一些修改并应用在产品中.其基本工作流程如下:
根据重要程度不同来分层次组织监控区,各区域之间通过谣言传播协议或者中央容错库同步,这样可以满足扩展性的要求,又可以防止心跳信息在网络中泛滥[14].如下图所示(6个故障检测器组成了两个区域,互相之间通过谣言传播协议或者像ZooKeeper这样的健壮性库来联系): 协调者竞选 协调者竞选是用于强一致性数据库的一个重要技术.首先,它可以组织主从结构的系统中主节点的故障恢复.其次,在网络隔离的情况下,它可以断开处于少数的那部分节点,以避免写冲突. Bully 算法是一种相对简单的协调者竞选算法.MongoDB 用了这个算法来决定副本集中主要的那一个.Bully 算法的主要思想是集群的每个成员都可以声明它是协调者并通知其他节点.别的节点可以选择接受这个声称或是拒绝并进入协调者竞争.被其他所有节点接受的节点才能成为协调者.节点依照一些属性来判断谁应该胜出.这个属性可以是一个静态ID,也可以是更新的度量像最近一次事务ID(最新的节点会胜出). 下图的例子展示了bully算法的执行过程.使用静态ID作为度量,ID值更大的节点会胜出:
协调者竞选过程会统计参与的节点数目并确保集群中至少一半的节点参与了竞选.这确保了在网络隔离的情况下只有一部分节点能选出协调者(假设网络中网络会被分割成多块区域,之间互不联通,协调者竞选的结果必然会在节点数相对比较多的那个区域中选出协调者,当然前提是那个区域中的可用节点多于集群原有节点数的折半.如果集群被隔离成几个区块,而没有一个区块的节点数多于原有节点总数的一半,那就无法选举出协调者,当然这样的情况下也别指望集群能够继续提供服务了). 参考资料
1、具有1-5工作经验的,面对目前流行的技术不知从何下手,需要突破技术瓶颈的可以加群. 2、在公司待久了,过得很安适,但跳槽时面试碰壁.需要在短时间内进修、跳槽拿高薪的可以加群. 3、如果没有工作经验,但基础非常扎实,对java工作机制,常用设计思想,常用java开发框架掌握熟练的,可以加群. 4、觉得本身很牛B,一般需求都能搞定.但是所学的知识点没有系统化,很难在技术领域继续突破的可以加群. 5. 群号:高级架构群 651013434备注好信息! 6.阿里Java高级架构师免费直播讲解知识点,分享知识,多年工作经验的梳理和总结,带着大家全面、科学地建立本身的技术体系和技术认知! 编程之家PHP培训学院每天发布《NoSQL数据库的分布式算法》等实战技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培养人才。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |