设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 手机 数据 公司
当前位置: 首页 > 服务器 > 安全 > 正文

微信开源PhxSQL背后:强一致高可用分布式数据库的设计和实现哲学(4)

发布时间:2021-01-07 19:13 所属栏目:53 来源:网络整理
导读:另外,我们希望通过开源更好地改进PhxSQL.我们欢迎技术性讨论和志愿者提交修改.我们承诺开源的PhxSQL会一直更新.除了一些和内部运维支撑系统进行集成的功能(PhxSQL把这些功能抽象成插件,我们针对内部运维支撑系统实

另外,我们希望通过开源更好地改进PhxSQL.我们欢迎技术性讨论和志愿者提交修改.我们承诺开源的PhxSQL会一直更新.除了一些和内部运维支撑系统进行集成的功能(PhxSQL把这些功能抽象成插件,我们针对内部运维支撑系统实现了这些插件),开源版和内部版本将保持一致.

6、PhxSQL的局限性

在一个不完美的世界里,完美是不存在的.我们很坦诚指出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,对于写入请求量很大的场景也可以很大程度上避免备机追流水落后的情况.

7、Why 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个特性:

  1. 如果一台机器执行一条消息所带的更新命令,那么所有的其它机器都执行这条命令(delivered).这里“执行”指的是原子广播层将消息交给上层,真实的执行时刻由上层决定.在数据库中,这个上层一般是并发事务管理器,它决定这些消息的真实执行顺序.
  2. 所有机器以相同的顺序执行命令
  3. 如果一台机器成功广播了一条消息,那么最终所有机器都将执行这条消息

使用原子广播后,事务的生命周期从prepare->committed/aborted改变为prepare->committing->committed/aborted.

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读