关于im:谈谈PhxSQL的设计和实现哲学下

49次阅读

共计 7612 个字符,预计需要花费 20 分钟才能阅读完成。

摘要

上一章探讨了咱们为什么要做 PhxSQL 和为什么这样做 PhxSQL。这里咱们次要谈谈为什么不做某些个性。舍得舍得,有舍才有得。CAP 通知咱们只能三选二,俗话通知咱们天下没有收费的午餐。每个个性除了本身提供的性能,也有其代价。为了保障强统一的线性一致性、高可用、serializable 级别事务隔离、齐全兼容 MySQL、和最小侵入 MySQL,PhxSQL 放弃了一些个性。

注释

7. Why Not?

7.1. 为什么不反对多写?

多写想想就很迷人。多写能够充分利用每台机器写时须要的资源。例如某些写操作可能十分消耗 CPU,多写能够把写操作扩散在各台机器上,充分利用各个机器的 CPU 资源,极大进步写入的性能。多写使得换主没有存在的必要,也就没有换主时可能存在的不可写工夫窗问题。多写还使得客户端能够就近写入,缩小跨数据中心写入带来的网络提早。

多写有两种:大家熟知的分 shard 或者组,各 shard 或者组间并行写入,以 Google Spanner[8]为典型代表;在 shard 或者组内并行,以 Galera 和 MySQL Group Replication 为代表。

7.1.1. 组间多写

组间多写是把数据分成多个不相交的 shard,每个组的机器负责一个 shard。当一个事务波及的数据(读汇合和或写汇合)都在某个组时,这种事务称为本地事务。当一个事务波及的数据分布在超过一个组时,这种事务称为分布式事务。

本地事务能够在本组独立执行,组之间不须要任何通信。为了缩小事务抵触带来的性能升高,个别都是由组内 leader 执行本地事务,通过 Paxos 等一致性协定保障组内机器的数据统一[8]。各个组间并行执行本地事务,能够极大进步本地型事务的写性能。

组间多写最大的妨碍是分布式事务,而分布式事务是十分低廉的。在 SQL 的模型中,为了实现 read repeatable 级别的事务隔离,事务管理器须要查看两个并发事务的写数据集是否抵触;为了达到 serializable 级别的事务隔离,事务管理器须要查看两个并发事务的读数据集和写事务集是否抵触[10]。这个别通过严格两阶段锁(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 执行。

7.1.2. 组内多主多写

组内多主多写时每个机器都有残缺的数据,但这份数据分成不相交的逻辑汇合,每个机器负责一个汇合的写入。这台机器称为这个汇合的主机,这个汇合称为这个主机负责的数据,其它机器称为这个汇合的备机。客户端将写操作发到所波及数据的主机,由主机通过 atomic broadcast 原子播送将更新申请发送给组内所有的机器,包含主机自身[9]。Galera 和 MySQL Group Replication 都是采纳这种办法。

图 3:组内多主多写架构[9]

原子播送具备 3 个个性:

i) 如果一台机器执行一条音讯所带的更新命令,那么所有的其它机器都执行这条命令(delivered)。这里“执行”指的是原子播送层将音讯交给下层,实在的执行时刻由下层决定。在数据库中,这个下层个别是并发事务管理器,它决定这些音讯的实在执行程序。

ii) 所有机器以雷同的程序执行命令。

iii) 如果一台机器胜利播送了一条音讯,那么最终所有机器都将执行这条音讯。

应用原子播送后,事务的生命周期从 prepare->committed/aborted 扭转为 prepare->committing->committed/aborted。

图 4:事务生命周期状态转换[9]

当一个事务只波及到一个汇合的数据时,称为本地事务,由这个汇合的主机的本地事务管理器先应用本地严格 2PL 仲裁,而后将 committing 状态的事务通过原子播送发给其它备机。

当一个事务波及到多于一个汇合的数据时,称为复合事务(complex transaction)。这个事务所波及的某个数据汇合的主机将 committing 事务状态,包含读汇合(如果须要 serializable 级别隔离。这里的一个小优化是采纳 dummy row 缩小可能极其宏大的读汇合[10])、写汇合、以及 committing 状态,通过原子播送发给全组进行仲裁。Galera 和 MySQL Group Replication 都只是校验写汇合,因而不反对 serializable 级别事务隔离[18]。

