事务系统实现模式很简单?你确定没忽视这些差异?
旺道跨圈推广 -> 最新发布
事务系统实现模式很简单?你确定没忽视这些差异?

本文试图讨论这几个问题:

  • MySQL的redo log和binlog为什么要用XA?

  • MongoDB的oplog是按照什么顺序复制?

  • Raft真的只能串行Apply吗?

  • 数据库的复制和事务是完全独立的两回事?

  • 为什么MySQL不早点做一个Raft插件,直接用Raft实现高可用?

本文旨在阐述Fault-Tolerant Transaction的几种实现模式。虽然乍一看它们可能都是Raft+KVEngine +Concurrency Control,容易被认为是同一类方法,但实际上的差异很大,在讨论时不应该忽视它们之间的差异。

一、基本概念

  • 讨论的Fault-Tolerance,指的是通过网络通信的多个计算机节点,在部分节点发生Stop Failure的情况下,仍然尽力保证可用性;

  • 不讨论具体的Fault-Tolerance方法,默认读者对Raft等算法有基本理解;

  • 也不讨论具体的Concurrency Control方法,默认读者对其有基本的理解;

  • 会涉及到Spanner、TiKV、MongoDB等具体的数据库。

1、基于RSM的Fault-Tolerant KV

Replicated State Machine最早应该是在『Implementing fault-tolerant services using the state machine approach』提出。它是一种很简单实用的实现容错的方法,核心思想是:几个状态机具有相同的初始状态,并且按照同样的顺序执行了同样的命令序列,那么它们的最终状态也是一样的。由于状态一样,那么任意一个状态机宕机,都可以被其他的代替,因此实现了Fault Tolerant。

事务系统实现模式很简单?你确定没忽视这些差异?

这里提到了几个概念,命令、执行顺序、状态机,它们都是抽象概念,对应到具体的应用场景才有实际意义。在KVEngine的场景下,命令就是Put/Get等操作,状态机就是KVEngine本身,而执行序列,则由Replication Log决定。

既然提到了RSM和KV,那么基于RSM的KV也就呼之欲出了。把发到KVEngine的操作先用Raft复制一遍,在Apply的时候扔回到KVEngine执行,于是我们就得到了一个Fault-Tolerant的KVEngine。

看起来很简单,但我在这里显然忽略了很多细节:

  • 串行还是并行Apply:Raft被人诟病的一点是串行Commit、串行Apply,但这并不是Raft的锅;

  • 两条Log:Raft复制需要一个Log,KVEngine也会有一个WAL,会带来IO放大,能不能合并成一个呢?

  • Checkpoint:为了加速Recovery,需要做Checkpoint;

  • 只读操作需要复制吗?

  • 命令可以是复合操作吗:单行的CAS操作可以吗,多行的事务操作可以作为一个命令吗?

2、基于RSM的事务

我们来考虑最后一个问题,RSM中的命令,可以直接是一个事务吗?

既然Raft都是串行Apply了,那么看起来把事务的所有操作作为一个命令扔到状态机执行并没有什么问题。

但问题在于,实际中的事务是交互式的,也就是包含了if-else等逻辑的,并且逻辑还可能依赖了数据库系统外部的状态,所以不能简单地用Write Batch + Snapshot来实现一个事务,还是要有Concurrency Control的逻辑。

事务系统实现模式很简单?你确定没忽视这些差异?

为了解决Concurrency Control的问题,我们在Raft Leader上,实现一个Lock Table和Transaction Manager。拿S2PL方法举例:

  • 读数据之前加读锁,写数据之前加写锁;读操作通过Raft读数据,写操作Buffer在本地;

  • 在用户决定事务提交时,即可释放读锁;通过Raft写一条事务日志,包含所有写操作;

  • 在Raft Apply事务日志时,把写操作应用到KVEngine,并且释放写锁。

