前 18 章我们分别讨论了存储引擎、索引、事务、查询优化、复制、分区、分布式事务、一致性与共识——每一章都在解决一个特定问题。但真实的系统设计从来不是单点问题,而是所有问题的交织:你需要在数据建模时考虑分片策略,在选型时权衡 CAP,在缓存时考虑一致性,在容灾时考虑成本。
本章综合运用全系列知识,从零设计一个社交电商平台的数据库架构。将走过完整的设计流程:需求分析 → 数据建模 → 存储选型 → 读写分离与缓存 → 分库分表 → 分布式事务 → 搜索与推荐 → 容灾与监控 → 演进路径。每一步都会回溯到前 18 章的理论基础,让你看到知识如何落地为工程决策。
前置知识:本章是全系列的收官之作,综合运用前 18 章全部知识。建议按需回顾:数据建模参考 数据建模与 Schema 设计,选型参考 数据库选型与实践,复制参考 数据复制,分区参考 数据分区,分布式事务参考 分布式事务,分库分表参考 分库分表与 NewSQL,可靠性参考 数据库可靠性。
一、需求分析
1.1 业务功能
社交电商平台”潮购”融合社交与电商,核心功能模块:
- 用户系统:注册/登录、个人资料、关注/粉丝、私信
- 商品系统:商品发布、分类管理、库存管理、SKU 管理
- 订单系统:下单、支付、退款、物流跟踪
- 社交系统:动态发布、点赞/评论/收藏、推荐流
- 搜索系统:全文搜索商品、用户、内容
1.2 非功能需求
| 维度 | 指标 | 目标值 |
|---|---|---|
| QPS | 读 QPS / 写 QPS | 50,000 / 5,000(峰值 3 倍) |
| 延迟 | 核心 API P99 | < 100ms(读),< 500ms(写) |
| 可用性 | SLA | 99.95%(年停机 < 4.4 小时) |
| 数据量 | 用户 / 商品 / 订单 | 5000 万 / 1 亿 / 10 亿(3 年) |
| RPO | 数据丢失容忍 | < 1 分钟 |
| RTO | 恢复时间目标 | < 30 分钟 |
1.3 系统架构总览
上述架构遵循 数据库选型与实践 中讨论的**多语言持久化(Polyglot Persistence)**原则——不同数据特征使用不同存储引擎,而非用一种数据库解决所有问题。
二、数据建模
2.1 ER 图设计
2.2 范式与反范式取舍
在 数据建模与 Schema 设计 中讨论了范式与反范式的权衡。社交电商场景的核心取舍:
| 设计决策 | 范式化(3NF) | 反范式化 | 本项目选择 |
|---|---|---|---|
| 订单中的商品信息 | 仅存 product_id,查询时 Join | 冗余商品名称/价格/图片 | 反范式——订单是历史快照,商品可能改价 |
| 用户关注数 | COUNT 查询 follows 表 | 冗余 follower_count 字段 | 反范式——高频读取,低频更新 |
| 商品分类路径 | 递归 Join 父分类 | 冗余全路径 path_ids | 反范式——避免递归查询 |
| 订单金额 | 从 order_items 聚合 | 冗余 total_amount | 反范式——避免聚合计算 |
反范式化的核心原则:读多写少且对一致性要求不严格的数据适合冗余。订单快照是典型的反范式场景——下单时的价格必须固化,不能随商品调价而变化。
2.3 表结构设计
用户表:
CREATE TABLE users ( id BIGINT NOT NULL COMMENT '用户ID(Snowflake)', username VARCHAR(50) NOT NULL COMMENT '用户名', email VARCHAR(255) NOT NULL COMMENT '邮箱', phone VARCHAR(20) DEFAULT NULL COMMENT '手机号', password_hash VARCHAR(255) NOT NULL COMMENT '密码哈希', avatar_url VARCHAR(512) DEFAULT NULL COMMENT '头像URL', status TINYINT NOT NULL DEFAULT 1 COMMENT '1正常 2禁用', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_email (email), UNIQUE KEY uk_phone (phone), KEY idx_username (username), KEY idx_created_at (created_at)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;商品表:
CREATE TABLE products ( id BIGINT NOT NULL COMMENT '商品ID', name VARCHAR(200) NOT NULL COMMENT '商品名称', category_id BIGINT NOT NULL COMMENT '分类ID', price DECIMAL(10,2) NOT NULL COMMENT '售价', original_price DECIMAL(10,2) DEFAULT NULL COMMENT '原价', stock INT NOT NULL DEFAULT 0 COMMENT '库存', sales_count INT NOT NULL DEFAULT 0 COMMENT '销量(反范式)', status TINYINT NOT NULL DEFAULT 1 COMMENT '1上架 2下架', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_category (category_id), KEY idx_status_created (status, created_at), KEY idx_sales (sales_count DESC)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;订单表:
CREATE TABLE orders ( id BIGINT NOT NULL COMMENT '订单ID(Snowflake)', user_id BIGINT NOT NULL COMMENT '买家ID', status TINYINT NOT NULL DEFAULT 1 COMMENT '1待付 2已付 3已发 4完成 5取消', total_amount DECIMAL(12,2) NOT NULL COMMENT '订单总金额(反范式快照)', payment_time DATETIME DEFAULT NULL COMMENT '支付时间', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user_created (user_id, created_at), KEY idx_status (status), KEY idx_created_at (created_at)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;2.4 编码格式选择
在 数据建模与 Schema 设计 中讨论了 JSON/Protobuf/Avro 的取舍。本项目的选择:
| 数据 | 编码格式 | 理由 |
|---|---|---|
| 商品属性(动态字段) | JSON(MySQL JSON 列) | Schema 灵活变化,读多写少 |
| 消息队列事件 | Protobuf | 高吞吐、向后兼容、跨语言 |
| 社交动态内容 | BSON(MongoDB 原生) | 嵌套文档、Schema-free |
| 数据同步日志 | Avro + Schema Registry | 演化兼容、与 Kafka 集成 |
三、存储选型
3.1 选型矩阵
基于 数据库选型与实践 中的选型框架,结合 存储引擎 的 B 树与 LSM 树特性分析:
| 存储引擎 | 职责 | 选型理由 | CAP 位置 |
|---|---|---|---|
| MySQL (InnoDB) | 用户/商品/订单等核心业务数据 | ACID 事务、B+ 树范围查询、成熟生态 | CP(主从切换短暂不可用) |
| Redis (Cluster) | 缓存/会话/排行榜/库存预扣 | 内存级延迟、丰富数据结构、Pub/Sub | AP(最终一致性) |
| Elasticsearch | 商品/内容全文搜索 | 倒排索引、相关性排序、聚合分析 | AP(近实时搜索) |
| MongoDB | 社交动态/评论/消息 | 文档模型、嵌套结构、灵活 Schema | CP(可调一致性) |
3.2 CAP 权衡分析
3.3 Redis 数据结构映射
基于 Redis 深入 中讨论的数据结构特性:
| 业务场景 | Redis 结构 | Key 设计 | 过期策略 |
|---|---|---|---|
| 用户会话 | String | session:{uid} | TTL 30min |
| 商品详情缓存 | Hash | product:{pid} | TTL 1h + 惰性删除 |
| 库存预扣 | String + Lua | stock:{pid} | 无过期 |
| 排行榜 | ZSet | rank:daily:{date} | TTL 48h |
| 用户关注列表 | Set | following:{uid} | 无过期 + Cache-Aside |
| Feed 流 | List/ZSet | feed:{uid} | TTL 7d |
四、读写分离与缓存
4.1 MySQL 主从复制 + 读写分离
基于 数据复制 中的单主复制模型和 MySQL 深入 中的 GTID 复制:
读写分离的核心问题——复制延迟导致读到旧数据,在 数据复制 中已详细讨论。本项目的应对策略:
| 场景 | 延迟容忍 | 解决方案 |
|---|---|---|
| 用户查看自己的订单 | 零容忍 | 强制路由到 Master |
| 商品列表浏览 | 秒级可容忍 | 从 Slave 读取 |
| 搜索结果 | 秒级可容忍 | 从 Slave 读取 |
| 库存查询 | 零容忍 | Redis 预扣 + Master 确认 |
4.2 Redis 缓存策略
采用 数据库性能优化 中讨论的 Cache-Aside 模式:
# Cache-Aside 读取async def get_product(product_id: int) -> Product: # 1. 查缓存 cache_key = f"product:{product_id}" cached = await redis.get(cache_key) if cached: return Product.from_json(cached)
# 2. 缓存 miss,查数据库 product = await db.query( "SELECT * FROM products WHERE id = %s", product_id ) if product: # 3. 回写缓存 await redis.setex(cache_key, 3600, product.to_json())
return product
# Cache-Aside 更新async def update_product(product_id: int, data: dict) -> None: # 1. 先更新数据库 await db.execute( "UPDATE products SET name=%s, price=%s WHERE id=%s", data["name"], data["price"], product_id ) # 2. 再删除缓存(而非更新缓存) await redis.delete(f"product:{product_id}")4.3 缓存一致性方案
| 方案 | 一致性 | 复杂度 | 本项目选择 |
|---|---|---|---|
| 先更新 DB 再删缓存 | 最终一致 | 低 | 默认方案 |
| 先删缓存再更新 DB | 最终一致(有窗口) | 低 | 并发时可能脏读 |
| 延迟双删 | 较强一致 | 中 | 关键数据 |
| 基于 Canal 订阅 Binlog | 最终一致 | 高 | 搜索索引同步 |
# 延迟双删:适用于库存等关键数据async def update_stock(product_id: int, delta: int) -> None: cache_key = f"stock:{product_id}"
# 1. 先删缓存 await redis.delete(cache_key)
# 2. 更新数据库 await db.execute( "UPDATE products SET stock = stock + %s WHERE id = %s AND stock + %s >= 0", delta, product_id, delta )
# 3. 延迟再删一次(防止并发读回写旧值) await asyncio.sleep(0.5) # 延迟 > 主从复制延迟 await redis.delete(cache_key)五、分库分表
5.1 分片策略
基于 数据分区 和 分库分表与 NewSQL 的理论,本项目采用垂直分库 + 水平分表组合策略:
| 业务域 | 分库 | 分表策略 | 分片键 | 分片数 |
|---|---|---|---|---|
| 用户 | user_db | 按 user_id 哈希 | user_id | 16 |
| 商品 | product_db | 按 product_id 哈希 | product_id | 32 |
| 订单 | order_db | 按 user_id 哈希 | user_id | 64 |
| 社交 | social_db | 按 user_id 哈希 | user_id | 16 |
订单按 user_id 而非 order_id 分片,是因为买家查订单是最高频的查询路径。按 user_id 分片后,同一买家的所有订单在同一分片,避免跨分片查询。卖家维度的查询通过 Elasticsearch 二级索引解决。
5.2 分布式 ID — Snowflake
在 分库分表与 NewSQL 中讨论了分布式 ID 方案。本项目采用 Snowflake 变体:
/** * Snowflake ID 结构(64 bit): * | 1 bit 符号 | 41 bit 时间戳 | 5 bit 数据中心 | 5 bit 机器 | 12 bit 序列号 | * 每毫秒可生成 4096 个 ID,最多支持 1024 节点 */public class SnowflakeIdGenerator { private final long epoch = 1704067200000L; // 2024-01-01 private final long datacenterId, workerId; private long sequence = 0, lastTimestamp = -1L;
public synchronized long nextId() { long ts = System.currentTimeMillis(); if (ts == lastTimestamp) { sequence = (sequence + 1) & 0xFFF; if (sequence == 0) ts = waitNextMillis(ts); } else { sequence = 0; } lastTimestamp = ts; return ((ts - epoch) << 22) | (datacenterId << 17) | (workerId << 12) | sequence; }}5.3 分片路由配置
# ShardingSphere 分片规则rules: - !SHARDING tables: orders: actualDataNodes: order_db_${0..15}.orders_${0..3} tableStrategy: standard: shardingColumn: user_id shardingAlgorithmName: orders_mod keyGenerateStrategy: column: id keyGeneratorName: snowflake
shardingAlgorithms: orders_mod: type: MOD props: sharding-count: 64 # 16库 × 4表
keyGenerators: snowflake: type: SNOWFLAKE props: worker-id: 15.4 跨分片查询方案
| 查询类型 | 方案 | 代价 |
|---|---|---|
| 按分片键查询 | 直接路由到目标分片 | 零额外代价 |
| 按非分片键精确查询 | 建立映射表(如 order_id → user_id) | 多一次查询 |
| 按非分片键范围查询 | 广播到所有分片,合并结果 | 高代价,需限制分片数 |
| 卖家查订单 | Elasticsearch 二级索引 | 近实时,毫秒级延迟 |
| 分页排序 | 各分片并行查 Top-N,归并排序 | 内存归并,需限制深度分页 |
六、分布式事务
6.1 订单创建的分布式事务
下单操作涉及三个服务:订单服务(创建订单)、库存服务(扣减库存)、支付服务(发起支付)。在 分布式事务 中分析了 2PC 的阻塞问题和 Saga 的补偿模式。
本项目采用 Saga 模式——牺牲强一致性,换取高可用性:
6.2 本地消息表保证最终一致性
基于 分布式事务 中的本地消息表模式:
-- 每个服务本地消息表CREATE TABLE outbox_messages ( id BIGINT NOT NULL AUTO_INCREMENT, aggregate_id BIGINT NOT NULL COMMENT '聚合根ID(如订单ID)', event_type VARCHAR(100) NOT NULL COMMENT '事件类型', payload JSON NOT NULL COMMENT '事件内容', status TINYINT NOT NULL DEFAULT 0 COMMENT '0待发 1已发 2失败', retry_count INT NOT NULL DEFAULT 0, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_status_created (status, created_at), KEY idx_aggregate (aggregate_id)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;// 订单创建 + 消息投递(同一本地事务)@Transactionalpublic Order createOrder(CreateOrderCmd cmd) { // 1. 创建订单 Order order = Order.create(cmd); orderMapper.insert(order);
// 2. 写入本地消息表(与订单在同一事务中) OutboxMessage msg = OutboxMessage.builder() .aggregateId(order.getId()) .eventType("ORDER_CREATED") .payload(JsonSerializer.serialize(order)) .status(0) .build(); outboxMapper.insert(msg);
return order;}
// 定时任务:扫描未发送消息,投递到 Kafka@Scheduled(fixedDelay = 1000)public void relayOutboxMessages() { List<OutboxMessage> messages = outboxMapper .selectPendingMessages(100);
for (OutboxMessage msg : messages) { try { kafkaTemplate.send("order-events", msg).get(); outboxMapper.updateStatus(msg.getId(), 1); } catch (Exception e) { outboxMapper.incrementRetry(msg.getId()); if (msg.getRetryCount() >= 5) { outboxMapper.updateStatus(msg.getId(), 2); alertService.send("消息投递失败: " + msg.getId()); } } }}本地消息表的核心保证:业务操作与消息投递在同一数据库事务中。只要事务提交成功,消息就一定存在;只要消息存在,就一定会被投递——这就是 分布式事务 中讨论的 至少一次投递(At-Least-Once Delivery) 语义。消费者需要保证幂等性。
七、搜索与推荐
7.1 Elasticsearch 索引设计
{ "mappings": { "properties": { "id": { "type": "long" }, "name": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart", "fields": { "keyword": { "type": "keyword" }, "pinyin": { "type": "text", "analyzer": "pinyin" } } }, "category_path": { "type": "keyword" }, "price": { "type": "scaled_float", "scaling_factor": 100 }, "sales_count": { "type": "integer" }, "suggest": { "type": "completion", "analyzer": "ik_max_word" } } }, "settings": { "number_of_shards": 8, "number_of_replicas": 1 }}7.2 数据同步 — Canal + Kafka
基于 批处理与流处理 中的 CDC(Change Data Capture)模式:
# Canal Instance 配置canal.instance.master.address: mysql-master:3306canal.instance.dbUsername: canalcanal.instance.filter.regex: "product_db\\..*,order_db\\..*"canal.instance.tsdb.enable: true
# Kafka Topic 投递canal.mq.servers: kafka:9092canal.mq.topic: canal_${database}_${table}canal.mq.partitionHash: "product_db.products:id,order_db.orders:user_id"7.3 推荐数据流
| 数据源 | 处理方式 | 目标存储 |
|---|---|---|
| 用户浏览/点击 | Flink 实时计算 → 用户画像 | Redis (Hash) |
| 购买/收藏行为 | Spark 批处理 → 协同过滤 | HDFS → MySQL |
| 社交关系 | 图计算 → 好友推荐 | Neo4j → Redis |
| 商品属性 | Elasticsearch → 相似推荐 | ES 内部 |
八、容灾与监控
8.1 两地三中心架构
基于 数据库可靠性 中的容灾方案:
| 指标 | 同城双活 | 异地灾备 |
|---|---|---|
| RPO | 0(同步复制) | < 1 分钟(异步复制) |
| RTO | < 30 秒(自动切换) | < 30 分钟(手动切换) |
| 成本 | 高(双机房全量资源) | 中(降级资源) |
| 适用场景 | 机房级故障 | 城市级故障 |
8.2 备份策略
基于 数据库可靠性 中的备份恢复策略:
| 备份类型 | 频率 | 保留周期 | 存储位置 |
|---|---|---|---|
| 全量备份(Xtrabackup) | 每日 02:00 | 30 天 | 对象存储 + 异地 |
| 增量备份 | 每 4 小时 | 7 天 | 对象存储 |
| Binlog 归档 | 实时 | 7 天 | 对象存储 + 异地 |
| Redis RDB | 每小时 | 3 天 | 本地 + 对象存储 |
#!/bin/bash# 全量备份脚本(Xtrabackup)BACKUP_DIR="/data/backups/mysql/$(date +%Y%m%d)"mkdir -p "$BACKUP_DIR"
xtrabackup --backup --target-dir="$BACKUP_DIR/full" \ --user=backup --password=$BACKUP_PASS --parallel=4 --compress
# 上传到对象存储 + 清理 30 天前本地备份rclone sync "$BACKUP_DIR" remote:mysql-backup/$(date +%Y%m%d) --transfers=4find /data/backups/mysql -mtime +30 -exec rm -rf {} +8.3 监控与告警
# Prometheus 告警规则groups: - name: database_alerts rules: - alert: MySQLReplicationLag expr: mysql_slave_seconds_behind_master > 10 for: 2m labels: severity: warning annotations: summary: "MySQL 复制延迟超过 10 秒"
- alert: MySQLConnectionPoolExhausted expr: mysql_connections_used / mysql_connections_max > 0.9 for: 1m labels: severity: critical annotations: summary: "MySQL 连接池使用率超过 90%"
- alert: RedisMemoryUsage expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.85 for: 5m labels: severity: warning annotations: summary: "Redis 内存使用率超过 85%"
- alert: OrderCreationLatency expr: histogram_quantile(0.99, rate(order_create_duration_bucket[5m])) > 0.5 for: 3m labels: severity: critical annotations: summary: "订单创建 P99 延迟超过 500ms"| 监控维度 | 核心指标 | 告警阈值 |
|---|---|---|
| MySQL | QPS/TPS、慢查询数、复制延迟、连接数 | 慢查询 > 50/min,延迟 > 10s |
| Redis | 内存使用率、命中率、连接数、延迟 | 命中率 < 95%,内存 > 85% |
| ES | 索引速率、搜索延迟、段合并 | 搜索 P99 > 200ms |
| 业务 | 订单创建延迟、支付成功率、库存超卖率 | 支付成功率 < 99.9% |
九、架构演进路径
没有系统一开始就是分布式的。从单机到分布式的演进,每一步都是因为前一步的方案无法满足增长的需求。在 数据库全景 中讨论了数据库的分类体系,在 数据分区 中讨论了扩展的动机——下面是潮购平台的演进路线:
| 阶段 | 核心变更 | 解决的瓶颈 | 引入的新问题 |
|---|---|---|---|
| Phase 1 → 2 | 主从复制 + Redis 缓存 | 读 QPS 不足 | 复制延迟、缓存一致性 |
| Phase 2 → 3 | 垂直分库 + 水平分表 | 单表数据量过大 | 跨库 Join、分布式 ID |
| Phase 3 → 4 | Saga + 本地消息表 | 跨库事务一致性 | 消息幂等、补偿逻辑 |
| Phase 4 → 5 | TiDB/NewSQL 替代分库分表 | 运维复杂度 | 迁移风险、NewSQL 成熟度 |
架构演进不是越快越好。每个阶段都应该穷尽当前架构的优化空间后再升级——正如 数据库性能优化 所强调的:先优化,再扩展。过早引入分布式会带来不必要的复杂度。
十、总结
10.1 全系列知识回顾
19 章内容,从单机到分布式,从理论到实战,形成完整的知识体系:
| 篇章 | 章节 | 核心问题 | 本文应用 |
|---|---|---|---|
| 基础 | 数据库全景 | 数据库分类与选型框架 | 多语言持久化策略 |
| 基础 | 存储引擎 | B 树 vs LSM 树 | MySQL(InnoDB) vs ES(LSM) 选型 |
| 基础 | 索引原理 | 索引如何加速查询 | 分片键索引、ES 倒排索引 |
| 基础 | 事务与并发控制 | ACID 与隔离级别 | 订单事务、库存并发扣减 |
| 基础 | 查询处理与优化 | 优化器如何选择执行计划 | 慢查询优化、索引策略 |
| 实战 | MySQL 深入 | InnoDB 内部实现 | GTID 复制、行格式选择 |
| 实战 | PostgreSQL 深入 | PG 内部实现 | 对比参考 |
| 实战 | Redis 深入 | Redis 数据结构与持久化 | 缓存策略、排行榜、库存预扣 |
| 实战 | 数据库性能优化 | 系统性调优方法论 | 缓存策略、连接池、监控体系 |
| 实战 | 数据建模与 Schema 设计 | 范式与编码格式 | 反范式设计、JSON/Protobuf 选型 |
| 实战 | 数据库选型与实践 | 选型决策框架 | MySQL + Redis + ES + MongoDB |
| 分布式 | 数据复制 | 复制延迟与一致性 | 主从读写分离、半同步复制 |
| 分布式 | 数据分区 | 分区策略与再平衡 | 哈希分片、跨分片查询 |
| 分布式 | 分布式事务 | 跨节点事务保证 | Saga 模式、本地消息表 |
| 分布式 | 一致性与共识 | 共识算法与一致性模型 | CAP 权衡、Raft 选举 |
| 分布式 | 分库分表与 NewSQL | Sharding 与 NewSQL | 分片策略、Snowflake ID |
| 衍生 | 批处理与流处理 | 批流数据处理 | Canal CDC、Flink 实时推荐 |
| 衍生 | 数据库可靠性 | 备份容灾与混沌工程 | 两地三中心、备份策略、监控告警 |
10.2 核心要点总结
| 设计维度 | 核心决策 | 理论基础 |
|---|---|---|
| 数据建模 | 订单快照反范式 + 商品属性 JSON | 范式 vs 反范式权衡(Ch10) |
| 存储选型 | MySQL + Redis + ES + MongoDB | 多语言持久化 + CAP(Ch11) |
| 读写分离 | 关键查询强制 Master + Cache-Aside | 复制延迟应对(Ch12) |
| 分库分表 | 按 user_id 哈希 + Snowflake ID | 分片策略 + 分布式 ID(Ch16) |
| 分布式事务 | Saga + 本地消息表 + 幂等消费 | 最终一致性(Ch14) |
| 数据同步 | Canal CDC → Kafka → ES/Redis | 变更数据捕获(Ch17) |
| 容灾 | 同城双活 + 异地灾备 + 定期演练 | RPO/RTO 权衡(Ch18) |
| 演进 | 单机 → 读写分离 → 分库分表 → 微服务 → NewSQL | 渐进式架构(Ch1, Ch13) |
数据库架构设计没有银弹——每一个决策都是在一致性、可用性、性能和成本之间的权衡。理解了前 18 章的理论基础,你就能在每一个权衡点做出有依据的决策,而不是盲目跟风。这才是本系列最大的价值:不是教你选择什么,而是教你如何选择。
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时






