这个是前年AWS re:Invent 2022 的内容, 有兴趣可以看这个链接: Aurora re:Invent 2022

这个是去年AWS re:Invent 2023 的内容, 有兴趣可以看这个链接: Aurora re:Invent 2023

AWS reInvent 2024 刚刚结束, 笔者作为数据库从业人员主要关注的是AWS Aurora 今年做了哪些改动, 今年最大的可能就是 Aurora DSQL 的发布了.

因此这个文章主要介绍 Aurora DSQL 的实现, 以及笔者的一些看法.

下面的内容主要分成 3 部分:

  1. snapshot isolation + EC2 TimeSync service + OCC

  2. Cross Region cache coherence

  3. Serverless

image-20241216042217470

在发布会上, Matt 介绍 DSQL 将多次 commit 合并成一次 commit, 从而实现了 90% 的性能提高, 那么 DSQL 是如何实现的呢?

主要通过 snapshot isolation + EC2 TimeSync service + OCC 实现.

具体做法原先一个事务中包含 10 条 SQL, 每一条 SQL 都需要和数据库交互, 需要对某一些行就先 row lock, 避免事务执行过程中被其他事务修改. 那么如果在跨 region 场景, 延迟可能到了 100ms 以上, 一个事务包含 10 条 SQL 那么就至少需要 1s 才能 commit, 那么自然很容易出现性能问题.

DSQL 的做法通过 snapshot isolation + EC2 TimySync service 获取 t(start) 的版本信息, 然后在提交的时候通过 OCC(optimistic concurrency control) 进行冲突检测, 如果没有冲突, 那么就直接进行 commit, 如果有冲突, 那么就需要业务层进行回滚+重试操作了.

因此这次只需要在 commit 的时候, 需要和数据库交互, 10 条 SQL 执行过程中, 都读取当前 AZ 的 snapshot 出来的版本就可以了, 这就是 Matt 讲的可以优化 90% 的实现方式.

但是真实的场景是这样的么?

其实 OCC 并没有想象的那么好, 其实很早就有讨论基于 OCC 的数据库的并发控制机制实现, “On Optimistic Methods for Concurrency Control” in 1979 by H.T. Kung and John T. Robinson 已经介绍了. 但是一直没有大规模被使用主要由于,

OCC适合于交互式或系统内部组件同步延时较大的场景, 之前大部分数据库都是一体化设计, 计算, 存储, 内存等等都在本地, 因此开销并不大, OCC 冲突导致事务中止浪费计算资源的开销远大于同步操作的开销, 所以没有大规模使用.

那么在跨 region 类似 DSQL 这样场景可以使用吗?

理论上在跨 region 场景 OCC 可以比之前一体化设计数据库有更多的收益, 而且工程实现会更加的简单.

但是可以理解这里把处理冲突的方式交给了用户, 比如目前 DSQL 的事务的大小是有限制的, 一个事务默认最多能够支持修改 10000 行, 事务最长时间为 5 分钟.

用户需要知道直接的业务场景是否有明显的冲突, 做过云数据库的都知道很多时候业务根本不知道这些 SQL 是谁写的了, 另外需要用户实现类似重试逻辑, 但是 Aurora DSQL 作为云厂商售卖的数据库, 用户已经习惯使用Pessimistic Concurrency Control (PCC) 的冲突检测方式, 需要针对 Aurora DSQL 去重新修改代码, 在现在多云的背景下, 用户又不希望被厂商 Lock in, 那么就更不可能了.

从技术角度可以看为什么 DSQL 选择了 OCC.

可以猜测的原因更多是从工程的角度去考虑, 更易于实现, 减少维护成本, 减少了全局 lock service.

因为如果选择 PCC 的话, 那么需要为了一个全局锁服务, 写入都需要去全局 lock service 去获得, 这么首先是开销, 另外是还需要额外维护全局锁服务. 而使用 OCC 则不需要, 就像在 Matt 介绍场景一样, 在写入的时候, 对于每一行写入的数据仅仅在 commit 的时候, 在行上去判断是否有冲突即可, 确实大量减少交互次数, 对于延迟高的跨 Region 场景收益会更大.

另外这里有一点没有提到, 就是如何处理多个 Region cache coherence 的问题?

下面这个图是 Aurora 和 Aurora DSQL 的对比.

image-20241209050254992

Aurora 里面 Log & blocks 是放在一起存储的, Aurora DSQL 里面将 log store 和 block store 分开存储, 因为 log 写入和 page 写入其实是两个非常不一样的 IO 方式, log 写入主要是 append only, page 写入是随机 IO, 其实大部分 Aurora 后来的云数据库都实现了类似的方式, 比如 socrate, taurusDB 等等.

其实早年在 PolarDB 我们也考虑将 log/page 放在不同的存储里面, 这样的实现有诸多好处, 唯独增加了复杂度.

