CockroachDB是如何进行分布式原子事务的

CockroachDB的一个主要特性是他完全支持分布式数据库中任意键之间的ACID事务。
CockroachDB事务对数据库应用一系列的操作的同时,仍然能够保持ACID属性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
在这片文章中,我们将重点讨论CockroachDB如何在不适用锁的情况下实现原子事务。

__原子性(Atomicity)__可以被定义如下:
对于一组操作,要么全部执行,要么一个也不执行。

没有原子性的话,那些执行了一般的事务在被中断的情况下就可能只执行了部分修改。

策略(Strategy)

CockroachDB用于提供原子事务的测录遵循以下步骤:

  1. 开关(Switch):在修改任何键的值之前,事务创建一个开关,它是一个可写的值,不同于在批处理中改变的任何实际值。开关不能同时被访问——开关的读写是严格有序的。开关最初是“关(off)”的,它可以切换到“开(on)”的状态。
  2. 筹划(Stage):写进程对数据库进行一些列的改变,但是不覆盖任何已存在的值;新的值做好了替换旧的值的准备。
  3. 过滤(Filter):对于所有有筹划值(staged value)的键(key),读进程在获得该键对应的值之前不需要检测一下该事务的开关的状态。如果开关状态是“关(off)”,读进程将会该键的原始的值;如果开关状态是“开(on)”,读进程会返回筹划后的值。因此,所有对某一个键的读进程所获取到的值将直接取决于开关的状态。
  4. 快速切换(Flip):当写进程准备好了事务中的所有变化,写进程快速切换开关到“开(on)”状态。与过滤(Filter)相结合,所以该事务中的分级的值将做好准备返回给接下来所有的读进程。
  5. 取消筹划(Unstage):一旦事务完成(中止或提交),筹划值将会尽可能快地被清空。如果该事务成功,那么所有原始值将会被筹划值(staged values)取代;如果事务失败了,所有筹划值将会被丢弃。需要注意的是,取消筹划是异步完成的,它并不需要在事务提交之后再进行。

详细的事务过程

开关(Switch):CockroachDB事务记录

为了开始事务,写进程(Writer)首先需要创建 事务记录(transaction record) 。
CockroachDB使用事务记录为我们的总体策略提供切换。

每个事务记录具有以下字段:

  • 一个对应该事务的唯一标识(UUID);
  • 当前状态(current state),包括 挂起(PENDING)、中止(ABORTED)或 已提交(COMMITED);
  • 一个Cockroach K/V键。这个键用于指定“开关(switch)”在分布式数据存储中的位置。

写进程(writer)在挂起(PENDING)状态下生成一个新的UUID的事务记录。
然后,写进程使用一个特殊的CockroachDB命令 BeginTransaction() 来存储事务记录。
该记录与事务记录中的密钥位于同一位置(即在分布式系统中的同一节点上)。

因为事务记录存储在单个Cockroach键中,对它的操作会严格排序(通过组合Raft和我们的底层存储引擎)。
事务的 状态(state) 是开关(switch)的开关状态,状态的挂起(PENDING)和终止(ABORTED)对应“关(off)”,已提交(COMMITED)状态对应“开(on)”。
因此,事务记录满足我们对开关的需求。
(译者注:开关是一个理论概念,事务记录是开关的实现)

注意,事务状态可以由挂起(PENDING)转移到终止(ABORTED)或已提交(COMMITTED),但是没有别的转移方式(因为终止(ABORTED)和已提交(COMMITED)状态都是最终状态)。

筹划(Stage):写意图(Write Intents)

为了 筹划(stage) 在事务中的更改,CockroachDB使用了一个名为 “写意图(write intent)” 的结构。
任何时候,一个值作为事务的一部分被写入一个键,它被写为一个写意图。

如果事务成功结束,那么该写意图结构中所包含的值将会被成功写入(数据库中)。

写意图还包含存储事务记录的 键(key) 。
这是至关重要的:如果一个读进程(reader)遇到了一个写意图,他使用这个键的值来定位事务记录(开关(the switch))。

作为最终规则,在任何键上只能有一个写意图。
如果有多个同时发生的存储过程,可能会发生一个存储过程在写一个键的数据,而与此同时这个键又对应了另一个存储过程中的一个活跃的写意图。
然而,事务并发是一个复杂的话题,我们将在以后的博客文章中讨论(《论事务隔离》);
而现在,我们假设一次只有一个事务,并且现有的写意图必须来自一个废弃的事务。

