BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

CockroachDB是如何实现分布式原子事务的?

| 作者 谢丽 关注 12 他的粉丝 发布于 2015年9月12日. 估计阅读时间: 6 分钟 | AICon 关注机器学习、计算机视觉、NLP、自动驾驶等20+AI热点技术和最新落地成功案例。

作为一个分布式数据库,CockroachDB有一个鲜明的特性,就是支持ACID事务。近日,Cockroach Labs团队成员Matt Tracy撰文介绍了CockroachDB如何在不使用锁的情况下实现原子事务。

CockroachDB的原子事务策略总共包含如下五个基本步骤。

1.“开关(Switch)”:CockroachDB事务记录

在开始一个事务之前,写进程首先会创建一个包含如下字段的事务记录

  • 事务唯一标识UUID
  • 事务当前状态,可以有三种取值,其中PENDING为初始状态,ABORTED或COMMITTED为终止状态
  • 一个Cockroach K/V键,指定“开关”在分布式数据存储中的位置

写进程会使用一个专门的CockroachDB命令BeginTransaction()存储事务记录。事务记录或者开关不能并行访问,只能严格按照顺序进行读/写操作。事务记录的PENDING或ABORTED状态对应开关的“off”状态,COMMITTED对应“on”。

2.“暂存(Stage)”:Write Intent

写进程会准备好多个数据库变更,但并不会覆盖任何现有值。为了暂存一个事务中的变更,CockroachDB使用了一个名为Write Intent的结构。任何时候,一个值作为一个事务的一部分写入到一个键,它都会生成一个Write Intent。Write Intent结构中还包含指示事务记录存储位置的键。

另外,还有一个规则,就是任何键都有且仅有一个Write Intent(Matt在此并未考虑事务并发)。

3.“过滤(Filter)”:读取Write Intent

对于任何有暂存值的键,在读取时都必须检查事务开关的状态。如果开关状态为“off”,则返回该键的原值;如果开关状态为“on”,则返回暂存值。也就是说,如果一个键有暂存值,那么对该键的所有读取操作都必须使用开关状态过滤,具体步骤如下:

  1. 如果现有Write Intent对应的事务记录仍然处于PENDING状态,则将其置为ABORTED状态。
  2. “清除(cleanup)”现有的Write Intent。
  3. 返回该键的普通值(即不是Write Intent)。如果之前的事务已经COMMITTED,那么清除操作会将暂存值升级为普通值;否者,返回该键的原值。

4.“按开关(Flip)”:提交事务

当写进程准备好事务中的所有变更后,它会打开开关(即将事务记录更新成COMMITTED,开关状态置为“on”)。事务生成的所有Write Intent都会立即生效;之后发生的任何读取操作在看到事务已经提交后都会返回Write Intent中的暂存值。

另外,将事务记录的状态置为ABORTED可以终止事务,之后发生的读取操作将忽略这个事务生成的Write Intent。

5.“解除暂存(Unstage)”:清除Write Intent

前面4个步骤已经可以提供原子事务;但是,第2步开销很大,因此,在事务完成后,CockroachDB会尽快清除暂存值。如果事务成功,那么暂存值会取代原值;如果失败,那么暂存值会被丢弃。总之,如果一个键没有Write Intent,那么读取操作就无需过滤,也就可以以适当的分布式方式完成。需要注意的是,解除暂存是异步的,并不需要在事务COMMITTED之前完成。

网友RJ Ryan对Matt所谓的“无锁(lockless)”提出了质疑。他认为,开关和Write Intent看起来跟锁类似。对此,Matt答复说:

这篇博文谈到“锁”时,是指数据库记录锁,一个修改数据库某个部分的独占性许可。

开关(或事务记录)并不是一个数据库锁,因为它没有阻止其它数据库操作进行……对开关本身的操作会按顺序进行……但它不会阻止任何操作执行。

Write Intent也不是数据库锁,因为它不会保证键的独占性访问;相反,它允许一个事务“发现”其它正在访问相同键的并发事务。当这种情况出现时,其中一个事务必须终止;不过,它并没有像锁一样采用“先来先服务”的策略,而是为每个事务赋予一个数值型的优先级,优先级最高的事务总是会胜出。

Matt指出,如果读者对CockroachDB的完整事务模型感兴趣,可以查看GitHub上的详细设计文档Tobias Schottdorf也是CockroachDB项目的贡献者。他在回复网友的评论时指出,虽然CockroachDB的原子事务策略与使用MS-DTC的SQL Server分布式事务处理一样都是2PC,但它们并不相同。XA有准备和提交两个阶段,提交阶段实际上要做大量的工作。但在Cockroach中,“准备”阶段就将值写到了它们最终应该存在的位置,所以“提交”阶段只需要对单个键执行一次写操作,几乎不做什么工作。

另外,在介绍完CockroachDB的原子事务策略后,Matt还特别介绍了CockroachDB的清除操作,感兴趣的读者可以进一步阅读


感谢郭蕾对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ@丁晓昀),微信(微信号:InfoQChina)关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入InfoQ读者交流群InfoQ好读者)。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT