复制
主从复制先问延迟能不能接受。读自己的写,用“读主库”或“读自己的会话位点”,不要默认读从库。多主复制能写入近的机房,冲突要在业务层可解释,否则只是把问题推迟。
无主复制看的是法定人数。W+R 大于节点数,能提高读到最新值的概率,不是线性一致。故障时降低 quorum 等于主动接受过期读,这个决定要写进运维手册,不要到故障夜才改。
分区
按用户 ID 哈希,查询单用户很快,按时间范围扫会打到所有分区。按时间分区,热点会落在最新的那一块。复合键(用户 + 时间)是我后来更常用的折中。
再平衡会移动数据。自动迁移看着省事,磁盘和网络会被吃满。我倾向固定分区数,扩容时按计划搬,而不是让系统自己挑半夜。
事务
读已提交挡脏读,挡不住不可重复读。可重复读在 PostgreSQL 里是快照,和 MySQL 的间隙锁不是一回事。串行化最贵,只给“扣库存、记账”这类必须的路径。
分布式事务的两阶段提交会在协调者宕机时卡住。我现在默认:能用本地事务加消息表,就不用 XA。跨库的“看起来原子”,成本在运维,不在代码行数。
流处理
日志是事实来源,数据库表是物化视图。这句话帮我少做了几次“先改库再发消息”的双写。先写日志或 outbox,再投影到查询模型。
正好一次投递在跨系统时几乎做不到。做成“至少一次 + 幂等处理”。幂等键放在业务 ID 上,不要放在消息中间件自动生成的序号上。
这本书适合当词典,不适合当施工图。具体引擎的默认隔离级别,仍要读各自的官方文档。