这里举的例子是S2PL,但对于其他的并发控制方法也基本通用。例如Snapshot Isolation,事务开始时获得KV的Snapshot,读操作都走Snapshot,写操作获得写锁,数据Buffer在本地,事务提交时检查[begin, end]之间有没有写冲突,没有的话则通过Raft写事务日志,在Apply事务日志之后,把写操作应用到KVEngine,最后释放写锁。

事务系统实现模式很简单?你确定没忽视这些差异?

这种方法接近Spanner的做法,它具有几个特点:

  • 只有Leader需要维护Lock Table、Transaction Manager,事务并发控制基本在Leader节点完成;

  • 从RSM的角度来看,这里的Lock Table起到了命令定序的作用,保证所有State Machine按照同样的顺序执行命令;

  • 加锁操作不走复制协议,解锁操作在复制协议Apply之后完成,锁会在复制的开始到Commit一直持有:也就意味着,复制协议的Commit即是事务的Commit,在Commit之前发生Failover,事务都会Abort;

  • Raft所复制的,即是事务的REDO。

3、基于共享存储的事务

重新看一下上面这个模型,复制协议所做的事情非常简单,和其他模块的耦合也很小,仅仅是维护一个有序的Log,因此,我们可以把它从share-nothing推广到share-storage的模型中。

事务系统实现模式很简单?你确定没忽视这些差异?

也就是说,我们把普通的单机事务引擎,放到一个高可用的存储上,就得到了基本可用的Fault-Tolerant 事务引擎了,连复制协议也不需要实现的。

不过事情显然不会这么简单:

  • 如何实现只读节点,提供读扩展的能力;

  • 计算节点如何更快地Failover;

  • 如何把更多的操作下推到存储节点。

4、基于高可用KV的事务

事务系统实现模式很简单?你确定没忽视这些差异?

回到一开始的第一种方案,在一个节点实现了KV、Raft、Lock Table、Transaction Manager,看起来耦合度比较大了,我们能不能对其进行分层,进一步简化呢?例如Google的经典做法,基于GFS实现Bigtable,基于Bigtable实现Percolator,Layered设计易于迭代、易于开发、易于调试。

因此我们可以考虑把KV层单独抽离出来,基于KV去实现Lock Table、Txn Manager:

  • Lock Table:在原本的KV中增加一列,变成Key => {Value, Lock};

  • Txn Manager: 从事务修改的所有Key中选出一个Primary Key,用来记录事务状态,因此KV进一步变成 Key => {Value, Lock, TxnStatus};

  • MVCC:甚至我们不甘心于Single Version,还想用Multi Version的并发控制,那么KV就变成{Key, Version} => {Value, Lock, TxnStatus}。

看过Percolator、TiKV设计的应该会比较熟悉,它们就是基于一个高可用的KV,把事务的状态都下沉到KV中。这种设计很容易拓展到分布式事务的场景,如果KV能够scale,那么上层的事务也能够scale了。

5、基于单机事务引擎实现高可用事务

上面的方案看起来都比较简单,不过有一个细节不容忽视:锁基本都是在复制协议提交之后才会释放,换句话说事务持有的锁会从事务开始直到多个节点写完日志,经历多次网络延迟、IO延迟,并且在拥塞情况下会面临排队延迟的风险。而锁意味着互斥,互斥意味着事务吞吐降低。

翻译一下:

  • 并发且有冲突的事务,其提交顺序由Lock Table决定,并且和复制协议的Log顺序一致;

  • 事务的Serialization Order,和RSM 中的Order一致。

不过这里存在一个问题:

  • 锁一定要在复制协议提交之后才能释放吗?

  • 提前释放会破坏Order的一致性吗?

  • RSM的Order一定要和事务的Serialization Order一致吗?

暂且不做回答,我们再看最后一种方案,基于单机事务引擎的高可用事务。

事务系统实现模式很简单?你确定没忽视这些差异?

在正常的单机事务流程中,增加一个复制的环节:本地事务提交之后不是立即返回用户,而是写binlog,等待binlog复制到其他节点之后再返回用户。

