QCon 演讲火热征集中,快来分享技术实践与洞见! 了解详情
写点什么

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

  • 2015-09-11
  • 本文字数:1864 字

    阅读完需:约 6 分钟

作为一个分布式数据库, 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 读者交流群)。

2015-09-11 19:003850
用户头像

发布了 1008 篇内容, 共 397.6 次阅读, 收获喜欢 345 次。

关注

评论

发布
暂无评论
发现更多内容

B站疯传 Java面试题,24小时删

程序知音

Java java面试 java架构 后端技术 Java面试八股文

华为新机到手升级HarmonyOS 3,畅享多设备高效互联协同

Geek_2d6073

【简历优化】如何写好项目的亮点难点?项目经历怎么写最好?

王中阳Go

高效工作 学习方法 面试 简历模板 11月月更

JAVA concurrency -- AQS 源码详解

骑牛上青山

Java 源码

web前端培训上海学习好吗

小谷哥

哪些前端学习方法对小白比较有用?

小谷哥

数据挖掘、机器学习、深度学习的区别

九章云极DataCanvas

数据挖掘 机器学习 深度学习

Go语言—基本输入输出包的使用

良猿

Go golang 后端 11月月更

web前端培训学习需要注意什么

小谷哥

惊艳华为PocketS发布会! 杰美特旗下高端品牌决色推出首款“月光宝壳”

科技热闻

eBPF 实践 -- 网络可观测

观测云

搭建企业镜像仓库~Harbor

蜗牛也是牛

阿里内部高并发核心编程笔记:多线程、锁、JMM、JUC、设计模式

程序知音

高并发 java架构 后端技术 高并发架构

Docker安装minio(CentOS7)

蜗牛也是牛

直播预告|全闪文件存储在 AI 大数据领域的前沿应用

焱融科技

云计算 分布式系统 高性能 文件存储 全闪存储

微博评论高可用高性能计算架构设计

Jack

架构实战训练营9期

你需要知道的webpack高频面试题

Geek_02d948

webpack

【高并发全彩版小册】阿里内部大佬用7部分讲懂!百亿级高并发系统

程序知音

Java 高并发 java架构 后端技术 高并发架构

STL迭代器失效问题

Maybe_fl

5 分钟教你搭建「视频动作分类」系统

Zilliz

人工智能 计算机视觉 Towhee 视频动作分类

如何在大促中做好系统高可用

阿里巴巴云原生

阿里云 微服务 高可用 云原生网关

量化交易炒币机器人开发合约策略

薇電13242772558

量化策略

带你全面了解Gateway

好程序员IT教育

Spring Cloud Gateway SpringCloud Gateway

系统运维利器,百万服务器运维实战总结!一文了解最新版SysAK|龙蜥技术

OpenAnolis小助手

Linux 开源 运维 龙蜥社区 SysAK

大数据培训学习后,就业不好就业

小谷哥

java学习后该怎么培养自主学习能力

小谷哥

技术贴 | Rocksdb 中 Memtable 源码解析

KaiwuDB

数据库

启科量子 QuSprout 正式开源

启科量子开发者官方号

开源 量子计算 量子编程

面向智慧城市的GIS框架

tjn

GIS 可视化 11月月更

鼎医信息加入PolarDB开源数据库社区

阿里云数据库开源

阿里云 polarDB PolarDB-X 阿里云数据库 PolarDB for PostgreSQL

专为实时而生 — GreptimeDB 现已在 GitHub 正式开源

Greptime 格睿科技

开源 分布式 云原生 时序数据库 存算分离

CockroachDB是如何实现分布式原子事务的?_数据库_谢丽_InfoQ精选文章