今年在拉斯维加斯参加 2024 年的 Amazon Web Services re:Invent 时,我作为一名长期从事分布式数据库研发的工程师,对亚马逊云科技在数据库领域的最新进展和未来方向充满期待。在今年的 re:Invent 上,Aurora DSQL(下文简称 DSQL)的发布无疑成为全场焦点,从 Amazon Web Services CEO 的主题演讲到我个人非常钦佩的 Amazon CTO Werner Vogels 的 keynote,都对 DSQL 进行了深入介绍。毫不夸张地说,今年的 re:Invent 完全可以称为一场分布式数据库的盛宴。
### 初识 Aurora DSQL
在周二的 Amazon Web Services CEO Matt Garman 的主题演讲中,亚马逊云科技首次公布了 DSQL 的预览版。当屏幕上出现这一信息时,我确实有些兴奋。一直以来,Aurora 能做的事情已经很多,为什么还需要一个全新的分布式数据库?这次亚马逊云科技自己给出了答案:面对更极致的可扩展性需求和复杂的应用场景,当前的 Aurora 存在无法轻易解决的难题。客户需要一款真正分布式的数据库去满足这些全新的挑战。而这也正是 TiDB 等分布式数据库的价值所在。
![image.png](https://dev-media.amazoncloud.cn/00794781093c412492da88b5ef769ed5_image.png "image.png")
从现场介绍中,我看到 DSQL 拥有近乎无限的可扩展性、跨区域的 5 个 9 可用性以及与 PostgreSQL 协议兼容的特性。当时台下掌声雷动。但作为一名开发数据库的工程师,我更关心的是:DSQL 到底是如何实现的。
![image.png](https://dev-media.amazoncloud.cn/6a2070f70fb84ee18a7005dde70eb0f9_image.png "image.png")
### 第一次体验 DSQL
在 keynote 结束后,我迫不及待地登录自己的亚马逊云科技账号,新建了两个 DSQL 集群,一个是单 Region,另一个则是多 Region(由于目前仍是预览版,支持的 Region 非常有限)。整个集群创建流程还算流畅,大约两分钟后,集群便已就绪。
![image.png](https://dev-media.amazoncloud.cn/191a6c5034934a4ab6591beedb3a8962_image.png "image.png")
我在 Connect 页面获得连接信息后,直接用 psql 登入,查看版本发现 DSQL 是基于 PostgreSQL 16.5 开发的。
psql "host='$PGHOST' port=5432 dbname=postgres user=admin
password='$PGPASSWORD' sslmode=require"
postgres=> SHOW server_version;
server_version
— — —
16.5
然而初步体验并不顺畅。我习惯先用 sysbench 对新数据库进行初步性能测试,但却发现 sysbench 运行不了。因为在 PostgreSQL 测试中,sysbench 默认使用 SERIAL 主键类型,而 DSQL 并不支持 SERIAL。我查阅了文档,发现 DSQL 还有许多不支持的特性,例如不支持 JSON 类型。这多少让人有些失望:所谓的 PostgreSQL 兼容,仅仅是协议层面,许多常用功能目前还不能用(参考 [Unsupported PostgreSQL features in Aurora DSQL - Amazon Aurora DSQL](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/working-with-postgresql-compatibility-unsupported-features.html?trk=cndc-detail))。这对已在 PostgreSQL 或 Aurora 上成熟运行的用户来说,会增加迁移成本。
我尝试通过 auto_inc=off 规避 SERIAL 问题,但很快又遇到新的障碍:DSQL 不允许在已有数据的表上创建索引。只能使用 CREATE INDEX ASYNC ([Creating async indexes in Aurora DSQL - Amazon Aurora DSQL](https://docs.aws.amazon.com/aurora-dsql/latest/userguide/working-with-create-index-async.html?trk=cndc-detail)) 语句,而没有一个同步“封装” —— 这对用户体验来说很不友好,也会给迁移带来障碍。最后,我通过设置 create_secondary=off 绕过索引创建问题,终于能在 DSQL 上跑起 sysbench。但整个过程令人感到 DSQL 的用户体验仍有很大的改进空间。这些功能缺失和兼容性问题短期内或许难以彻底改善,也势必影响 Aurora 现有用户的无缝迁移,当然我也期待他们能快速的解决这些问题。
### DSQL 的架构剖析
作为研发工程师,在简单体验后,我最关心的还是 DSQL 的内部架构及实现细节。亚马逊云科技官方及 DSQL 的开发者 Marc Brooker 提供了一些介绍文章,链接如下:
- [Introducing Amazon Aurora DSQL | Amazon Web Services](https://aws.amazon.com/cn/blogs/database/introducing-amazon-aurora-dsql/?trk=cndc-detail)
- [DSQL Vignette: Aurora DSQL, and A Personal Story - Marc's Blog](https://brooker.co.za/blog/2024/12/03/aurora-dsql.html?trk=cndc-detail)
- [DSQL Vignette: Reads and Compute - Marc's Blog](https://brooker.co.za/blog/2024/12/04/inside-dsql.html?trk=cndc-detail)
- [DSQL Vignette: Transactions and Durability - Marc's Blog](https://brooker.co.za/blog/2024/12/05/inside-dsql-writes.html?trk=cndc-detail)
- [DSQL Vignette: Wait! Isn't That Impossible? - Marc's Blog](https://brooker.co.za/blog/2024/12/06/inside-dsql-cap.html?trk=cndc-detail)
DSQL 的架构图显示了清晰的三层结构:最上层是基于 PostgreSQL 引擎的计算层(Compute Layer),下面是 Transaction Log 与 Storage 层。
![image.png](https://dev-media.amazoncloud.cn/830553fe8cd6420690b7adf6416b6ba3_image.png "image.png")
尤其值得关注的是中间的事务日志层(Transaction Log Layer),由 Adjudicator 和 Journal 两个组件组成。
![image.png](https://dev-media.amazoncloud.cn/b910bb0bfc714613ab3d606b3fd6893a_image.png "image.png")
Storage 层未有太多细节披露,但已知它内部实现了 MVCC(多版本并发控制),可能是基于 LSM-tree(类似 RocksDB)实现,从而为 Snapshot 隔离读提供支持。这样一来,只要事务有了一个全局时钟戳(通过亚马逊云科技自己的高精度时钟实现),便能在 Storage 层读到对应版本的数据。
![image.png](https://dev-media.amazoncloud.cn/8ed56bec600e498e951b09d33fa6ff80_image.png "image.png")
对于分布式事务来说,写操作才是真正的挑战。DSQL 采用乐观并发控制(OCC)。当提交事务时,Query Processor 会将变更发送给 Adjudicator,Adjudicator 会跟其它 Adjudicator 协调,确保没有其他事务在相同时间戳前对这些数据行进行写入。这一过程如果顺利,便将事务记录写入 Journal。Journal 作为日志服务,保证事务的原子性和持久化,一旦写入成功,事务即可对外宣告提交成功。
DSQL 里面的 Journal 应该使用的是 Amazon Web Services MemoryDB 里面同样的 log service (相关论文:[Amazon MemoryDB: A Fast and Durable Memory-First Cloud Database](https://assets.amazon.science/e0/1b/ba6c28034babbc1b18f54aa8102e/amazon-memorydb-a-fast-and-durable-memory-first-cloud-database.pdf?trk=cndc-detail)),后面可以在具体的分析下如何实现的。
![image.png](https://dev-media.amazoncloud.cn/4821c5882816465ba454fbd3dc5901e3_image.png "image.png")
Storage 层节点则订阅 Journal 日志,以异步方式更新自身数据。当然,这里可能会有一个时间差,譬如给客户返回写成功了,客户立刻发起读请求,而这时候 Storage 还没订阅到最新的更新,如何读取到最新的数据,是一个挑战。这里可能的做法是 Adjudicator 用心跳等的方式,实时的让 Storage 去快速拉取更新,而读请求会等 Storage 从 Journal 同步到对应的更新之后,才能读取等。
DSQL 的整体设计优雅且简单明了,但这并非彻底创新之举。从架构上看,与 FoundationDB 有诸多相似之处,而这种架构也带来了一些限制:
- 难以优雅支持长事务:在某些金融、批处理、数据分析场景中,长事务是刚需。长事务在 OCC 模型下存在诸多性能与实现难题,这也是日后 DSQL 必须面对和解决的问题。
- 悲观事务支持困难:大多数现实应用在复杂读写、竞争强烈的场景中往往需要悲观锁定策略。TiDB 最初只提供乐观事务,后来发现这对用户和应用迁移不够友好,最终在后续版本默认提供悲观事务支持。DSQL 的 OCC 模型未来是否会同样面临这方面的挑战?答案恐怕是肯定的。
### 写在最后
在今年的 re:Invent 期间,我将大部分精力都花在研究 Aurora DSQL 上。坦率地说,目前的 DSQL 在产品成熟度、功能完整性以及用户体验上仍不如 CockroachDB 和 YugabyteDB 等同类分布式数据库成熟。从官方团队的表态来看,他们希望在 6 个月内完成 GA(正式商用),我个人对此仍持保留态。
然而,DSQL 的推出本身对整个分布式数据库领域是积极信号。连 Aurora 都不得不考虑提供分布式关系型数据库,证明现实中有大量客户正面临可扩展性瓶颈。而这恰恰是 TiDB 等分布式数据库的强项。欢迎更多企业和开发者加入分布式数据库的世界,探索云时代下下一代数据库的未来。