扩展数据库写入的策略
Source: Dev.to
引言
在上一篇文章中,我们看到通过减少数据库每次查询需要完成的工作量来实现读的扩展。
写入面临的是另一类问题。
写入不仅仅是“存储这条数据”。它通常意味着:
- 更新索引
- 维护顺序
- 强制约束
- 检查关系
- 修改多个结构
随着写入流量的增加,数据库会变得写受限,因为每一次写入都迫使系统进行大量的组织工作。
因此,扩展写入的目标很简单:
让每一次写入尽可能轻量化。

扩展写入的核心思路
当数据库必须:
- 更新大量索引
- 维护严格的结构
- 执行同步检查
- 触及多个数据位置
时,写入会变慢。
策略: 通过推迟、分散或简化这些工作,减少写入时需要完成的工作量。下面的每一种技术都遵循这一思路。
1. 分片(水平分区)
将数据拆分到多个分片上,使每个分片只处理一部分写入负载。
为何有效: 如果一台机器能够处理 W 次写入/秒, N 个分片大约可以处理 N × W 次写入/秒。写入被分散,而不是在同一资源上竞争。
2. 批量写入
将大量写入合并在一起,而不是一次写入一条记录。
为何有效: 对数据库和磁盘而言,较大的顺序操作效率更高,能够降低每次写入的开销。
3. 异步写入
提前向客户端确认写入成功,将繁重的工作(索引、约束等)留到后台执行。
为何有效: 用户感知的延迟下降,数据库可以离线更高效地组织工作。
4. 预写日志(WAL)
在实际修改表之前,先将变更写入追加式日志。
为何有效: 向日志追加非常快,数据库随后再应用并组织这些变更。
5. 基于 LSM 的引擎
日志结构合并(LSM)树(如 Cassandra、RocksDB、LevelDB)先将数据写入内存,随后定期将已排序的数据刷新到磁盘。
为何有效: 写入在最初阶段非常快,排序和压实工作在之后进行,推迟了昂贵的操作。
6. 幂等写入
设计写入操作,使得重复执行同一操作不会产生不良影响。
为何有效: 重试、批处理和异步处理可以在不进行额外读‑写前检查的情况下进行。
7. 减少索引
仅保留真正必要的索引。
为何有效: 需要维护的结构越少,每次写入的工作量就越小。
所有这些技术背后的模式
所有策略共享一个共同原则:
通过减少即时的组织工作,使写入更便宜。
可以通过以下方式实现:
- 分散负载
- 延迟工作
- 简化结构
- 将随机写入转为顺序写入
结语
扩展写入并不是让数据库本身更快,而是让每一次写入更轻量。实现方式包括:
- 推迟结构维护
- 在分片或节点之间分散负载
- 顺序写入(批量)
- 避免不必要的工作(多余的索引、同步检查)