比如需要考虑 log 和 page 快照一致性问题, 需要考虑维护两个存储池子, log store 使用的机型应该更好, 而 page store 使用的机型可以差一些等等, 一旦需要分池, 那么云计算最大的池化的优势也就没有了. 所以后面也就没有这样实现.

除了这个差异, 其实这里两个架构最大的区别是, 在 Aurora DSQL 里面取消了每一个实例上面的cache

我们知道在一写多读架构下面, 多个节点之间 cache 一致性是一个比较大的问题.

比如在 rw 节点写入 a = 100 (old value = 99) 以后.

在 ro 节点去读取 a 的值, 这个时候有两种情况:

  1. a 不在 ro 节点的 cache 里面, 那么就需要从底下的 storage 去读取 a 的值, 这个时候会根据 ro 节点 lsn 信息, 应用到指定版本的 lsn 从而获得 a 的 value.
  2. 该 ro 节点的内存中已经有 old value a = 99, 那么这个时候需要判断当前 ro 节点的 apply_lsn 信息, 如果 apply_lsn 还没到 rw 节点写入(a = 100) 的位点信息, 那么此时可以直接返回, 如果 ro apply_lsn > rw (a=100) lsn, 那么就需要从底下 storage log 读取对应的 redo log 信息, 应用到指定的 lsn 然后再返回给客户.

从上面的例子可以看到, 在一写多读的架构下, 需要保证 cache 中的数据是一致的, 才可以避免 ro 节点读取到错误版本的数据, 从而导致读取出错.

那么其实在多节点写入的架构下面其实一样存在这样的问题, 而且这个问题会更加的严重, 因为同样要解决多个节点之间的 cache 一致性问题.

那么 DSQL 怎么解决?

非常的暴力, 直接取消了这个 cache, 也就是这个 buffer pool 不存在了, 所有的读取和写入都直接到 DSQL - block store 上.

那么带来的问题是, 这样 block store 的性能是否可以?

在一写多读下, 直接读取 cache 中的内容就可以返回, 那么在 DSQL 的架构下, 需要读取的都不是本地存储, 而是远端的 block store, 本地 内存读取的延迟差不多是百 ns 级别, 而远端存储访问, 即使是 RDMA 优化过后, 也需要 100us 左右. 这样的延迟几乎大了 1 千倍, 这是几乎不可能接受的事情.

为了解决 DSQL 没有 cache 的问题, DSQL 实现了很多的计算下推操作, RW 节点和 block store 请求的不再是 Page, 而是具体的某一行, 这样可能尽可能减少需要请求的 page, 提高性能.

但是大部分线上 OLTP 的场景, 很多时候返回的也都是某一行, 只需要一个 page 即可, 虽然返回某一行可以减少需要返回的内容, 但是在带宽足够的情况下, 这里收益并不明显. 另外这里其实也给 block store 增加了复杂度.

还有一个比较差别的点可能跟Marc Brooker 有关, Marc Brooker 在 AWS 做了 10 年的 Lambda, 所以对 serverless 有执念.

DSQL 在 serverless 上比 Aurora 更彻底, DSQL 的实例在有请求的时候, 通过 Firecracker 启动一个实例, 在执行完请求以后, 直接就将实例释放, 由于没有 cache 的存在, 并且使用的是 OCC 计算节点几乎没有保留任何有状态的信息, 那么在连接关闭以后, 这个节点就可以直接关掉了, 所在这里可以做到秒级别的 serverless.

而传统 Aurora 差不多需要的时间是 5min 级别.

对于在 Global database 场景, Aurora DSQL 使用了和跨 AZ 场景, 几乎一样的能力. 由于跨 region 场景, 延迟更高因此 OCC 带来的性能收益也更加明显.

image-20241216005352899

笔者观点:

从上面的原理介绍我们可以看到 Aurora DSQL 由于减少了 cache 层, 延迟会增加, 使用 OCC 那么用户使用的复杂度会增加. 因此笔者认为Aurora DSQL 的使用场景其实是有限, 需要对延迟不敏感, 业务上很少存在热点数据, 并且业务开发人员需要有较强的开发能力, 能够实现业务层的重试机制, 业务范围很大, 需要分布多个 region 这样的场景. 否则大部分情况下 AWS RDS or Aurora 就够了.

Reference:

1: AWS re:Invent 2024 - CEO Keynote with Matt Garman

2: DSQL Vignette: Aurora DSQL, and A Personal Story

3: DSQL Vignette: Reads and Compute

4: DSQL Vignette: Transactions and Durability

5: DSQL Vignette: Wait! Isn’t That Impossible?

6: AWS re:Invent 2024 - Deep dive into Amazon Aurora and its innovations (DAT405)


<
Previous Post
MySQL B-tree Height Issues in Large Single Tables
>
Blog Archive
Archive of all previous blog posts