每台机器都能够通过本地事务状态和原子播送收到的音讯,独立断定 committing 事务最终是提交还是终止。这种断定由原子播送的个性保障全局统一。

图 5:Deferred Update Replication 和 Certification-based Replication 事务执行时序[11]

强调一下:在机器通过原子播送进行数据同步时,事务的最终后果不能在播送前决定,而是在执行这条音讯依赖的前置音讯及这条音讯后能力决定。这称为 Deferred Update Replication9 推延的更新复制或者 Certification-based Replication[11]。这里有个重要特点须要留神:只有收到一条音讯的所有前置音讯后,这条音讯和所有未执行的前置音讯能力由事务管理器并发执行。因而,这里引入了肯定的串行化。

原子播送的突出长处是在低提早局域网有很高的吞吐率。

但同时原子播送有不小的按机器个数放大的网络提早,在非低提早网络会显著放大网络提早。MySQL Group Replication 应用的 Corosync[16]、Galera[15]默认应用的 gcomm 和反对的 Spread[17]都是基于 Totem[13]这个成员治理和原子播送协定。

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[8]技术读取任一合乎资格的机器,能力保障线性一致性。Galera 节点间有提早,并且只读事务在本地执行,不反对线性一致性[15]。如果 MySQL Group Replication 反对线性一致性,请不吝告知。

理解基于原子播送的组内多主多写模式的原理和优缺点后,应用多写模式还须要依据业务认真划分数据集,尽量减少公共数据的应用,同时解决好自增 key 等细节问题,以缩小事务间的跨机抵触。

PhxSQL 建设在开源的 PhxPaxos 根底上,感兴趣的读者能够用 PhxPaxos 不便实现原子播送插件,加载到 MySQL 中,从而反对多写。

如果不要 read repeatable 或者 serializable 级别隔离的事务,例如简略的 key-value 操作,同时通过 lease 机制保障线性一致性,是能够做到高效率多写的。但这就违反了 PhxSQL 齐全兼容 MySQL 和最小侵入 MySQL 的准则。

7.2. 为什么不反对分库分表?

分库分表也是个迷人的抉择:能够平行有限扩大读写性能。分库分表就是分组,上个大节曾经探讨了分布式事务的昂扬老本。另外,为了保障齐全兼容 MySQL、反对全局事务和 serializable 级别事务隔离,不大改 MySQL 就反对 sharding 是十分艰难的。大改又违反了“最小侵入 MySQL”准则,并且可能引入新的不兼容性。在利用不要求全局事务和 serializable 级别事务隔离状况下,感兴趣的读者能够把 PhxSQL 作为一容错的 MySQL 模块,在下层构建反对分库分表的零碎。因为 PhxSQL 自身的容错性,这样做比在 MySQL 根底上间接构建要简略,无需关怀每个 sharding 自身的出错。如果当前有需要,PhxSQL 团队也可能基于 PhxSQL 开发一个分库分表的新产品。当然,这个产品难以提供 PhxSQL 级别的兼容性。

7.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 账户生产 400 和 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 只有一个胜利。具体分析有趣味的读者能够本人实现。

7.4. 为什么不把显著晋升 MySQL 性能作为一个次要指标?

事实上,PhxSQL 曾经显著晋升了 MySQL 主备的写入性能。与 semi-sync 比,在测试环境中,PhxSQL 的写入性能比 semi-sync 高 16% 到 25% 以上。读性能持平。这是在满足齐全兼容 MySQL 和最小侵入 MySQL 准则下所能取得的后果。鉴于 PhxSQL 对 MySQL 的改变是如此之小,对性能有高要求的读者,能够不便地把 PhxSQL 中的 MySQL 换成其它高性能版本,取得更高性能。

7.5. 为什么编译时不反对 C ++11 以下规范?