这种方式的事务延迟,看起来还是本地事务的延迟,加上复制日志的延迟;但相比于之前的方案,本地事务可以先提交,锁可以提交释放,总体的事务吞吐相比之下会有所提升。

看起来甚至比之前的方案更加简单,事务和复制模块得到了完美的分离,但这里忽略了一个复杂的问题:

  • 基于哪个日志来复制,基于数据库的Journal,还是再写一个binlog?

  • 基于什么顺序进行复制,如果是基于Journal复制可以用Journal顺序,如果基于binlog,顺序又是什么?

  • 如果有两个日志,两个日志其实意味着Transaction Serialization Order和RSM的State Machine Order不一样,会不会产生事务的并发异常,或者导致State Machine不一致?

由于直接复制Journal会引起一系列复杂的耦合问题,大部分数据库都选择单独写一个binlog/oplog来实现复制,不过在实现时可以做优化,因为如果真的写两个log会有原子性的问题(一个写成功了另一个没写成功)以及IO放大的问题。

这里的设计空间比较庞大,不做详细讨论,仅仅考虑在简化的模型下复制顺序的问题。

事务系统实现模式很简单?你确定没忽视这些差异?

对于并发执行的事务,为了确定复制顺序,这里维护一个称之为OpTime的自增ID。后续的复制会按照OpTime的顺序,OpTime小的先复制。如果OpTime仅仅是在事务的开始和结束之间分配,会带来问题:

  • 有冲突且并发的事务T1先Commit,具有较大的OpTime,也就意味会被后复制;

  • 后Commit的事务T2先Replication Commit,而先Commit的事务T1可能因为复制失败而Rollback;

  • 对于事务来说,这种场景下出现的异常类似Read-Uncommitted,事务T2读到了未Commit的数据。

因此,OpTime的分配需要有更强的限制:对于并发且有冲突的事务,OpTime的顺序要和事务的Serialization Order一样:

事务系统实现模式很简单?你确定没忽视这些差异?

在S2PL的场景中,我们把OpTime分配放到Lock之后Commit之前,即可满足这个要求。因为按照S2PL的调度,事务的Commit-Point就是Lock完成和Unlock之间。对照上面的例子,事务T2的OpTime被推迟到T1之后,复制的顺序也会相应改变,不会发生先前的异常了。

事务系统实现模式很简单?你确定没忽视这些差异?

推广到其他的并发控制方法也是类似,例如上面的Snapshot Isolation。提交之前会检查[begin, end]是否有冲突,有冲突直接重启事务。相当于在[begin, end]区间内分配OpTime即可。

这种方法通过OpTime,保留了Transaction Serialization Order和RSM的Order之间的关系:

  • 并发且有冲突的事务,其OpTime的顺序和事务Serialization Order一样;

  • 并发但没有冲突的事务,其OpTime顺序不确定,因为谁先提交都不会影响正确性;

  • 有先于关系的事务,OpTime也一定满足这个先于关系。

不过这里留下了一个问题,留待读者思考:

如何按照OpTime复制,因为有事务Abort的情况,OpTime做不到连续自增,仅仅是单调自增。

二、对比

第一种其实是Spanner,第二种是TiKV、Percolator,第三种是MySQL、MongoDB。

它们在复制上的区别:

  • 第一种方案,复制了事务的REDO,事务的提交顺序由Raft Log的顺序确定,Failover等机制完全按照RSM的模型来即可;

  • 第二种方案,Raft仅仅用于复制KV,事务的顺序和Raft Log的顺序没有关系,KV层的Failover和事务的Recovery完全独立;

  • 第三种方案,已经区别于传统的RSM模型,因为它其实是先Apply,再Replication、Commit,可以实现并发Apply。

从复杂度来看:

  • 第二种最简单清晰,从Raft,到Raft KV,再到Transactional KV,分层良好;

  • 其次是第一种,在Leader节点会额外实现Lock Table、Transaction Manager,这个和Raft是紧密结合的,但是事务提交的顺序就是Raft Log的提交顺序,不会造成混淆;

  • 最复杂的是第三种,由于事务提交顺序和Optime顺序不一致,对复制、读写等各种流程都会造成影响,看似简单但实则耦合。

