现状观察:MariaDB 不是云原生的
坦白说:MariaDB / MySQL 目前的形态不是云原生数据库。它们被设计为在单台服务器上使用本地存储运行。即使是主从复制架构,本质上也是每个节点的完整数据副本。
在云环境中,这带来了几个根本性问题:
- 存储与计算耦合。 如果你需要更多 CPU,就必须配置一台带有全部存储的新服务器。如果你需要更多存储,就必须调整服务器规格。
- 水平扩展受限。 每个副本包含完整的数据副本。添加一个 2 TB 的从库意味着复制 2 TB 的数据。
- 故障切换意味着停机。 提升从库涉及收敛时间,在此期间最新的写入可能丢失(在异步复制中)或集群不可用(在同步复制中)。
现代云原生数据库如 Amazon Aurora、Google AlloyDB 或 PostgreSQL Neon 通过将计算与存储解耦解决了这些问题。
灵感来源:PostgreSQL Neon
PostgreSQL Neon 是一个引人入胜的项目。它将 PostgreSQL 的本地存储层替换为远程分布式存储。PostgreSQL 引擎作为纯计算节点运行:它接收查询、规划执行,并通过网络与远程存储服务交换数据页。
优势是惊人的:
- 即时扩展:添加计算节点无需数据复制
- 分支:创建数据库"分支"(如 Git 分支)是瞬时的——这是元数据操作,不是物理复制
- 按需付费:不活跃的计算节点会被停止,你只为存储付费
MariaDB 能走同样的道路吗?
Handler API:天然的解耦点
MariaDB 拥有 PostgreSQL 所没有的独特架构优势:handler API。它是 SQL 引擎(解析器、优化器、执行器)与存储引擎(InnoDB、Aria、RocksDB、ColumnStore 等)之间的抽象接口。
handler API 定义了如下操作:
handler::ha_open() // 打开一个表
handler::ha_read_first() // 读取第一行
handler::ha_read_next() // 读取下一行
handler::ha_write_row() // 写入一行
handler::ha_update_row() // 更新一行
handler::ha_delete_row() // 删除一行
handler::ha_index_read() // 基于索引读取
每个存储引擎都实现这些方法。InnoDB 通过访问本地 B-tree 页来实现。Aria 有不同的实现。RocksDB 使用 LSM-tree。
如果一个存储引擎通过网络访问远程页来实现这些方法呢?
PolarDB 方案(阿里巴巴)
阿里巴巴已经通过 PolarDB 证明了这是可行的,PolarDB 基于 MySQL 源码。PolarDB 使用:
- 替代本地存储的分布式文件系统(PolarFS)
- 用于持久性的共识协议(Raft)
- 计算节点之间的共享页缓存
结果是一个存储与计算解耦的 MySQL。多个计算节点可以同时读取相同的数据,单个节点处理写入。
PolarDB 表明 MariaDB/MySQL 的 handler API 是一个可行的解耦点。阿里巴巴没有重写 SQL 引擎——他们实现了一个访问远程存储的 handler。
愿景:MariaDB 的远程 Handler API
设想一个名为 RemoteStore 的 MariaDB 存储引擎:
CREATE TABLE users (
id BIGINT PRIMARY KEY,
name VARCHAR(255)
) ENGINE=RemoteStore
CONNECTION='storage-cluster.internal:9000/db1';
这个存储引擎没有本地数据。每个 handler API 调用都会被转换为对分布式存储服务的网络调用。存储服务将管理:
- 数据复制(至少 3 份副本)
- 持久性(分布式预写日志)
- 快照和分支
- 压缩和分层(热数据在 SSD 上,冷数据在 S3 上)
编译不含内嵌引擎的 MariaDB
实现这一愿景的第一步是编译不含任何内嵌存储引擎的 MariaDB。目前,InnoDB 被编译进 mariadbd 二进制文件中。编译选项允许禁用某些引擎,但 InnoDB 仍然深度集成。
一个"无头"MariaDB——一个纯 SQL 引擎,不含存储——将是这样的:
MariaDB SQL 引擎(解析器 + 优化器 + 执行器)
↓ handler API
插件: RemoteStore → 网络 → 分布式存储
这个无头 MariaDB 将是轻量级的(几百 MB 内存),可以在毫秒内启动,并可以作为无状态容器部署在 Kubernetes 中。
技术挑战
这一愿景并非没有挑战:
网络延迟
每次页面访问都要经过网络。数据中心网络延迟在 100 到 500 微秒量级。这比本地 SSD 访问慢 100 到 1,000 倍。计算节点层面的激进页面缓存是必不可少的。
锁管理
InnoDB 在本地管理锁。在共享远程存储中,锁管理必须是分布式的。这是一个困难的问题,可能引入额外的死锁和超时。
分布式缓冲池
InnoDB 的缓冲池是本地的。在云原生架构中,需要计算节点之间的缓存失效机制。当一个节点写入页面时,其他节点的缓存必须被失效。
事务日志
InnoDB 的 redo log 和 undo log 是本地的。在解耦架构中,WAL 必须是分布式的,且所有节点都可以访问。
现有的组件
这一愿景的某些组件已经存在于 MariaDB 生态系统中:
- MariaDB ColumnStore:一个列式存储引擎,可以使用 S3 存储
- Spider:一个将数据分布到多个 MariaDB 服务器上的存储引擎
- CONNECT:一个可以访问外部数据源的存储引擎
这些引擎都没有实现完全的计算/存储解耦,但它们展示了 handler API 的灵活性。
结论
让 MariaDB 成为云原生是一个雄心勃勃但并非不切实际的挑战。handler API 提供了一个天然的解耦点,这是 PostgreSQL 和 Oracle MySQL 都没有以如此清晰形式具备的。
阿里巴巴的 PolarDB 证明了它在技术上是可行的。PostgreSQL Neon 证明了市场需要它。问题不是"是否可能?"而是"MariaDB 社区中谁会第一个做到?"
当 MariaDB 能够作为一个 200 MB 的无状态容器启动,连接到分布式存储,并在毫秒内响应查询的那一天——游戏规则就改变了。
本文最初发表于 Medium。
评论 (0)
暂无评论。
发表评论