Chapter 05

数据库设计与扩展

数据是系统的核心。掌握关系型与 NoSQL 的选型逻辑,
理解分片、复制与分布式数据库的工作原理。

关系型 vs NoSQL:如何选型

没有最好的数据库,只有最合适的数据库。选型前先问清楚三个问题:数据结构固定吗?需要事务吗?读写比例是多少?

维度 关系型(MySQL/PostgreSQL) NoSQL(MongoDB/Cassandra/Redis)
数据模型 表结构,Schema 固定,关联通过 JOIN 文档/KV/列族/图,Schema 灵活
事务 ACID,支持复杂多表事务 大多数仅支持单文档/单行原子性
查询能力 SQL,任意条件查询,JOIN 强大 按 Key 查询为主,JOIN 弱或不支持
扩展方式 主要垂直扩展,分片复杂 原生水平扩展,分布式友好
一致性 强一致 通常最终一致(可调)
典型用途 金融、订单、用户账户、任何需要ACID的场景 用户画像、日志、时序、社交图谱、缓存

NoSQL 四大家族

KV 存储
Redis / DynamoDB
最简单,按 Key 精确查找。极快(内存级)。适合:Session、缓存、计数器、排行榜。
文档数据库
MongoDB / Firestore
以 JSON 文档为单位存储,Schema 灵活。适合:用户资料、商品详情、内容管理(字段不固定)。
列族存储
Cassandra / HBase
按列族组织,写入极快,适合时序/追加场景。适合:IoT 数据、日志、消息历史、时序数据。
图数据库
Neo4j / Amazon Neptune
以节点和边建模,擅长多跳关系查询。适合:社交网络、推荐系统、知识图谱、欺诈检测。

数据库分片(Sharding)

当单机数据库的存储或写入达到上限时,水平分片(Sharding)将数据分散到多个数据库节点。

分片前(单机 DB 写入瓶颈): 所有写入 ──▶ [ Single DB ] ──▶ 写 QPS 上限约 3K/s 存储上限约 5TB 分片后(3个分片): 写请求 ──▶ Shard Router │ ┌─────────┼─────────┐ ▼ ▼ ▼ [DB-0] [DB-1] [DB-2] user 0-33% user 33-66% user 66-100% 写 QPS 3倍 存储 3倍

分片策略一:范围分片(Range-Based Sharding)

按用户 ID 范围分片: Shard 0:user_id 1 ~ 10,000,000 Shard 1:user_id 10,000,001 ~ 20,000,000 Shard 2:user_id 20,000,001 ~ 30,000,000 优点:范围查询高效(如:查所有 ID 在 1-1000 的用户) 缺点:数据分布不均(早期用户活跃,Shard 0 成热点) 新用户永远写入最后一个 Shard(写热点)

分片策略二:哈希分片(Hash-Based Sharding)

按哈希值分片: shard_id = hash(user_id) % shard_count user_id=1001 → hash=872341 → 872341 % 3 = 1 → Shard 1 user_id=1002 → hash=654789 → 654789 % 3 = 0 → Shard 0 user_id=1003 → hash=123456 → 123456 % 3 = 0 → Shard 0 优点:数据分布均匀,无热点问题 缺点:范围查询需要查所有 Shard(聚合查询慢) 扩容时数据迁移量大(% 变化导致大量 rehash)

分片策略三:一致性哈希(Consistent Hashing)

一致性哈希环: 0 Node A 330 60 ↖ ↙ 270 ── 哈希环 ── 90 ↙ ↖ 210 150 Node B 180 加入 Node C 普通哈希:新增/删除节点 → 几乎所有数据需要重新映射(O(N)) 一致性哈希:新增/删除节点 → 只有相邻 1/N 的数据需要迁移 实际应用: - Memcached 客户端负载均衡 - Cassandra 数据分片 - Amazon DynamoDB - Chord DHT 分布式哈希表 虚拟节点(Virtual Node): 每个物理节点在哈希环上映射多个虚拟节点 解决数据分布不均问题(节点少时的偏斜)

读写分离与主从复制

主从复制架构: 写操作 ──▶ ┌──────────────┐ │ Primary DB │ │ (Master) │ └──────┬───────┘ │ 复制(Replication) │ Binlog / WAL ┌─────────┼──────────┐ ▼ ▼ ▼ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ Replica 1 │ │ Replica 2 │ │ Replica 3 │ │ (Slave) │ │ (Slave) │ │ (Slave) │ └────────────┘ └────────────┘ └────────────┘ 读操作分散到各 Replica 复制延迟(Replication Lag)问题: 主库写入 → Binlog 传输 → 从库重放 → 有延迟(毫秒~秒) 场景:用户刚发完帖子刷新 → 读从库 → 看不到自己的帖子! 解决方案: ① 写后读(Read-Your-Writes): 用户自己的写操作之后的读,路由到主库 ② 单调读(Monotonic Read): 同一用户的读请求永远路由到同一个从库 ③ 关键读走主库(如支付确认页面)

分布式数据库:TiDB 与 CockroachDB

新一代分布式数据库(NewSQL)试图兼顾 SQL 的易用性和 NoSQL 的水平扩展能力。

TiDB 架构(PingCAP): SQL 客户端(MySQL 协议兼容) │ ┌──────▼──────────────────────────┐ │ TiDB Layer │ │ SQL 解析、优化器、执行器 │ │ 无状态,可水平扩展 │ └──────┬──────────────────────────┘ │ ┌──────▼──────────────────────────┐ │ PD (Placement Driver) │ │ 元数据管理、Region 调度、时钟 │ └──────┬──────────────────────────┘ │ ┌──────┴──────────┬───────────────┐ ▼ ▼ ▼ ┌────────┐ ┌────────┐ ┌────────┐ │ TiKV │ │ TiKV │ │ TiKV │ │ Node 1 │ │ Node 2 │ │ Node 3 │ │(Raft副本)│ │(Raft副本)│ │(Raft副本)│ └────────┘ └────────┘ └────────┘ 特性: - 兼容 MySQL 协议,应用改造成本低 - 自动分片(Region = 96MB 的数据块) - 基于 Raft 的强一致性 - HTAP:同时支持 OLTP 和 OLAP
特性传统 MySQL 分片TiDB / CockroachDB
分片透明性应用层需要感知分片逻辑完全透明,像单机 MySQL
跨分片事务非常复杂,需要 2PC 或 Saga原生支持分布式事务
扩容操作需要手动迁移数据,高风险在线自动扩容,几乎无感知
运维复杂度中(熟悉 MySQL 即可)高(新概念多,调优复杂)
性能单机极致,分布式事务弱单机稍低,分布式事务强
适用规模数百 GB ~ 数 TB数 TB ~ PB 级
▶ 面试要点