微信技能团队最近在开源开放上动作不断,后端方面前段韶光他们开源了生产级paxos类库PhxPaxos,现在又开源了高可用分布式数据库PhxSQL,本文我们将理解一些PhxSQL背后的故事,以及它设计和实现的哲学。
老司机简介
陈明,PhxSQL卖力人。2012年加入微信,先后卖力微信、朋友圈、账号、关系链、环球分布式支配、PhxSQL等项目,见证了微信后台根本架构支持从一亿用户到八亿用户、从单点到环球分布、从粗放到追赶和超越的历史过程。
在加入微信之前,陈明在搜搜从事搜索架构培植和在微软亚洲研究院研究分布式架构及存储。陈明从清华大学打算机系得到博士学位,研究方向是分布式系统。
PhxSQL开源地址见:
https://github.com/tencent-wechat/phxsql
为何研发PhxSQL?
PhxSQL是一个兼容MySQL、做事高可用、数据强同等的关系型数据库集群。PhxSQL以单Master多Slave办法支配,在集群内超过一半机器存活的情形下、即可供应做事,并且自身实现自动Master切换、担保数据同等性。PhxSQL不依赖于Zookeeper等任何第三方做存活检测及选主。PhxSQL基于MySQL的一个分支Percona 5.6开拓,功能和实现与MySQL基本同等。
PhxSQL可以供应和zookeeper相同的强同等性与高可用性,并且支持serializable级别的事务隔离。
陈明表示,微信研发PhxSQL是为理解决在运用MySQL时一个普遍且巨大的痛点:强同等和高可用,MySQL不支持PhxSQL面向的分布式环境下强同等和高可用运用处景,而这在金融和账号类关键运用是必须的。据他们所知,目前还未有类似的公开方案,因此,只能自己研发。
后面的正文里面,也会详细的谈论MySQL在分布式环境下的痛点。
PhxSQL目前运用在微信后台的账号系统、企业微信、及QQ邮箱。个中一个关键做事的集群由5台做事器构成一个组,容忍两机同时故障,写高峰2000/秒,读高峰60000/秒。
性能与架构迁移
在他们的基准测试中,PhxSQL相对付MySQL的写性能有16-25%的提升,读性能持平。详细测试报告拜会 github/phxsql 网址。实际上,PhxSQL的紧张目标是强同等、高可用、和serializable事务隔离;性能只是一个关注点。其余,PhxSQL将很快支持性能更好的5.7版本MySQL。
PhxSQL设计的一个基本原则便是完备兼容MySQL,MySQL客户端不须要任何修正就可以直接访问PhxSQL,以便于将现有的。但是由于MySQL客户端不支持做事器故障时连接到新的可用节点,他们供应了多种可选方案。
PhxSQLProxy可以将客户端要求转发给可用节点。
PhxSQL client lib支持自动切换做事器,原有运用程序只要在源码中创建连接时传入PhxSQL做事器IP列表、链接时将MySQL client lib换成PhxSQL client lib即可。
VIP等方案也可以和PhxSQL合营利用。
有些人可能会把稳到PhxPaxos和PhxSQL都带有前缀Phx,陈明说Phx代表不去世的凤凰,是凤凰英文单词phoenix的缩写。它将用于微信后真个一系列开源项目,后续他们将放出更多的开源项目,敬请期待。
小Q注:以下部分内容由「微信后台团队」授权InfoQ发布,ID:gh_93b1115dc96f
PhxSQL的设计和实现哲学
PhxSQL发布以来,受到很多关注。作为热爱技能的码农,我们感谢大家的关心和支持,欢迎统统基于技能出发点的谈论。“Show you the code”之后,我们在这里谈谈PhxSQL的设计和实现哲学,也同时回答大家提出的一些疑问。
1PhxSQL是什么?
PhxSQL是一个通过Paxos担保强同等和高可用的的MySQL集群。PhxSQL建立在Paxos的同等性和MySQL的binlog流水根本上。紧张事理大略来说:
Paxos选出主机
主机把本机MySQL设置成可写的MySQL主机,在MySQL写binlog流程中拦截binlog流水、发送到Paxos,形玉成局的binlog流水
备机把本机的MySQL设置成只读的MySQL备机,MySQL备机从全局binlog中拉取流水,重放和实行,从而主备MySQL同等
针对常见的业务场景,PhxSQL供应两个做事端口:强同等读写端口(ReadWritePort)和只读端口(ReadonlyPort);对数据哀求强同等的业务,通过ReadWritePort来读写;只哀求能读取但不哀求最新数据的读要求(比如一些定时对账业务),可以通过ReadonlyPort来读取
只要有多于一半机器事情和互联,PhxSQL就可以正常事情。
图 1:PhxSQL架构
2“强同等”和“高可用”是什么级别?
很多MySQL集群方案都流传宣传强同等和高可用。PhxSQL这方面有什么不同?
大家熟知的Zookeeper供应强同等和高可用。同等性有很多级别,从强到弱分别是:Strict(严格同等性),Linearizable(线性同等性),Sequential(序列同等性),Causal(因果同等性),Eventual等。
严格同等性只是一个理论模型。根据相对论,由于信息传播的速率不可能高于光速,严格同等性在实际中险些无法实现。线性同等性的理论定义很繁芜,不太严谨直不雅观地讲,便是任何一个客户端都可以读到别的客户端写入的最新内容。这也是大家常日理解的强同等。
Zookeeper的强同等指“线性同等性”。高可用是说只要多于一半机器事情和互联即可在担保线性同等性的质量下正常事情。PhxSQL的强同等是指“线性同等性”,高可用是指只要多于一半机器事情和互联即可在担保线性同等性子量下事情。即,
PhxSQL供应和Zookeeper相同的强同等性和高可用性!
主要事情说三遍:)。大家可以把PhxSQL当Zookeeper利用,例如用来选主!
在数据库事务隔离方面,PhxSQL支持最高级别的serializable。在性能方面,PhxSQL供应明显优于MySQL半同步的写性能和险些相同的读性能[22]。
细心的读者可能把稳到,和常日的“高可用、强同等”说法顺序相反,这个小节的标题中,“强同等”故意放在了“高可用”的前面。在这里须要澄清一个误区。当谈到高可用时,有时会故意无意忽略或者降落同等性。
严格意义上来讲,可用性和同等性必须一块谈论,知足同等性哀求条件下的可用性才故意义。打个不严谨的比方,同等性就像汽车的“安全性”,可用性便是汽车的“可用性”。如果一辆车号称“可用性”很好,可以连续事情10年,但从来不提“安全性”,那么这辆车的品质是值得疑惑的。
3为什么要做PhxSQL?
虽然有很多NoSQL、NewSQL系统、以及多主多写MySQL集群、支持分库分表的MySQL集群,MySQL传统主备同步方案仍旧具备很多新系统难以企及的优点。MySQL主备在主机上支持完全SQL、全局事务、以repeatable read和serializable级别的事务隔离,在金融、帐号等关键业务中有巨大的代价。同时,现有繁芜MySQL运用迁移到新的非兼容系统本钱也很高。
但是MySQL传统主备方案也有其缺陷。最明显的便是主机故障后的自动换主和新旧主数据同等性(以及衍生的换主后主备同等性、各个备机之间同等性,这里就不详加谈论了),即所谓的同等性和可用性。
为理解决这个问题,有传统流派:用Zookeeper、etcd、或者其它第三方来检测心跳、选主、和切换。改造MySQL client让其能感知新的主机。或者为了能让传统MySQL client不加修正就能感知新的主机,支配MySQL代理做事器,让其将连到自身的MySQL client要求透明转发给新的主机。
为了减少主备间数据的掉队,从而降落旧主机故障、某台备机被提升成新主机时,新旧主机之间、新主机和其它备机之间的差异,很多方案在主备同步机制上做了很多有益的事情。
例如semi-sync等待多数派备机应答,通过优化线程和网络、主备多通道、备机并行实行binlog流水等只管即便减少主备之间差异。如果主备间任何时候都完备同等,那么任何时候换主都是强同等的。这句话的其余一个意思是,如果无法担保主备间任何时候完备同等,那么当有持续不断的更新时,任何时候的换主都是无法担保强同等的。
传统流派其余一个分支便是将MySQL本地磁盘换成更高可靠性的SAN,当MySQL主机故障时,将SAN挂接到备机上供应做事。而当SAN故障时怎么办?当须要跨机房支配时怎么办?
意识到传统流派的局限性,新出了Galera和MySQL Group Replication等。除了流传宣传供应强同等性和高可用性外,还支持master-master多点写入等诱人新特性。
天下上目前已知的经由理论证明和实际考验的同等性算法屈指可数:两阶段提交two-phase commit (2PC)、Paxos、Raft、Zookeeper Atomic Broadcast (ZAB)、Viewstamped Replication等。2PC虽然可以担保同等性,但在主机故障时无法事情,存在可用性问题。
目前被工业界广泛认可和运用的是Paxos和Raft,2PC一样平常在前两者帮助选主下利用。这里的一个小建议便是:如果一个分布式系统流传宣传支持线性同等性级别的强同等和高可用,请先检讨它利用的同等性算法。如果是新算法,请检讨它的形式化证明或者逻辑证明。
因此,为支持线性同等性和高可用,同时完备兼容MySQL,我们在MySQL的根本上运用Paxos,设计和开拓了PhxSQL。
4PhxSQL的设计原则是什么?
从实际需求出发,除了前述强同等、高可用、完备兼容MySQL这3个明显、必须的设计原则,我们还提出以下3原则。
1、大略可逻辑证明的同等性模型
这可能是明显差异PhxSQL和其它方案的一个特点。一个经由逻辑证明的模型才是可靠的,一个建立在可靠模型根本上的系统也才是可信赖的。PhxSQL同等性模型建立在两个条件上:
Paxos担保同等性。这个大家都可以接管。
各个MySQL的binlog流水同等,则各个MySQL机器之间数据“同等”。这个假设小有争议。例如纵然binlog流水同等,由于不同的binlog格式、备机重放流水的不同配置,也会导致主备之间、不同备机之间的数据产生不同级别的“不同”,例如一条和当前韶光干系的insert操作。
这种不一致有些运用可以容忍,有些则不能。在这里,PhxSQL担保流水同等,而把格式和配置的自由留给运用和DBA根据详细场景确定。在最严格的配置下,binlog同等,则数据同等。
在这两个条件下,PhxSQL的同等性模型通过Paxos,使得主机写入Paxos的binlog流水与备机从Paxos里拉取的binlog流水同等,从而担保MySQL数据的同等性。详细证明过程我们将其余供应。模型和证明过程都很大略,大家在读完源码后也可以考试测验:)。
但纵然模型精确,PhxSQL精确实现了这个模型吗?用普通的话讲,没有bug。码农都知道这是个巨大的寻衅。从一个算法和模型到精确的实现之间差距是巨大的。例如,精确实现Paxos寻衅就很大。为了只管即便减少bug,我们选择了大略和易理解同时运用广泛的Paxos作为同等性协议。
为了实现一个“生产”级别的Paxos,三位紧张码农各自独立实现了Paxos,在各自测试完精确性后,三套Paxos之间作为一组Paxos的独立节点互操作考验精确性,末了再集体实现一个发行版本PhxPaxos!
除了单元测试、系统测试外,测试环境还随机高频率独立重启机器、对网络包进行乱序、延迟、重复等以对系统进行充分测试。
有读者可能问,Paxos慢且网络延迟大,PhxSQL为什么不实现一个“优化”版?Paxos有各种版本,例如Fast Paxos、EPaxos。但这些都是Paxos,遵照Paxos的基本操作,所作的改变,都做了严格的形式化或者逻辑证明。
PhxPaxos严格遵照Paxos算法实现,没有做任何改变或者“优化”。PhxPaxos的正常写操作的网络延迟是一个网络RTT,已经是任何算法理论上能达到的最快速率。
现在,对付PhxSQL来说,切换主机是一件很平常和随意马虎的操作,就像往MySQL里插入一条数据一样平常和随意马虎。
2、最小侵入MySQL原则
MySQL是个巨大的快速演进的生态系统,担保PhxSQL中的MySQL与官方MySQL的兼容性与可升级性是必须的。这使得MySQL运用可以快速迁移到和运行在PhxSQL上。这也使得PhxSQL可以迅速相应官方MySQL的升级,将PhxSQL中的旧版本MySQL升级到新的官方MySQL,从而得到新的特性、性能、稳定性、和安全性提升。
这就哀求PhxSQL中的MySQL对官方MySQL改动只管即便少。实际上,PhxSQL版MySQL只变动了三个小地方:修正了binlog插件接口中一个函数的参数;在MySQL启动时新增了一个插件函数用于检讨MySQL本地的binlog文件,在MySQL协议中透传了真正的客户端IP以兼容授权功能(如果运用不须要可以不修正)。
这几个改动是如此小,且涉及的是险些稳定不变的流程,使得PhxSQL中MySQL跟随官方MySQL升级可以无缝完成。实际上,我们正和MySQL社区沟通,希望把这几处修正并入官方版本,从而使得PhxSQL往后可以完备利用官方版本MySQL,也使得更多人可以方便采取PhxSQL。
(a)
(b)
图 2:PhxSQL对MySQL的关键修正。(a)是MySQL。(b)是PhxSQL中的MySQL。PhxSQL修正了after_flush这个函数的参数,新增了在MySQL启动时调用的before_recovery这个函数。
也正是由于这个缘故原由,我们没有由于可以减少模块个数而把PhxSQLProxy、PhxBinlogSvr放到MySQL进程内。为了担保和运用最广泛的MySQL单机版兼容,也没有在事务层和存储层参与或修正。
3、大略的架构、支配、和运维
在知足哀求的条件下,大略的架构有很多好处,例如开拓、掩护、诊断、掩护、可靠性等等都变得随意马虎。PhxSQL只有3+1个模块。PhxSQL中的MySQL是必须的。PhxBinlogSvr卖力全局binlog存储和同步、选主、集群成员管理等关键功能。
在很多MySQL主备集群方案中,利用Zookeeper、etcd、心跳检测、Agent等承担选主的功能。PhxSQLProxy则作为传统MySQL client访问PhxSQL中MySQL做事的代理,使得PhxSQL的换主操为难刁难于传统MySQL client透明。
在其它集群方案中,一样平常也是通过代理MySQL proxy、或者虚拟网关VIP,向传统MySQL client屏蔽集群的换主操作,供应透明访问。可选模块是PhxSQL client lib,它修正了MySQL client库中的连接初始化函数,许可传入一个集群的PhxSQLProxy列表,从而在一个PhxSQLProxy没有相应时、自动访问其它可用PhxSQLProxy,进一步提高可用性。开拓职员可以直接链接PhxSQL client lib。
PhxSQL的支配和运维都很大略。在支配时,只要在目标机各自装好PhxSQL,在配置中指定集群的机器的IP列表,PhxSQL即可运行。换主这个操作已经从运维层面转移到PhxSQL正常的事情流程。
常日MySQL集群中换主后可能须要人肉检讨数据同等性、人肉“闪回”(这可能违反同等性担保,导致“幻读”);无法”闪回“导致必须打消某台MySQL,重新拉取数据备份,和追流水等。这些耗时、繁重、易错的操作在PhxSQL中已经完备不须要。
至于热升级和热变更集群成员更大略。PhxSQL支持rolling-update,可以逐步升级每台机器。变更集群成员是指往集群添加机器、撤出机器、和更换机器(原子操作)。在担保强同等和高可用条件下,热变更(一直服变更)是非常困难的。
PhxSQL通过在Paxos中实现成员变更办理了这个难题。PhxSQL供应了一个变更操作命令。当在新机器安装和启动PhxSQL后(哀求MySQL已经加载一份较新的数据备份),可以在现有集群中一键将新机器引入、剔除一台旧机器、或者同时做两者。这三种操作都是原子操作!
新机器会自动追流水。想想看,相称于Zookeeper支持热变更成员,是不是很令人激动的特性?
PhxSQL由于在同步层利用Paxos,天然支持多数据中央、多机房支配,两地三中央这种支配更是不在话下。对付PhxSQL来说,多数据中央和多机房支配与机房内支配没有差异。PhxSQL的性能取决于多数派机器之间的网络延迟。
5为什么要开源?
作为热爱技能的码农,我们相信开源的技能可以使得这个天下更美好。从我们日常开拓利用的Emacs/Vim、GCC、GDB,间接为大众供应社交、电子商务、信息做事的Linux、Apache、MySQL、PHP,到大众逐日利用来沟通和娱乐的Android等,开源是全体互联网的基石,为全天下供应许多关键不可或缺的根本做事。我们充分享受了开源带来的技能进步、经济发展、和社会提高,我们也希望开源的PhxSQL可以回馈社区,帮助更多有须要的人。
其余,我们希望通过开源更好地改进PhxSQL。我们欢迎技能性谈论和志愿者提交修正。我们承诺开源的PhxSQL会一贯更新。除了一些和内部运维支撑系统进行集成的功能(PhxSQL把这些功能抽象成插件,我们针对内部运维支撑系统实现了这些插件),开源版和内部版本将保持同等。
6PhxSQL的局限性
在一个不完美的天下里,完美是不存在的。我们很坦诚指出PhxSQL存在的两个局限:
1、MySQL主机在实行SQL DDL命令(例如建库和建表命令)时可能存在同等性风险。
由于MySQL的innodb引擎不支持DDL回滚,如果主机在innodb已经commit这条DDL命令,但是这条命令的binlog还没到达PhxSQL的拦截点前宕机,则这条DDL binlog会在全局binlog中缺失落,从而备机也不会收到这条binlog。
而为了担保线性同等性、serializable级别事务隔离、及“最小侵入MySQL”原则,我们也不想修正MySQL源码,提前截获DDL命令。考虑到DDL命令频度较低,我们后续准备在PhxSQLProxy加入检讨和后续审计告警。也欢迎大家提出更好方案。
2、在写入要求量很大的系统中,MySQL备机流水可能掉队较多;如果这个时候主机去世机,备机暂时无法提升成新主机,造成系统在一段韶光内不可写。
为了担保线性同等性,对付哀求读取最新数据的要求(通过ReadWritePort发起的读要求)也将失落败;须要等至少一台备机追完流水,被提升为主性能力相应读取最新数据的要求。
对付不须要读取最新数据的要求(通过ReadonlyPort发起的要求),可以从任意备机实行,但不担保线性同等性。(把稳:PhxSQL担保无论MySQL主机流水领先MySQL备机多少,MySQL主机binlog流水和全局binlog流水是同等的,不会导致数据丢失和毁坏线性同等性。)
MySQL备机追流水掉队是基于binlog复制这种模式的一个潜在问题。事实上,不仅MySQL主备,任何一个多副本系统,只要每个写操作不等待所有副本返回,都会涌现类似的有些副本掉队的问题;而那些等待所有副本返回的模式,在耗时和可用性方面又存在问题。
可喜的是MySQL 5.7版本实现了并行复制机制,显著地提高了备机追流水的性能。PhxSQL将很快支持MySQL 5.7,对付写入要求量很大的场景也可以很大程度上避免备机追流水掉队的情形。
7Why Not?
1、为什么不支持多写?
多写想想就很诱人。多写可以充分利用每台机器写时须要的资源。例如某些写操作可能非常耗费CPU,多写可以把写操作分散在各台机器上,充分利用各个机器的CPU资源,极大提高写入的性能。多写使得换主没有存在的必要,也就没有换主时可能存在的不可写韶光窗问题。多写还使得客户端可以就近写入,减少跨数据中央写入带来的网络延迟。
多写有两种:大家熟知的分shard或者组,各shard或者组间并行写入,以Google Spanner[8]为范例代表;在shard或者组内并行,以Galera和MySQL Group Replication为代表。
1.组间多写
组间多写是把数据分成多个不相交的shard,每个组的机器卖力一个shard 。当一个事务涉及的数据(读凑集和或写凑集)都在某个组时,这种事务称为本地事务。当一个事务涉及的数据分布在超过一个组时,这种事务称为分布式事务。
本地事务可以在本组独立实行,组之间不须要任何通信。为了减少事务冲突带来的性能降落,一样平常都是由组内leader实行本地事务,通过Paxos等同等性协议担保组内机器的数据同等[8]。各个组间并行实行本地事务,可以极大提高本地型事务的写性能。
组间多写最大的阻碍是分布式事务,而分布式事务是非常昂贵的。在SQL的模型中,为了实现read repeatable级别的事务隔离,事务管理器须要检讨两个并发事务的写数据集是否冲突;为了达到serializable级别的事务隔离,事务管理器须要检讨两个并发事务的读数据集和写事务集是否冲突。
这一样平常通过严格两阶段锁(strict two-phase locking,严格2PL)和/或者多版本并发掌握MVCC实现。当这些数据集跨组时,就涉及到跨组的机器通信。
一个组同时碰着本地事务和分布式事务时,在本组须要根据事务的隔离级别,由事务管理器仲裁实行。
以Google Spanner为例,一个涉及两个机器组(Spanner中的组是指Paxos组)事务就须要在coordinator leader和non-coordinator-participant leader之间两次通信,前者组内还涉及一次Paxos写操作,后者组内再加两次Paxos写操作[8,Sec. 4.2.1 Read-Write Transactions]。
当跨机房支配时,机器之间的网络延迟使得通信代价更加高昂。Spanner为了减少这种昂贵的跨组事务,哀求所有数据都必须有Primary key,并且其它数据只管即便挂接在Primary key下面,使得事务只管即便在一个组内、且由组内leader实行。
2.组内多主多写
组内多主多写时每个机器都有完全的数据,但这份数据分成不相交的逻辑凑集,每个机器卖力一个凑集的写入。这台机器称为这个凑集的主机,这个凑集称为这个主机卖力的数据,其它机器称为这个凑集的备机。
客户端将写操作发到所涉及数据的主机,由主机通过atomic broadcast原子广播将更新要求发送给组内所有的机器,包括主机本身[9]。Galera和MySQL Group Replication都是采取这种方法。
图 3:组内多主多写架构[9]
原子广播具有3个特性:
如果一台机器实行一条所带的更新命令,那么所有的其它机器都实行这条命令(delivered)。这里“实行”指的是原子广播层将交给上层,真实的实行时候由上层决定。在数据库中,这个上层一样平常是并发事务管理器,它决定这些的真实实行顺序。
所有机器以相同的顺序实行命令
如果一台机器成功广播了一条,那么终极所有机器都将实行这条
利用原子广播后,事务的生命周期从prepare->committed/aborted改变为prepare->committing->committed/aborted。
图 4:事务生命周期状态转换
当一个事务只涉及到一个凑集的数据时,称为本地事务,由这个凑集的主机确当地事务管理器先利用本地严格2PL仲裁,然后将committing状态的事务通过原子广播发给其它备机。
当一个事务涉及到多于一个凑集的数据时,称为复合事务(complex transaction)。
这个事务所涉及的某个数据凑集的主机将committing事务状态,包括读凑集(如果须要serializable级别隔离。这里的一个小优化是采取dummy row减少可能极其弘大的读凑集)、写凑集、以及committing状态,通过原子广播发给全组进行仲裁。Galera和MySQL Group Replication都只是校验写凑集,因此不支持serializable级别事务隔离。
每台机器都可以通过本地事务状态和原子广播收到的,独立剖断committing事务终极是提交还是终止。这种剖断由原子广播的特性担保全局同等。
图 5:Deferred Update Replication和Certification-based Replication事务实行时序
强调一下:在机器通过原子广播进行数据同步时,事务的终极结果不能在广播前决定,而是在实行这条依赖的前置及这条后才能决定。这称为Deferred Update Replication推迟的更新复制或者Certification-based Replication。
这里有个主要特点须要把稳:只有收到一条的所有前置后,这条和所有未实行的前置才能由事务管理器并发实行。因此,这里引入了一定的串行化。
原子广播的突出优点是在低延迟局域网有很高的吞吐率。
但同时原子广播有不小的按机器个数放大的网络延迟,在非低延迟网络会显著放大网络延迟。MySQL Group Replication利用的Corosync和Galera支持的Spread都是基于Totem这个成员管理和原子广播协议。
Totem是个为低延迟局域网设计的协议。在Totem中,所有机器组成一个环(ring)。无论一台机器是否须要广播,令牌(token)在机器之间都按照环顺序通报。只有拿到令牌的机器才可以进行广播,即发出提交事务要求。因此不才一台机器收到上一台机器令牌的网络延迟期间,全体系统处于等待状态。
为了担保Safe Order Delivery,(实际是regular token,不是regular message)须要在环中循环两圈,才能知道是否可以实行,因此,延迟是(4f+3)RTT/2,个中(2f+1)是机器的数目、f表示容错的机器数。
在一个范例的两地三中央支配中,这导致一次事务写操作延迟极其高昂。例如一地两中央的网络延迟一样平常可以掌握在2ms(单向),上海-深圳间网络延迟一样平常是15ms(单向),则一次事务写操作的网络延迟是64ms!
在两地三中央的配置中,PhxSQL的主和一个备一样平常分别在一地的两中央,另一个在异地。在常日情形下,master的Paxos一次写入只需一个accept,并且只等最快的备机返回。这时PhxSQL的写延迟只有4ms!
比较Paxos这类协议,原子广播还有一个毛病。当任意一台机器宕机或者网络中断时,Totem此时会超时,在踢掉宕机的机器、重新确定组成员之前,全体集群的停滞实行,即写操作停息。
对付read-only事务,只有去数据凑集的主机读取、或者昂贵地读取原子广播Quorum台机器、或者利用类似Spanner的TrueTime技能读取任一符合资格的机器,才能担保线性同等性。Galera节点间有延迟,并且只读事务在本地实行,不支持线性同等性。如果MySQL Group Replication支持线性同等性,请不吝奉告。
理解基于原子广播的组内多主多写模式的事理和优缺陷后,利用多写模式还须要根据业务仔细划分数据集,只管即便减少公共数据的利用,同时处理好自增key的细节问题,以减少事务间的跨机冲突。
PhxSQL建立在开源的PhxPaxos根本上,感兴趣的读者可以用PhxPaxos方便实现原子广播插件,加载到MySQL中,从而支持多写。
如果不要read repeatable或者serializable级别隔离的事务,例如大略的key-value操作,同时通过lease机制担保线性同等性,是可以做到高效率多写的。但这就违反了PhxSQL完备兼容MySQL和最小侵入MySQL的原则。
2、为什么不支持分库分表?
分库分表也是个诱人的选择:可以平行无限扩展读写性能。分库分表便是分组,上个小节已经谈论了分布式事务的高昂本钱。其余,为了担保完备兼容MySQL、支持全局事务和serializable级别事务隔离,不大改MySQL就支持sharding是非常困难的。
大改又违反了“最小侵入MySQL”原则,并且可能引入新的不兼容性。在运用不哀求全局事务和serializable级别事务隔离情形下,感兴趣的读者可以把PhxSQL作为一容错的MySQL模块,在上层构建支持分库分表的系统。由于PhxSQL本身的容错性,这样做比在MySQL根本上直接构建要大略,无需关心每个sharding本身的出错。
如果往后有需求,PhxSQL团队也可能基于PhxSQL开拓一个分库分表的新产品。当然,这个产品难以供应PhxSQL级别的兼容性。
3、为什么这么纠结于serializable级别事务隔离性,read repeatable级别很多时候已经够用了啊?
我们在设计原则中已经提到,为了完备兼容MySQL。我们认为一项好的技能是一项大略方便用户的技能,供应符合用户直觉预期、不用看太多把稳事变的技能是我们的谅解。我们很诚恳,也是为了方便用户。我们不想说PhxSQL完备兼容MySQL,然后在不起眼的地方blabla列出好几页蝇头小字的例外。事实上,对付关键业务来说,serializable是必要的、read repeatable是不敷的。read repeatable有个令人讨厌的write-skew非常[12]。
举个例子。小薇在一个银行有两张信用卡,分别是A和B。银行给这两张卡总的信用额度是2000,即A透支的额度和B透支的额度相加必须不大于2000:A+B<=2000。
两个账户的扣款函数用事务实行分别是:
A账户扣款函数:
sub_A(amount_a):
begin transaction
if (A+B+amount_a <= 2000)
{ A += amount_a }
Commit
B账户扣款函数:
sub_B(amount_b):
begin transaction
if (A+B+amount_b <= 2000)
{ B += amount_b }
commit
假定现在A==1000,B==500。如果小薇是个黑客,同时用A账户消费300和B账户消费300,即amount_a == 400,amount_b == 300。那么这个数据库会发生什么事情呢?
如果是read repeatable级别隔离,sub_a和sub_b都会同时成功!
末了A和B账户的透支额分别是A=1000+400=1400,B=500+300=800,总的透支额A+B=1400+800=2200>2000,超过了银行付与的额度!
如果不是信用卡的两笔小消费,而是两笔大额转账,那么银行怎么办?
如果是serializable级别隔离,则sub_a和sub_b只有一个成功。详细剖析有兴趣的读者可以自己完成。
4、为什么不把显著提升MySQL性能作为一个紧张目标?
事实上,PhxSQL已经显著提升了MySQL主备的写入性能。与semi-sync比,在测试环境中,PhxSQL的写入性能比semi-sync高15%到20%以上。读性能持平。这是在知足完备兼容MySQL和最小侵入MySQL原则下所能得到的结果。
鉴于PhxSQL对MySQL的改动是如此之小,对性能有高哀求的读者,可以方便地把PhxSQL中的MySQL换成其它高性能版本,得到更高性能。
5、为什么编译时不支持C++11以下标准?
作为热爱新技能的码农,我们真的很喜好C++11中期待已久、激动民气的新特性,例如极大增强的模板、lambda表达式、右值和move表达式、多线程内存模型等,这将C++带入了一个新的时期,大大提高了码农搬砖的速率、编码的精确性、和程序的性能。有了C++11,PhxSQL的开拓效率提高了很多。
8、与Galera及MySQL Group replication的比较
拜会7.1.2小节。
结论
PhxSQL是一个完备兼容MySQL,供应与Zookeeper相同强同等性和可用性的MySQL集群。
感谢大家看完这么长的一篇文章。希望大家多阅读PhxSQL源码,多提技能性见地,乃至成为源码贡献者!
▽
喜好我们的会点赞,爱我们的会分享!