作为酷爱新技术的码农,咱们真的很喜爱 C ++11 中期待已久、激动人心的新个性,例如极大加强的模板、lambda 表达式、右值和 move 表达式、多线程内存模型等,这将 C ++ 带入了一个新的时代,大大提高了码农搬砖的速度、编码的正确性、和程序的性能。有了 C ++11,PhxSQL 的开发效率进步了很多。

8. 与 Galera 及 MySQL Group replication 的比拟

参见 7.1.2 大节。

论断

PhxSQL 是一个齐全兼容 MySQL,提供与 Zookeeper 雷同强一致性和可用性的 MySQL 集群。

感激大家看完这么长的一篇文章。心愿大家多浏览 PhxSQL 源码,多提技术性意见,甚至成为源码贡献者!

参考

  1. M.P. Herlihy and J. M. Wing. Linearizability: a correctness condition for concurrent objects. ACM Transactions on Programming Languages and Systems (TOPLAS), Volume 12 Issue 3, July 1990, Pages 463-492.
  2. L. Lamport. How to make a multiprocessor computer that correctly executes multiprocess programs. IEEE Trans. Computer. C-28,9 (Sept. 1979), 690-691.
  3. P. Hunt, M. Konar, F. P. Junqueira, and B. Reed. ZooKeeper: wait-free coordination for Internet-scale systems. USENIXATC’10, 2010.
  4. L. Lamport. Paxos Made Simple. ACM SIGACT News (Distributed Computing Column) 32, 4 (Whole Number 121, December 2001) 51-58.
  5. D. Ongaro and J. Ousterhout. In search of an understandable consensus algorithm. USENIX ATC’14, 2014.
  6. B. M. Oki and B.H. Liskov. Viewstamped replication: a New primary copy method to support highly-available distributed systems. PODC’88, 8-17, 1988.
  7. T. Chandra, R. Griesemer, and J. Redstone. Paxos made live – an engineering perspective. PODC’07, 2007.
  8. J. C. Corbett, J. Dean, M. Epstein, and etc. Spanner: Google’s Globally-Distributed Database. OSDI’12, 2012.
  9. F. Pedone, R. Guerraoui, and A. Schiper. The database state machine approach. Journal of Distributed and Parallel Databases and Technology, 14:71–98, 2002
  10. V. Zuikeviciute and F. Pedone. Revisiting the database state machine approach. VLDB Workshop on Design, Implementation, and Deployment of Database Replication. 2005.
  11. Certification-based Replication. Visited at 2016/9/5.
  12. Snapshot isolation. Visited at 2016/9/5.
  13. Y. Amir, L. E. Moser, P. M. Melliar-smith, D. A. Agarwal, and P. Ciarfella. The totem single ring ordering and membership protocol. ACM Transactions on Computer Systems. 13 (4): 311–342.
  14. http://downloads.mysql.com/presentations/innovation-day-2016/Session_7_MySQL_Group_Replication_for_High_Availability.pdf. Visited at 2016/9/5.
  15. Replication API. Visited at 2016/9/5.
  16. Corosync by corosync. Visited at 2016/9/5.
  17. http://www.spread.org/. Visited at 2016/9/5.
  1. Isolation Levels. Visited at 2016/9/5
  2. L. Lamport. Fast Paxos. Technical Report, MSR-TR-2005-112.
  3. I. Moraru, D. G. Andersen, and M. Kaminsky. There is more consensus in egalitarian parliaments. SOSP’13, 2013.
  4. GitHub – tencent-wechat/phxpaxos: C++ Paxos library that has been used in Wechat production environment..

OpenIMgithub 开源地址:

https://github.com/OpenIMSDK/…

OpenIM 官网:https://www.rentsoft.cn

OpenIM 官方论坛:https://forum.rentsoft.cn/

更多技术文章:

开源 OpenIM:高性能、可伸缩、易扩大的即时通讯架构
https://forum.rentsoft.cn/thr…

【OpenIM 原创】简略轻松入门 一文解说 WebRTC 实现 1 对 1 音视频通信原理
https://forum.rentsoft.cn/thr…

正文完
 0