从事务并发的角度来看:

  • 第三种方案可以完美支持并发,且持有锁的时间较短,仅仅是写一次本地日志;

  • 第一二种方案持有锁的时间更长,最后在Apply时理论上可以做到并发,如果没有其他约束。

从读写开销的角度来看:

  • 第一种最好,Replication Log和Engine Log可以合并,每条事务只要复制一次Raft Log;

  • 其次是第二种,通常会把binlog和存储引擎的journal独立,需要写两遍;不过oplog可以写到存储引擎里,一次IO即可提交(MongoDB的做法);

  • 最后是第二种,在KV中增加了更多的数据,放大较多。

不过这仅仅是理论上的分析,实际的复杂度、性能,很大程度上取决于实现而非理论。

三、总结

如果我们从很粗的层面来看,会觉得这些系统不过都是几个技术点的组合,而每一个技术点看起来都很简单,进而觉得事务系统不过是如此。

但实际上事务系统绝非简单的KV+Raft+Snapshot Isolation,它们之间不同的组合方式,会最终造就不同的系统。

本文留下了很多问题,RSM的Order往往认为是全序的,而Transaction 的Serialization Order是偏序的(偏序关系由事务冲突定义),它们之间如何统一?

RSM的Checkpoint和Transaction Checkpoint的统一?RSM的Recovery和Transaction Recovery的关系?写两条日志的系统(journal和binlog)两条日志之间的关系是什么?

留待下次分享,欢迎大家留言交流!

作者:hellocode

来源:https://zhuanlan.zhihu.com/p/51940735

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

事务系统实现模式很简单?你确定没忽视这些差异?

近期热文

看到外卖平台这样改善数据库架构,DBA表示放心了

对!嫁人就嫁程序员!

2018 Python官方年度报告:掌握Python趋势

分库分表就能无限扩容吗?

不管你使用哪种OLAP引擎,都可以这样搞定查询优化