当写入已具有写入意图的键时:

  1. 如果已经存在的意图(intent)的事务记录(transaction record)是PENDING状态的话,那么将其转换为ABORTED状态。如果之前的事务是COMMITED或ABORTED,那么什么都不做。
  2. 清除早期事务中的现有意图,这将删除意图。
  3. 为并发事务添加新的意图。

过滤(Filter):读取一个意图

在读取一个键时,必须遵循总体策略的原则3,并在返回值之前查阅任何开关的值。

如果键包含一个普通值(比如,不是一个写意图),读进程(reader)可以确信,没有涉及此键的事务正在进行中,
并且它包含最近提交的值。
因此,该值逐字返回。

但是,如果读进程读取到的是一个写意图,则意味着在删除意图之前,在某个点之前放弃了先前的事务(记住:我们已经假设过在同一时间只能进行一个存储过程)。
在继续之前,读进程需要先检查事务的开关的状态(事务记录)。

  1. 如果事务状态(transaction record)目前仍然是PENDING则将其转换为ABORTED状态。
  2. 清除早期事务中的现有意图,这将删除意图。(译者注:前两步和stage阶段一样)
  3. 返回键所对应的普通值。如果早先的事务的状态是COMMITED,则清理操作(cleanup operation)将会将普通值(plain value)更新为筹划值(staged value);不然的话,该步操作将会在事务开始之前返回这个键所对应的原始的值。

快速切换(Flip):提交事务

为了提交事务,事务记录被更新为提交(COMMITED)的状态。

所有由该事务写的写意图将会立即生效:
在未来的所有遇到此事务的写意图的读取操作都会通过事务记录来获得结果数据,
(译者:意思大概是你一样的读数据,但是在Flip之后的这段时间,你的读取将会由写意图对应的事务记录来代理)
因为事务已经提交,所以返回的值由写意图给你。
(译者:意思大概是,香港回归第二天,你去办理政府业务,虽然香港的这个机构还没有马上变,但是里面的人已经变成了中国的了。那么其实接下来大家可以猜到,也就是中国部门正式替换掉英国的部门,而现在只是派一个人过来代理一下)

终止(Aborting)事务

可以通过更新事务记录的状态为中止(ABORTED)来中止事务。
此时,事务将永久中止,将来的读取将忽略该事务创建的写意图。

取消筹划(Unstage):清空意图

上面的系统已经提供了原子提交的属性;
然而,过滤步骤是昂贵的,因为它需要跨分布式系统的写入来过滤中心位置(事务记录)。
对于分布式系统来说,这是不期望的行为。

因此,在事务完成后,我们会尽快地删除其创建的写意图:
如果键具有没有写意图的普通值,则不需要对读取操作进行过滤,从而以适当的分发方式完成。

清理操作(Cleanup Operation)

当关联事务不再挂起(PENDING)时,可以在写意图上调用清除操作。
它遵循以下简单步骤:

  • 如果事务状态是终止(ABORTED),写意图将会被移除。
  • 如果事务状态是已提交(COMMITTED),该键对应地写意图地筹划值将会被转化成普通值,然后这个写意图将会被移除。
  • 清除操作是幂等(idempotent)的;也就是说,如果两个进程试图清理同一个键和事务的意图,则第二个操作将会被忽略。

清理是在下列情况下进行的:

  • 当一个写进程成功提交或者终止了一个事务,他尝试立即清空它之前写下的所有写意图。
  • 当一个写进程碰到了之前的事务中的写进程产生的写意图。
  • 当一个读进程碰到了之前的事务中的写进程产生的写意图。

通过多重途径积极地清理过期的写意图,最小化地过滤了所需地性能影响。

圆满完成(Wrap Up)

自此,我们已经讨论了CockroachDB确保其分布式、无锁事务的原子性的基本策略。

但是故事比我在这里所说的更多。
CockroachDB支持并发的事务,这将写入一个包含重叠键的集合(sets)中。
允许重叠的并发事务是AID中的“I”,它保证事务隔离。
我们将在以后的文章中详细介绍我们是如何实现事务隔离的。
敬请期待!

