CockroachDB学习笔记——[译]CockroachDB是如何进行分布式原子事务的
- 原文:How CockroachDB Does Distributed, Atomic Transactions
- 原文链接:https://www.cockroachlabs.com/blog/how-cockroachdb-distributes-atomic-transactions/
- 原作者: Matt Tracy
- 原文日期:Sep 2, 2015
- 译:zifeiy
CockroachDB是如何进行分布式原子事务的
CockroachDB的一个主要特性是他完全支持分布式数据库中任意键之间的ACID事务。
CockroachDB事务对数据库应用一系列的操作的同时,仍然能够保持ACID属性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
在这片文章中,我们将重点讨论CockroachDB如何在不适用锁的情况下实现原子事务。
__原子性(Atomicity)__可以被定义如下:
对于一组操作,要么全部执行,要么一个也不执行。
没有原子性的话,那些执行了一般的事务在被中断的情况下就可能只执行了部分修改。
策略(Strategy)
CockroachDB用于提供原子事务的测录遵循以下步骤:
- 开关(Switch):在修改任何键的值之前,事务创建一个开关,它是一个可写的值,不同于在批处理中改变的任何实际值。开关不能同时被访问——开关的读写是严格有序的。开关最初是“关(off)”的,它可以切换到“开(on)”的状态。
- 筹划(Stage):写进程对数据库进行一些列的改变,但是不覆盖任何已存在的值;新的值做好了替换旧的值的准备。
- 过滤(Filter):对于所有有筹划值(staged value)的键(key),读进程在获得该键对应的值之前不需要检测一下该事务的开关的状态。如果开关状态是“关(off)”,读进程将会该键的原始的值;如果开关状态是“开(on)”,读进程会返回筹划后的值。因此,所有对某一个键的读进程所获取到的值将直接取决于开关的状态。
- 快速切换(Flip):当写进程准备好了事务中的所有变化,写进程快速切换开关到“开(on)”状态。与过滤(Filter)相结合,所以该事务中的分级的值将做好准备返回给接下来所有的读进程。
- 取消筹划(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))。
作为最终规则,在任何键上只能有一个写意图。
如果有多个同时发生的存储过程,可能会发生一个存储过程在写一个键的数据,而与此同时这个键又对应了另一个存储过程中的一个活跃的写意图。
然而,事务并发是一个复杂的话题,我们将在以后的博客文章中讨论(《论事务隔离》);
而现在,我们假设一次只有一个事务,并且现有的写意图必须来自一个废弃的事务。
当写入已具有写入意图的键时:
- 如果已经存在的意图(intent)的事务记录(transaction record)是
PENDING状态的话,那么将其转换为ABORTED状态。如果之前的事务是COMMITED或ABORTED,那么什么都不做。 - 清除早期事务中的现有意图,这将删除意图。
- 为并发事务添加新的意图。
过滤(Filter):读取一个意图
在读取一个键时,必须遵循总体策略的原则3,并在返回值之前查阅任何开关的值。
如果键包含一个普通值(比如,不是一个写意图),读进程(reader)可以确信,没有涉及此键的事务正在进行中,
并且它包含最近提交的值。
因此,该值逐字返回。
但是,如果读进程读取到的是一个写意图,则意味着在删除意图之前,在某个点之前放弃了先前的事务(记住:我们已经假设过在同一时间只能进行一个存储过程)。
在继续之前,读进程需要先检查事务的开关的状态(事务记录)。
- 如果事务状态(transaction record)目前仍然是
PENDING则将其转换为ABORTED状态。 - 清除早期事务中的现有意图,这将删除意图。(译者注:前两步和stage阶段一样)
- 返回键所对应的普通值。如果早先的事务的状态是
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是如何进行分布式原子事务的的更多相关文章
- CockroachDB学习笔记——[译]CockroachDB中的SQL:映射表中数据到键值存储
CockroachDB学习笔记--[译]CockroachDB中的SQL:映射表中数据到键值存储 原文标题:SQL in CockroachDB: Mapping Table Data to Key- ...
- CockroachDB学习笔记——[译]如何优化Go语言中的垃圾回收
原文链接:https://www.cockroachlabs.com/blog/how-to-optimize-garbage-collection-in-go/ 原作者:Jessica Edward ...
- CockroachDB学习笔记——[译]在CockroachDB中如何让在线模式更改成为可能
原文链接:https://www.cockroachlabs.com/blog/how-online-schema-changes-are-possible-in-cockroachdb/ 原作者: ...
- CockroachDB学习笔记——[译]Cgo的成本与复杂性
原文链接:https://www.cockroachlabs.com/blog/the-cost-and-complexity-of-cgo/ 原作者:Tobias Schottdorf 原文日期:D ...
- CockroachDB学习笔记——[译]为什么Go语言是CockroachDB的正确选择
原文链接:https://www.cockroachlabs.com/blog/why-go-was-the-right-choice-for-cockroachdb/ 原作者:Jessica Edw ...
- CockroachDB学习笔记——[译]The New Stack:遇见CockroachDB,一个弹性SQL数据库
原文链接:https://www.cockroachlabs.com/blog/the-new-stack-meet-cockroachdb-the-resilient-sql-database/ 原 ...
- CockroachDB学习笔记——[译]Scaling Raft
原文链接:https://www.cockroachlabs.com/blog/scaling-raft/ 原作者:Ben Darnell 原文日期:Jun 11, 2015 译:zifeiy 在Co ...
- CockroachDB学习笔记——[译]Hello World
原文链接:https://www.cockroachlabs.com/blog/hello-world/ 原作者:Spencer Kimball 原文日期:Jun 4, 2015 译:zifeiy 数 ...
- .NetCore学习笔记:三、基于AspectCore的AOP事务管理
AOP(面向切面编程),通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑 ...
随机推荐
- Fillder的前后端的应用
测试需求:有一个功能,允许用钻石兑换金币,假设1钻石=1金币,前端控制一次至少兑换10个,最多100个,后台不做验证. 测试方案:输入10,也就是告诉前端我要兑换10个金币,等前端验证通过之后,截取要 ...
- linux(3)
一.用户和组的管理 Linux/Unix是多用户系统: root是超级用户,拥有最高权限.其它用户及权限由root来管理.对比Windows系统: 控制面板 -> 管理工具 -> 计算机管 ...
- Python3+Appium学习笔记07-元素定位工具UI Automator Viewer
这篇主要说下如何使用UI Automator Viewer这个工具来定位元素.这个工具是sdk自带的.在sdk安装目录Tools目录下找到uiautomatorviewer.bat并启动它 如果启 ...
- Java基础 IO流的文件和目录的五类主要操作
笔记: /** IO流的 文件和目录的操作 * 1.路径需要 需要两个反斜杠 或者一个单斜杠! * 绝对路径:包括盘符在内的完整的路径名! * 相对路径:在当前目录文件下的路径! * 2.File 是 ...
- http协议头
1. ctx->AddResponseHeader("Content-Type", "application/octet-stream"); ctx-&g ...
- Golang 本身是用什么语言写的?
原文:https://www.zhihu.com/question/66944175 ------------------------------- 首先,问题的说法是有问题的. golang本身是用 ...
- 1113 form表单与css选择器
目录 1.form表单 form元素 特点 参数 form元素内的控件 1.input的使用 2.select标签 3.textarea元素 4.autofocus属性 2.CSS 1.基础语法 cs ...
- Vue入门到出门
原来微信小程序的js跟这个差不多啊.这个也不像jQuery那种完全是为了方便写js的感觉,难道算前端框架?还不太了解,总之要先看看,然后用HBuilder快点上手做点东西…… ------------ ...
- keyup([[data],fn]) 当按钮被松开时,发生 keyup 事件。它发生在当前获得焦点的元素上。
keyup([[data],fn]) 概述 当按钮被松开时,发生 keyup 事件.它发生在当前获得焦点的元素上. 注释:如果在文档元素上进行设置,则无论元素是否获得焦点,该事件都会发生.直线电机选型 ...
- kafka 介绍与使用
在介绍为什么使用kafka之前,我们有必要来了解一下什么是kafka? 1. 什么是kafka? Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala编写,它以可水平扩展和高吞吐率 ...