教育培训机构-如何策划节日招生?
做教育培训,最重要的事情莫过于招生了。面对不同的学员,招生方…于招生。目标不同,活动策划也会不一样。② 活动主题要鲜明不仅主题要鲜明,主题之间要有连续性。就像看连续剧一样,一集接一集,一环扣一环。策划好一系列活动,一个接一个来,从多个角度延续活动的宣传,突出主题,引起关注度。常用的招生方式有:体验课招…-------------想要获得更多运营技巧、doc文案,
教育培训:如何提高满班率和续班率
什么是满班率?就是实际人数除以计划招生人数,这个值就是满班率…员有流失是正常的,但要保证一个概率。在保障老学员续期的基础上,我们也要大胆创新,开设网络课程,拓宽招生区域。实地课程录制后,进一步发行到商弈云课上,通过商弈云课系统转成真实流量,网上有人点击观看,点赞,可以按点播量分佣金。助你在日常的营销推…-----------------------想要获得更多运
培训机构难盈利的问题出在哪里,如何实现盈利?
竞争白热化实地培训班、托管辅导班竞争白热化了,利润越来越稀薄…现没有多少盈利。还有一部分负责人在刚招生时,掌握了不少资金,开始盲目扩张,盲目做课程推广,以期待获得更多生源和收费,从而使培训班陷入了这种恶性循环的陷阱里。其实这些到手的钱,并不是你的利润,而是你未来要支出的钱。如遇到行业快速发展时期,或者…-----想要获得更多运营技巧、doc文件,请“关注”并“转
“差异化”经营是网络培训赚钱的关键所在
“差异化经营”这个词,相信大多数人都耳熟能详,但要做到的却是…。在现有的基础上更新升级或者资源整合就是对现有的产品或者技术,进行升级版本,或者通过一些资源整合,成一个项目。你的技能以前是用来生产或制造产品,现在是把技能升级成知识培训,转换云课堂。直白一点就是可以让老师自行录好课程并上传到学校的商弈云课…在着缺点和不足之处。在创新改革时,要从功能、服务、价格等方面
教育培训行业是如何运作的?
以前读书时,学校附近有个小摊卖鸡蛋灌饼。刚开始的时候只有一家….%,剩下的一对一和多人大班其实市场份额都很小。家长报培训班,是希望孩子能够学到知识。老师通过课上教学和课后辅导来满足孩子的需求,达到成绩提高的目标。我见过上百人的大培训班,为什么一个班这么多人?因为是名师讲课,但人太多坐后面,基本听不到重…是你的核心竞争力。想要得到用户的认同,你就必须做到产品质量好
旺道:实体店怎么做网络营销?
年纪大了,体力不好了,便赚不了什么钱了。所以,一定要在年轻的…写文案都是非常头痛的事情,那么下面我会给大家提供一个解决方案。在互联网营销系统里面有很多细节营销,软文营销就是其中一种,但好多小白头痛写文章,所以可以用这个方法也一样可以植入广告语,或者是图片广告,轮显切换广告,使用 旺道营销系统,也就是每…以帮你吸引海量精准粉丝。有了粉丝,你通过广告、产品、服务就可
旺道:圈里圈外,铁饭碗距离瓷饭碗究竟有多远?
中国人爱混圈子,从线下一直混到线上,各种奇形怪状的圈子勾勒出…不能推则敷衍了事,盼着混到主任科员退休;一种是老黄牛式,踏踏实实、兢兢业业工作,但拙于人际关系,活干得最多,但依旧不见晋升迹象;还有一种是提线木偶式,你扯一下线他动一下,好像脑子和身体是分离的。我突然一拍脑袋,这是提前衰老的迹象啊,工作内容…即使选择留在铁饭碗圈里,也应保有随时离开的思想警惕和进行必要
旺道:微信要双开了,朋友圈推广更好做了
现在手机只能登一个微信,如两个,三个微信的小伙伴们就只能退出…动推广工具、 设置头像点击头像图标,点“+”选择图片,可以上传你的企业,个人头像,产品服务等。旺道微信朋友圈广告免费朋友圈广告-旺道、 设置推广主题点“广告”,再点“+”设置推广的主题(类别),填好中文主题,以及你的网址。教你不花一分钱做朋…简直就是一劳永逸哟。如果你点开发布的文章看不到广告,那就是你
旺道:如何能让网站多个关键词排名百度首页?
最近接了一个单,做婴儿游泳馆加盟的。优化推广范围是全国,但是…泳馆加盟哪家好”、“婴儿游泳加盟多少钱”这类与我息息相关的词。如何能让网站多个关键词排名百度首页?但客户并不认同,客户说这个词指数低,或者说搜的人不多。是,这是一方面原因。但是,指数低有什么关系,你是卖产品还是卖指数。搜的人不多有什么关系,…实现广告效果最大化,来满足大众化的广告需求。对于这样的四两拔
旺道:如何成为网络营销达人?这个技能帮你节省80%的时间
在某次名师讲坛上,听到了一个让人警醒的故事。说有个村子缺水,…准的产品。现在已经不是新鲜事物,好多企业因为百度竞价的高额费用,头疼不已,所以做网站关键词优化排名,成为了企业必选的推广项目。做优化也要做到有成效,不然就是一分钱也是昂贵的。用 旺道智能机器人 就可以持续代替人工去做,它非常聪明,只要你够耐…手,设备先进,你多努力奔跑也于事无补。简单说,要去一个地方,

此文章来源来互联网,如果你有任何版权冲突,可以联络我们,微信号:WANCOME,QQ:1444641。加我们时,请说明来意,我们将优先处理你的问题。




旺道商弈  | 圈广告  | 一键推  | 圈推广  | 圈营销  | 圈推广  | 跨圈推
粤ICP备10213132号
旺道商标注册证号:8608864
Copyright © 2016 环企网络信息科技有限公司 版权所有