CockroachDB学习笔记——[译]CockroachDB是如何进行分布式原子事务的的更多相关文章

  1. CockroachDB学习笔记——[译]CockroachDB中的SQL:映射表中数据到键值存储

    CockroachDB学习笔记--[译]CockroachDB中的SQL:映射表中数据到键值存储 原文标题:SQL in CockroachDB: Mapping Table Data to Key- ...

  2. CockroachDB学习笔记——[译]如何优化Go语言中的垃圾回收

    原文链接:https://www.cockroachlabs.com/blog/how-to-optimize-garbage-collection-in-go/ 原作者:Jessica Edward ...

  3. CockroachDB学习笔记——[译]在CockroachDB中如何让在线模式更改成为可能

    原文链接:https://www.cockroachlabs.com/blog/how-online-schema-changes-are-possible-in-cockroachdb/ 原作者: ...

  4. CockroachDB学习笔记——[译]Cgo的成本与复杂性

    原文链接:https://www.cockroachlabs.com/blog/the-cost-and-complexity-of-cgo/ 原作者:Tobias Schottdorf 原文日期:D ...

  5. CockroachDB学习笔记——[译]为什么Go语言是CockroachDB的正确选择

    原文链接:https://www.cockroachlabs.com/blog/why-go-was-the-right-choice-for-cockroachdb/ 原作者:Jessica Edw ...

  6. CockroachDB学习笔记——[译]The New Stack:遇见CockroachDB,一个弹性SQL数据库

    原文链接:https://www.cockroachlabs.com/blog/the-new-stack-meet-cockroachdb-the-resilient-sql-database/ 原 ...

  7. CockroachDB学习笔记——[译]Scaling Raft

    原文链接:https://www.cockroachlabs.com/blog/scaling-raft/ 原作者:Ben Darnell 原文日期:Jun 11, 2015 译:zifeiy 在Co ...

  8. CockroachDB学习笔记——[译]Hello World

    原文链接:https://www.cockroachlabs.com/blog/hello-world/ 原作者:Spencer Kimball 原文日期:Jun 4, 2015 译:zifeiy 数 ...

  9. .NetCore学习笔记:三、基于AspectCore的AOP事务管理

    AOP(面向切面编程),通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑 ...

随机推荐

  1. YOLO---近段时间的练习目标

    YOLO---近段时间的练习目标 yolo(darknet)官方主页:https://pjreddie.com/darknet/yolo/   和在学校时用的不太一样了,有更新了- 还有一个常用版本: ...

  2. Java字节码方法表结构深度剖析

    继续上一次[https://www.cnblogs.com/webor2006/p/9459681.html]的字节码分析,这次来分析一下最为复杂的方法表的信息,如下: 而上一次分析到了属性表的位置在 ...

  3. Seafile和Nextcloud相比较哪个好用

    面对大量的照片视频,备份资料成了很多网友的刚需.但现在各大免费网盘,关闭地关闭,收费的收费,自建网盘成了一个不得已的选择.可以自建私有网盘的网盘程序最出名的要数Seafile和Nextcloud,一款 ...

  4. Spring-整合MyBatis-声明式事务

    12.整合Mybatis 步骤: 导入相关jar包 junit mybatis mysql数据库 spring相关 aop织入 mybatis-spring[new] 编写配置文件 测试 12.1.会 ...

  5. React中setState的怪异行为 ——setState没有即时生效

    setState可以说是React中使用频率最高的一个函数了,我们都知道,React是通过管理状态来实现对组件的管理的,当this.setState()被调用的时候,React会重新调用render方 ...

  6. idea maven配置

    转载自:https://www.cnblogs.com/Silencepeng/p/7444012.html 一.下载maven的包 http://www.apache.org/ 1.在网页中打开上面 ...

  7. Find a multiple POJ - 2356 【鸽巢原理应用】

    Problem DescriptionThe input contains N natural (i.e. positive integer) numbers ( N <= 10000 ). E ...

  8. 一些特殊的矩阵快速幂 hdu5950 hdu3369 hdu 3483

    思想启发来自, 罗博士的根据递推公式构造系数矩阵用于快速幂 对于矩阵乘法和矩阵快速幂就不多重复了,网上很多博客都有讲解.主要来学习一下系数矩阵的构造 一开始,最一般的矩阵快速幂,要斐波那契数列Fn=F ...

  9. Luogu5327【ZJOI2019】语言【树上差分,线段树合并】

    题目大意 给定一棵$n$个节点的树,维护$n$个集合,一开始第$i$个集合只有节点$i$.有$m$个操作,每次操作输入一个$(u,v)$,表示将$(u,v)$这条链上所有点所属的集合合并.求有多少个无 ...

  10. C语言学习笔记8-函数

    C语言学习笔记8-函数  ...待编辑 1.汇编看函数调用过程 2.函数调用过程图示:学好C这个是关键,要懂得原理 标准调用(_cdecl) 参数由右往左入栈,调用者平衡栈(即入多少参数后参数调用玩后 ...