分布式事务实现-Percolator
Google为了解决网页索引的增量处理,以及维护数据表和索引表的一致性问题,基于BigTable实现了一个支持分布式事务的存储系统。这里重点讨论这个系统的分布式事务实现,不讨论percolator中为了支持增量计算而实现的Notifications机制。
该系统基于BigTable,支持snapshot isolation隔离级别,这个隔离级别不在ANSI定义的隔离级别范围内。简单来说,就是一个事务看到的是一个stable的数据库的快照。快照隔离相对于可串行化隔离级别的优点是更高的读性能,不需要加锁,MVCC基于BigTable的多版本机制。缺点是有write skew问题,简单来说,对于两个事务T1:b=a+1和T2:a=b+1,初始化a=b=0。串行化的情况下,结果只可能是(a=2,b=1)或者(a=1,b=2),而在快照隔离级别下,结果可能是(a=1,b=1)。这在某些业务场景下是不能接受的。既然有多版本,就需要有版本号,percolator系统使用一个全局递增时间戳服务器来为事务产生时间戳,每个事务开始时拿一个时间戳t1,那么这个事务执行过程中可以读t1之前的数据。提交时再取一下时间戳t2,作为这个事务的提交时间戳。
现在说分布式事务。说起分布式事务第一个想到的就是两阶段提交,这个系统也不例外。客户端作为协调者coordinator,BigTable的tablet server作为参与者participant。 除了实际的表的每个Cell的数据存在BigTable中外,coordinator还将Cell锁信息,事务版本号存在BigTable中。简单来说,如果需要写列C,在BigTable中实际存在三列,分别为C:data,C:lock,C:write。由于BigTable实际上定位一个Value需要三个信息,rowkey,column和timestamp,所以实际上一个 column本身内部可以看成一个timestamp->value的map。那么:
1. c:write中存事务提交时间戳commit_ts=>start_ts。
2. c:data这个map中存事务开始时间戳start_ts=>实际列数据
3. c:lock存start_ts=>(primary cell),primary cell是rowkey和列名的组合,它在两阶段提交容错处理和事务冲突时使用,用来清理由于coordinator失败导致的分布式事务失败留下的锁信息。
举个没有任何冲突例子,假设一个分布式事务T1需要修改两个Cell,C1(Rowkey1:C1)和C2(Rowkey2:C2),C1为primary cell,Value分别为Value1和Value2,并且两个Cell处于不同的tablet server,serverA和serverB。客户端commit之前首先将两个Cell都加入到客户端本地的一个数组中,最后事务commit(包括两阶段的prepare和commit)的时候才将所有Cell发向tablet server。
没有检测到冲突的写事务流程:
prepare阶段:
1. 分布式事务T1启动,从全局时间戳服务器获取事务启动时间戳记作t1_start_ts。
2. 首先写primary cell C1,往C1:data中写入t1_start_ts=>value1,往C1:lock中写入t1_start_ts=>primary cell 表示加锁,同理,写serverB,往C2:data中写入t1_start_ts=>value2, 往C2:lock中写入t1_start_ts=>primary cell
commit阶段:
1. 从全局时间戳服务器获取事务提交时间戳记作t1_commit_ts。
2. 启动一个C1所在的BigTable行事务,包含以下两个操作
2.1 往primary cell C1:write写入t1_commit_ts=>t1_start_ts(这步是关键)
2.2 将primary cell的lock release(delete C1:lock,时间戳为t1_start_ts)
3. Commit这个BigTable 事务,这一步实际上将这个事务的数据对外可见,因为随后的一个读事务(事务启动时间戳记作t2_start_ts)读C1之前,会首先读C1:write的小于t2_start_ts的最大的版本的数据获得t1_start_ts,然后拿着t1_start_ts才能去C1:data中读取真正的数据。
4. 将其他secondary cell C2:write中写入t1_commit_ts=>t1_start_ts,release C2的lock
没有检测到冲突的读C1和C2的事务T3流程:
1. 从全局时间戳服务器获取事务提交时间戳记作t3_start_ts
2. 分别读C1和C2,读C:write的比t3_start_ts小的最大的一个事务提交时间戳的事务启动时间,然后拿这个事务启动时间去C:data中读真正的数据。
可以看出,一个Cell对外可见是通过写C:write来达到的,t1_commit_ts为事务提交版本号,t1_start_ts为t1这个事务修改后的数据版本号,真正读数据需要拿到t1_start_ts,而读t1_start_ts又需要首先拿到t1_commit_ts。
协调者(Client)宕机容错
假设C1上锁失败,C2上锁成功,那么分布式事务失败会将C2的锁残留在BigTable中。这个残留的锁由后续第一个读或写C2的事务来清除,满足什么样的条件才能清除?满足以下两个条件中的一个即可:1. 写这个lock的客户端在chubby上的结点没了,即客户端死了 2. C2:lock这把锁滞留时间太长了(lock内部保存最后更新时间即可)。 cleanup的操作就是直接delete C2:lock即可,时间戳为t2_start_ts_(percolator论文中此处有笔误)。但是如何知道残留下这个锁的事务是否已经提交?这就需要去读C2的primary cell的write字段,在这个例子里就是读C1:write,记残留下来的锁C2:lock的时间戳为lock_ts(percolator论文这里说的不清楚),那么具体的判断事务是否提交的操作就是读取C1:write的[lock_ts,正无穷)的所有版本,判断是否有一个版本的值是lock_ts,如果有,则说明残留锁的事务已经提交。
事务冲突
Prepare阶段冲突:写C1之前需要首先读取C1:lock,如果有任何一个版本被加上了锁,那么这次分布式事务失败。还有一种冲突是,有其他事务在本事务开始之后commit修改了C1,从而修改了C1:write,这是一种Snapshot isolation需要避免的写写冲突。
Commit阶段冲突:分布式事务提交需要先提交primary cell,再提交其他cell,再提交primary cell时需要先检查自己是否还拿住了primary cell的锁,在这里是C1:lock,即t1_start_ts_版本是否已经被删除。做这个判断的原因是其他事务可以cleanup这个lock,如果它认为这个事务握有锁时间过长或者写入lock的客户端宕机太慢等原因。在这里,primary cell的lock字段是其他事务进行cleanup操作和当前事务提交操作的同步点。
参考资料:
http://static.googleusercontent.com/media/research.google.com/en/us/pubs/archive/36726.pdf
https://github.com/XiaoMi/themis/
分布式事务实现-Percolator的更多相关文章
- Google关于Spanner的论文中分布式事务的实现
Google关于Spanner的论文中分布式事务的实现 Google在Spanner相关的论文中详细的解释了Percolator分布式事务的实现方式, 而且用简洁的伪代码示例怎么实现分布式事务; Pe ...
- MVCC/分布式事务简介
之前我们学习了RocksDB,但这还只是一个最基础的存储引擎.如果想把它在生产环境中用起来,还需要解决很多问题: 如何从单机扩展到分布式? 如何实现事务,并对事务进行并发控制? 用户接口能不能高级一点 ...
- 数据库分布式事务XA规范介绍及Mysql底层实现机制
1. 引言 分布式事务主要应用领域主要体现在数据库领域.微服务应用领域.微服务应用领域一般是柔性事务,不完全满足ACID特性,特别是I隔离性,比如说saga不满足隔离性,主要是通过根据分支事务执行成功 ...
- 群集中的MS DTC分布式事务协调器
MS DTC在大多数SQL 服务器下都需要安装,若只是安装数据库引擎或Analysis 服务可不安装DTC.如果后需要使用分布式事务,则可在SQL Server群集安装完成后再安装DTC. 一.群集M ...
- 事务使用中如何避免误用分布式事务(System.Transactions.TransactionScope)
1:本地事务DbTransaction和分布式事务TransactionScope的区别: 1.1:System.Data.Common.DbTransaction: 本地事务:这个没什么好说了,就是 ...
- 没有活动事务 链接服务器的 OLE DB 访问接口 "SQLNCLI" 无法启动分布式事务
在windows2003下执行分布式事务的时候出现如下情况. 一. 问题现象在执行分布式事务时,在sql server 2005下收到如下错误: 链接服务器"xxxxxxx"的 O ...
- 已禁用对分布式事务管理器(MSDTC)的网络访问的解决方法之一
C# ASP.NET项目提示上述错误,在代码中使用分布式事务提示添加或修改到数据库的时候.添加数据到数据库时,不会设置实体类的主键字段.
- 【转】PostgreSQL分布式事务配置
XA是open group提出的分布式事务处理规范,JTA支持XA规范,JTA只规定了接口,有些应用容器提供实现,也有一些三方的开源实现可用,比如Atomikos. 如果PostgreSQL参与分布式 ...
- 分布式事务(一)两阶段提交及JTA
原创文章,同步发自作者个人博客 http://www.jasongj.com/big_data/two_phase_commit/ 分布式事务 分布式事务简介 分布式事务是指会涉及到操作多个数据库(或 ...
随机推荐
- Spring整合Mybatis原理简单分析
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" ...
- Redis Cluster高可用集群在线迁移操作记录
之前介绍了redis cluster的结构及高可用集群部署过程,今天这里简单说下redis集群的迁移.由于之前的redis cluster集群环境部署的服务器性能有限,需要迁移到高配置的服务器上.考虑 ...
- MyBatis JavaType JdbcType
MyBatis 通过包含的jdbcType类型 BIT FLOAT CHAR TIMESTAMP OTHER UNDEFINED TINYINT REAL VARCHAR BINARY BLOB NV ...
- UVA 1605 Building for UN(思维)
题目链接: https://cn.vjudge.net/problem/UVA-1605#author=0 /* 问题 设计一个包含若干层的联合国大厦,其中每一层都是等大的网格,每个格子分配给一个国家 ...
- MVC实现更新数据库的数据
经过一系列MVC的练习,如数据库的数据显示,添加,删除等,还差一个功能,就是更新,那本次练习的是MVC对数据库的数据进行更新. 写好更新的存过程: 有了存储过程,可以写实体(Entity)的方法了.写 ...
- 创建第一个MVC应用程序
整个国庆期假,Insus.NET没有出门,在家静心修炼MVC.这意味着Insus.NET将来的日子里会以MVC为学习,开发,应用作为重点,不过现在才开始踏出第一步...... 路慢慢...... 下载 ...
- AE开发
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...
- asp.net错误记录
//登录 jquery-ajax post请求后台无法获取数据,get就可以!!!原因:get方法,后台接收用Request.QueryString["para1"];post方法 ...
- 撩课-Web大前端每天5道面试题-Day29
1.https协议的优点? 使用HTTPS协议可认证用户和服务器, 确保数据发送到正确的客户机和服务器: HTTPS协议是由SSL+HTTP协议构建的可进行加密传输. 身份认证的网络协议,要比http ...
- HDFS 命令大全
目录 概要 用户命令 dfs 命令 追加文件内容 查看文件内容 得到文件的校验信息 修改用户组 修改文件权限 修改文件所属用户 本地拷贝到 hdfs hdfs 拷贝到本地 获取目录,文件数量及大小 h ...