数据存储与一致性考量

存什么、怎么存、多一致? 关系型NoSQL各有适用场景:关系型擅长事务与复杂查询,NoSQL 分键值、文档、列式、图等,擅长扩展与特定访问模式。事务与一致性ACID 保证单机强一致,CAP 说分布式下 C/A/P 难兼得,最终一致性用补偿与幂等换可用与扩展。读写分离、分库分表是常见扩展手段;数据迁移与版本管理则保证 schema 与数据变更可追溯、可回滚。本章把这些串起来讲。

一、关系型与 NoSQL 的选型

关系型数据库(如 MySQL、PostgreSQL):结构化表、SQL、ACID 事务、外键与约束。适合强一致、多表关联、复杂查询、报表。单机或主从扩展,垂直扩展为主。

NoSQL 是一类非关系型存储的统称,常见几类:键值(Redis、DynamoDB)——简单 get/set、缓存与会话;文档(MongoDB、Couchbase)——JSON 文档、灵活 schema、适合读多写少与嵌套结构;列式(HBase、Cassandra)——按列存储、适合分析与大宽表;(Neo4j)——节点与边、适合关系与路径查询。选型看访问模式、一致性要求、扩展方式与团队能力;不少系统是「关系型主库 + NoSQL 缓存/检索」的混合架构。

关系型 Relational
表结构、SQL、ACID、关联查询。适合强一致、复杂查询与报表;垂直或主从扩展。
NoSQL(键值/文档/列/图)
按访问模式选:键值做缓存、文档做灵活结构、列式做分析、图做关系查询;常与关系型混合。
存储选型概览
Key-Value Document Column Graph
NoSQL 常见类型

二、事务与一致性:ACID、CAP、最终一致性

ACIDAtomicity 原子性(要么全成功要么全回滚)、Consistency 一致性(业务约束在事务前后成立)、Isolation 隔离性(并发事务互不干扰)、Durability 持久性(提交后落盘不丢)。关系型单机事务通常提供 ACID;跨库或跨服务则难以用「一个事务」兜住,需要 saga、补偿、最终一致等模式。

CAP:在分布式系统中,Consistency(所有节点看到同一份最新数据)、Availability(每个请求都能得到响应)、Partition tolerance(网络分区时系统仍能工作)三者不能同时满足。实践中 P 常必须接受(网络会分区),于是多在 CP(强一致、允许不可用)与 AP(高可用、接受最终一致)之间取舍。例如 CP 型:强一致数据库主节点;AP 型:多副本最终一致、冲突用版本或业务规则解决。

最终一致性:不要求每次读都拿到「刚写完」的结果,允许短暂不一致,通过异步复制与重试在一段时间后达到一致。适合读多写少、可接受延迟一致的场景;要配合幂等、补偿与对账,避免脏读导致业务错误。

ACID 简记

  • Atomicity:事务内全部成功或全部回滚
  • Consistency:事务前后业务约束成立
  • Isolation:并发事务互不干扰
  • Durability:提交后持久化不丢
CAP:一致性、可用性、分区容错

CAP 与选型

分区容错(P)通常无法放弃,因此实际在 CP(强一致、可能不可用)与 AP(高可用、最终一致)间选。强一致主库选 CP;多活、缓存、最终一致存储选 AP,用幂等与补偿保证业务正确。

三、读写分离、分库分表入门

读写分离:主库负责写,从库(副本)负责读,通过主从复制同步。写少读多时能显著减轻主库压力、提高读吞吐。注意从库有复制延迟,读到的可能是稍旧数据,适合可接受短暂滞后的场景;强一致读仍要走主库或带主库位点的读。

分库分表:当单库单表成为瓶颈时,按规则把数据拆到多个库/表。分表:同一库内多表(如按用户 ID 取模);分库:多库,每库可再分表。拆分维度常见有按范围、按 hash/取模;要避免热点、考虑跨库 join 与事务(尽量同库完成或用应用层拼装)。分库分表后,路由、扩容与迁移都会变复杂,需提前设计好键与路由策略。

读写分离与分库分表示意

四、数据迁移与版本管理

Schema 变更:加列、加索引、改类型等要有可回滚方案。加列尽量先可空或带默认值,再 backfill;删列先废弃、再停用、最后删。大表加索引可在线进行(不同数据库支持不同)或低峰执行,避免锁表过久。

数据迁移:大批量数据迁移(换库、拆库、归档)常用双写 + 同步 + 校验 + 切流:先双写新旧两处,再同步历史、对账一致,最后读切到新处、停旧写。迁移脚本要可重试、幂等,并有回滚预案。版本管理:用迁移工具(如 Flyway、Liquibase、Alembic)把 schema 变更写成版本化的脚本,在部署时按顺序执行,便于追溯与回滚。

迁移与版本要点

  • Schema 变更:加列可空/默认、删列先废弃再删;大表索引注意锁与时长
  • 数据迁移:双写 → 同步历史 → 对账 → 切读/停旧写;脚本幂等、可回滚
  • 版本化迁移脚本(Flyway/Liquibase 等),部署时按序执行,可追溯

一句话: 关系型强一致与复杂查询,NoSQL按访问模式选键值/文档/列/图,常与关系型混合。ACID 单机强一致,CAP 下多选 CP 或 AP,最终一致性配幂等与补偿。读写分离扩读,分库分表扩写与容量;迁移与版本要可回滚、可追溯。

小贴士: 分库分表后尽量让「一次请求」只打一个分片,避免跨库 join 与分布式事务;设计时把分片键(如 user_id)放进业务主查询条件。

五、小结

存储选型:关系型与 NoSQL(键值/文档/列/图)按场景与访问模式选,可混合。一致性:ACID 单机、CAP 取舍、最终一致与补偿。扩展:读写分离扩读、分库分表扩写与容量,注意延迟与路由。迁移与版本:Schema 变更可回滚、数据迁移双写对账切流、版本化脚本可追溯。下一章讲可扩展性、高可用与性能设计,把扩展方式、高可用手段与性能设计思路串起来。