TouchAll技术博客

TouchAll技术博客

[系统设计 - 数据库设计专题] 1.数据库技术选型

一、为什么选型如此重要?

数据库选型是系统架构中最关键的决策之一,选错数据库的代价:

代价类型 具体表现
性能瓶颈 查询慢、写入跟不上、高峰期系统崩溃
运维灾难 频繁扩容、数据迁移、7×24 救火
架构重构 业务增长后被迫换库,半年重写
成本失控 资源浪费、License 费用、人力投入

核心原则:没有最好的数据库,只有最适合的数据库。


二、数据库分类全景图

┌─────────────────────────────────────────────────────────────────┐
│                        数据库分类体系                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐          │
│  │   关系型      │  │   文档型      │  │    KV型      │          │
│  │   (RDBMS)    │  │  (Document)  │  │  (Key-Value) │          │
│  │              │  │              │  │              │          │
│  │ • MySQL      │  │ • MongoDB    │  │ • Redis      │          │
│  │ • PostgreSQL │  │ • Couchbase  │  │ • Memcached  │          │
│  │ • Oracle     │  │ • DynamoDB   │  │ • etcd       │          │
│  │ • SQL Server │  │              │  │ • RocksDB    │          │
│  └──────────────┘  └──────────────┘  └──────────────┘          │
│                                                                 │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐          │
│  │   列存型      │  │   时序型      │  │  搜索引擎     │          │
│  │  (Column)    │  │  (Time-Series)│  │  (Search)    │          │
│  │              │  │              │  │              │          │
│  │ • ClickHouse │  │ • InfluxDB   │  │ • Elastic-   │          │
│  │ • HBase      │  │ • TimescaleDB│  │   search     │          │
│  │ • Cassandra  │  │ • Prometheus │  │ • Solr       │          │
│  │ • BigQuery   │  │ • OpenTSDB   │  │ • Meilisearch│          │
│  └──────────────┘  └──────────────┘  └──────────────┘          │
│                                                                 │
│  ┌──────────────┐  ┌──────────────┐                            │
│  │   图数据库    │  │   对象存储    │                            │
│  │   (Graph)    │  │  (Object)    │                            │
│  │              │  │              │                            │
│  │ • Neo4j      │  │ • MinIO      │                            │
│  │ • JanusGraph │  │ • Ceph       │                            │
│  │ • NebulaGraph│  │ • S3/OSS     │                            │
│  └──────────────┘  └──────────────┘                            │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

三、各类型数据库详解

3.1 关系型数据库(RDBMS)

核心特性:强一致性、SQL 标准、事务支持、复杂查询

代表产品 特点 适用场景 不适用场景
MySQL 生态成熟、读写分离简单、社区活跃 Web 应用、电商、中小规模业务 超大规模写入、复杂分析
PostgreSQL 功能强大、支持 JSON/GIS、扩展性好 复杂查询、地理信息、金融系统 超大规模分布式场景
Oracle 企业级、高可用、强一致性 银行、电信、ERP 核心系统 互联网高并发、成本敏感
SQL Server 微软生态、易用性好 .NET 技术栈、企业内部系统 开源优先、Linux 环境

选型决策点

需要强事务一致性?
├── 是 → 需要分布式?
│       ├── 是 → 考虑 NewSQL(TiDB/CockroachDB)
│       └── 否 → 单机 RDBMS
│               ├── 预算充足 → Oracle/SQL Server
│               └── 开源优先 → MySQL/PostgreSQL
│                       ├── 复杂查询/GIS → PostgreSQL
│                       └── 简单 CRUD → MySQL
└── 否 → 考虑 NoSQL

3.2 文档型数据库(Document)

核心特性:Schema 灵活、嵌套结构、快速迭代

代表产品 特点 适用场景 不适用场景
MongoDB 文档模型、分片支持、查询丰富 内容管理、用户画像、快速迭代 复杂关联查询、强事务
Couchbase 内存优先、移动端同步、SQL 支持 移动应用、低延迟缓存 大规模分析
DynamoDB 全托管、自动扩缩、毫秒延迟 AWS 生态、游戏、广告 复杂查询、成本敏感

典型数据模型

// MongoDB 文档示例
{
  "_id": ObjectId("..."),
  "user_id": 10001,
  "profile": {
    "nickname": "张三",
    "avatar": "https://...",
    "tags": ["VIP", "活跃用户"]
  },
  "orders": [
    {"order_id": "A001", "amount": 100},
    {"order_id": "A002", "amount": 200}
  ],
  "created_at": ISODate("2024-01-01T00:00:00Z")
}

选型决策点

数据模型是嵌套/层级结构?
├── 是 → Schema 频繁变更?
│       ├── 是 → MongoDB
│       └── 否 → 考虑关系型
└── 否 → 考虑其他类型

3.3 KV 型数据库(Key-Value)

核心特性:极致性能、简单模型、内存优先

代表产品 特点 适用场景 不适用场景
Redis 内存存储、数据结构丰富、持久化 缓存、会话、排行榜、分布式锁 复杂查询、大数据量
Memcached 纯内存、多线程、简单 简单缓存、会话存储 持久化、复杂数据结构
etcd 强一致、分布式协调、Raft 配置中心、服务发现、分布式锁 高频读写、大数据量
RocksDB 嵌入式、LSM-Tree、持久化 本地存储、嵌入式数据库 分布式场景

Redis 数据结构应用场景

String   → 缓存、计数器、分布式锁
Hash     → 对象存储(用户信息)
List     → 消息队列、时间线
Set      → 标签、共同好友
ZSet     → 排行榜、延迟队列
Stream   → 消息队列(Kafka 轻量替代)

选型决策点

需要亚毫秒延迟?
├── 是 → 数据需要持久化?
│       ├── 是 → Redis(RDB/AOF)
│       └── 否 → Memcached
└── 否 → 需要强一致分布式协调?
        ├── 是 → etcd/ZooKeeper
        └── 否 → 考虑其他类型

3.4 列存型数据库(Column-Family)

核心特性:高吞吐写入、水平扩展、大数据分析

代表产品 特点 适用场景 不适用场景
ClickHouse 列存、向量化执行、SQL 支持 OLAP、日志分析、实时报表 高频小事务、点查
HBase 列族、稀疏存储、Hadoop 生态 大数据存储、用户行为、时序数据 复杂查询、事务
Cassandra 高可用、最终一致、线性扩展 大规模写入、时间序列、IoT 复杂查询、关联分析
BigQuery 全托管、Serverless、PB 级 云原生数据仓库、数据分析 低延迟要求

ClickHouse vs HBase 对比

场景:日志分析系统

ClickHouse:
✓ SQL 查询,学习成本低
✓ 压缩率高(10:1)
✓ 实时查询(秒级)
✗ 不支持更新
✗ 单表列数有限制

HBase:
✓ 支持更新
✓ 超大规模(PB 级)
✓ 与 Hadoop 生态集成
✗ 查询复杂(需要 Phoenix 转 SQL)
✗ 延迟较高

选型决策点

数据量 > 1TB 且以分析为主?
├── 是 → 需要实时更新?
│       ├── 是 → ClickHouse
│       └── 否 → 离线分析?
│               ├── 是 → Hive/Spark
│               └── 否 → HBase
└── 否 → 考虑其他类型

3.5 时序型数据库(Time-Series)

核心特性:时间索引、高吞吐写入、数据压缩

代表产品 特点 适用场景 不适用场景
InfluxDB 时序专用、SQL -like、生态好 监控指标、IoT、实时分析 复杂查询、事务
TimescaleDB 基于 PostgreSQL、SQL 兼容 需要复杂查询的时序场景 超大规模(相比 InfluxDB)
Prometheus 拉取模型、服务发现、告警 Kubernetes 监控、云原生 长期存储、业务数据
OpenTSDB 基于 HBase、大规模 海量指标存储 查询性能要求高

典型应用场景

监控指标:CPU、内存、网络、请求量
IoT 数据:传感器数据、设备状态
业务指标:订单量、用户活跃度、交易金额

选型决策点

数据是时间序列(指标/监控)?
├── 是 → 需要复杂查询?
│       ├── 是 → TimescaleDB
│       └── 否 → 与 Kubernetes 集成?
│               ├── 是 → Prometheus
│               └── 否 → InfluxDB
└── 否 → 考虑其他类型

3.6 搜索引擎(Search Engine)

核心特性:全文检索、倒排索引、近实时

代表产品 特点 适用场景 不适用场景
Elasticsearch 功能全面、生态丰富、近实时 全文检索、日志分析、复杂查询 强事务、高频更新
Solr Apache 项目、稳定、企业级 企业搜索、传统搜索场景 实时性要求高
Meilisearch 轻量、快速、易用 小型搜索、即时搜索 大规模、复杂分析

Elasticsearch 典型应用

电商搜索:商品名称、描述、标签全文检索
日志分析:ELK Stack(Elasticsearch + Logstash + Kibana)
数据分析:复杂聚合查询、实时报表

选型决策点

需要全文检索/复杂搜索?
├── 是 → 数据量 > 100GB?
│       ├── 是 → Elasticsearch
│       └── 否 → 轻量级?
│               ├── 是 → Meilisearch
│               └── 否 → Elasticsearch
└── 否 → 考虑其他类型

3.7 图数据库(Graph)

核心特性:图模型、关系遍历、路径查询

代表产品 特点 适用场景 不适用场景
Neo4j 属性图、Cypher 查询、生态好 社交网络、知识图谱、推荐系统 大规模分析
JanusGraph 分布式、基于 Cassandra/HBase 超大规模图、企业级 学习成本高
NebulaGraph 分布式、高性能、国产 大规模图、金融风控 生态不如 Neo4j

典型应用场景

社交网络:好友关系、关注关系、共同好友
知识图谱:实体关系、语义搜索
推荐系统:用户-商品-标签关系
风控系统:关联交易、欺诈检测

选型决策点

数据是强关系/图结构?
├── 是 → 需要分布式?
│       ├── 是 → JanusGraph/NebulaGraph
│       └── 否 → Neo4j
└── 否 → 考虑其他类型

四、选型决策流程图

┌─────────────────────────────────────────────────────────────────┐
│                    数据库选型决策流程                              │
└─────────────────────────────────────────────────────────────────┘

                          ┌─────────┐
                          │  开始    │
                          └────┬────┘
                               │
                               ▼
                ┌──────────────────────────┐
                │ 1. 数据模型是什么?        │
                └────────────┬─────────────┘
                             │
        ┌────────────────────┼────────────────────┐
        │                    │                    │
        ▼                    ▼                    ▼
  ┌───────────┐      ┌───────────┐      ┌───────────┐
  │ 关系/表格  │      │ 文档/嵌套  │      │ 图/关系网  │
  └─────┬─────┘      └─────┬─────┘      └─────┬─────┘
        │                  │                  │
        ▼                  ▼                  ▼
  ┌───────────┐      ┌───────────┐      ┌───────────┐
  │ 需要强事务?│      │ MongoDB   │      │ Neo4j     │
  └─────┬─────┘      └───────────┘      └───────────┘
        │
   ┌────┴────┐
   │         │
   ▼         ▼
  是         否
   │         │
   ▼         ▼
┌──────┐  ┌──────────────────┐
│RDBMS │  │ 2. 访问模式?     │
└──────┘  └────────┬─────────┘
                   │
      ┌────────────┼────────────┐
      │            │            │
      ▼            ▼            ▼
 ┌─────────┐ ┌─────────┐ ┌─────────┐
 │读多写少  │ │写多读少  │ │分析为主 │
 └────┬────┘ └────┬────┘ └────┬────┘
      │           │           │
      ▼           ▼           ▼
 ┌─────────┐ ┌─────────┐ ┌─────────┐
 │读写分离  │ │列存/时序 │ │列存型   │
 │+缓存    │ │         │ │         │
 └─────────┘ └────┬────┘ └─────────┘
                  │
           ┌──────┴──────┐
           │             │
           ▼             ▼
     ┌─────────┐   ┌─────────┐
     │时序数据?│   │大数据? │
     └────┬────┘   └────┬────┘
          │             │
     ┌────┴────┐   ┌────┴────┐
     │         │   │         │
     ▼         ▼   ▼         ▼
    是        否  是        否
     │         │   │         │
     ▼         ▼   ▼         ▼
 ┌────────┐┌────────┐┌────────┐┌────────┐
 │InfluxDB││Cassandra││Click-││HBase   │
 │        ││        ││House ││        │
 └────────┘└────────┘└────────┘└────────┘

五、选型案例

案例 1:电商平台技术选型

业务场景

  • 日活用户 100 万,日订单 5 万单
  • 需要商品搜索、订单管理、用户画像、数据分析

选型方案

┌─────────────────────────────────────────────────────┐
│  核心业务(订单/用户/商品)                            │
│  → MySQL 8.0(强事务、成熟生态)                      │
│  → 读写分离:1主2从                                   │
├─────────────────────────────────────────────────────┤
│  商品搜索                                            │
│  → Elasticsearch(全文检索、复杂筛选)                 │
│  → 数据同步:Canal 监听 MySQL Binlog                  │
├─────────────────────────────────────────────────────┤
│  缓存层                                              │
│  → Redis(会话、热点商品、购物车)                      │
│  → 集群模式:6节点(3主3从)                           │
├─────────────────────────────────────────────────────┤
│  用户画像/行为分析                                     │
│  → MongoDB(灵活 Schema、嵌套结构)                    │
│  → 或 ClickHouse(大规模分析)                        │
├─────────────────────────────────────────────────────┤
│  数据分析/报表                                         │
│  → ClickHouse(实时 OLAP、秒级查询)                   │
│  → 数据同步:Flink CDC                                │
└─────────────────────────────────────────────────────┘

选型理由

场景 选择 理由
订单 MySQL 强事务、复杂查询、团队熟悉
搜索 Elasticsearch 全文检索、复杂筛选、近实时
缓存 Redis 亚毫秒延迟、数据结构丰富
分析 ClickHouse 列存压缩、向量化执行、秒级查询

案例 2:IoT 平台技术选型

业务场景

  • 10 万台设备,每 10 秒上报一次数据
  • 需要实时监控、历史查询、告警

数据量估算

日增数据点:10万 × 8640次/天 = 8.64亿点/天
单点大小:~50字节
日增存储:~43GB/天
年增存储:~15TB/年

选型方案

┌─────────────────────────────────────────────────────┐
│  设备元数据/配置                                       │
│  → PostgreSQL(关系模型、复杂查询)                     │
├─────────────────────────────────────────────────────┤
│  实时指标存储                                          │
│  → InfluxDB(时序专用、高吞吐写入)                     │
│  → 保留策略:原始数据保留 7 天                          │
├─────────────────────────────────────────────────────┤
│  历史数据归档                                          │
│  → ClickHouse(大规模分析、高压缩)                     │
│  → 降采样:1分钟聚合数据保留 1 年                       │
├─────────────────────────────────────────────────────┤
│  实时监控/告警                                         │
│  → Prometheus + Grafana(监控告警)                    │
│  → Kafka(消息队列、削峰)                             │
└─────────────────────────────────────────────────────┘

数据流转

设备 → MQTT Broker → Kafka → 
  ├→ InfluxDB(实时查询)
  ├→ Prometheus(监控告警)
  └→ Flink → ClickHouse(历史归档)

案例 3:社交应用技术选型

业务场景

  • 1000 万用户,关注/粉丝关系
  • 需要动态流、推荐、搜索

选型方案

┌─────────────────────────────────────────────────────┐
│  用户基础信息                                          │
│  → MySQL(强事务、简单 CRUD)                          │
├─────────────────────────────────────────────────────┤
│  关注/粉丝关系                                         │
│  → Neo4j(图遍历、共同好友、推荐)                      │
│  → 或 Redis Set(简单关注列表)                        │
├─────────────────────────────────────────────────────┤
│  动态流/Feed                                          │
│  → Cassandra(高吞吐写入、时间序列)                    │
│  → 或 MongoDB(灵活模型)                             │
├─────────────────────────────────────────────────────┤
│  内容搜索                                              │
│  → Elasticsearch(全文检索、标签搜索)                  │
├─────────────────────────────────────────────────────┤
│  热点数据缓存                                          │
│  → Redis(用户信息、关注列表、排行榜)                  │
└─────────────────────────────────────────────────────┘

六、多数据库混用架构

6.1 架构原则

1. 主从分明
   - 每个业务域只有一个"主存储"
   - 其他存储通过 CDC/消息队列同步

2. 数据一致性
   - 明确数据源(Source of Truth)
   - 避免双写导致的不一致

3. 边界清晰
   - 不同数据库负责不同场景
   - 避免一个数据库做所有事

6.2 典型架构模式

┌─────────────────────────────────────────────────────────────┐
│                        应用层                                │
└─────────────────────────────────────────────────────────────┘
                              │
        ┌─────────────────────┼─────────────────────┐
        │                     │                     │
        ▼                     ▼                     ▼
┌───────────────┐   ┌───────────────┐   ┌───────────────┐
│   业务服务     │   │   搜索服务     │   │   分析服务     │
└───────┬───────┘   └───────┬───────┘   └───────┬───────┘
        │                   │                   │
        ▼                   ▼                   ▼
┌───────────────┐   ┌───────────────┐   ┌───────────────┐
│   MySQL       │   │ Elasticsearch │   │  ClickHouse   │
│  (主存储)     │   │  (搜索索引)    │   │  (分析引擎)    │
└───────┬───────┘   └───────────────┘   └───────────────┘
        │
        │ Binlog CDC
        ▼
┌───────────────┐   ┌───────────────┐
│    Redis      │   │  MongoDB      │
│   (缓存)      │   │  (用户画像)    │
└───────────────┘   └───────────────┘

6.3 数据同步方案

方案 适用场景 延迟 复杂度
Canal/Debezium MySQL Binlog → ES/Redis 秒级
Flink CDC 多源同步、实时计算 秒级
消息队列 异步解耦、削峰 秒级
应用层双写 简单场景、强一致 毫秒级

七、常见选型误区

误区 1:一个数据库解决所有问题

❌ 错误:只用 MySQL 做搜索、缓存、分析
✓ 正确:不同场景用不同数据库,各司其职

误区 2:盲目追求新技术

❌ 错误:为了用 TiDB 而用 TiDB(实际数据量 < 100GB)
✓ 正确:根据实际需求选择,MySQL 能解决就不用分库分表

误区 3:忽视团队能力

❌ 错误:选 Cassandra 但团队没人熟悉
✓ 正确:选择团队熟悉或有能力掌握的数据库

误区 4:不考虑运维成本

❌ 错误:自建 HBase 集群(运维复杂度高)
✓ 正确:云托管服务(如 AWS DynamoDB、阿里云 Lindorm)

误区 5:忽视数据迁移成本

❌ 错误:选了一个数据库,半年后发现不合适,迁移成本巨大
✓ 正确:前期充分评估,预留迁移方案

八、选型决策清单

在最终决策前,逐项确认:

□ 业务场景明确(读/写/查询/分析比例)
□ 数据量估算(当前 + 3 年预测)
□ 性能要求(QPS/延迟/可用性)
□ 团队能力(是否熟悉、学习成本)
□ 运维成本(自建 vs 云托管)
□ 生态集成(与现有技术栈兼容性)
□ 成本预算(License + 硬件 + 人力)
□ 迁移方案(如果不合适,如何退出)
□ 社区活跃度(开源项目的问题响应速度)
□ 厂商锁定风险(是否容易被绑定)

总结

数据库选型的核心原则:

  1. 场景驱动:从业务需求出发,不是从技术出发
  2. 权衡取舍:没有完美方案,只有最适合的方案
  3. 渐进演进:先简单后复杂,预留扩展空间
  4. 成本意识:考虑总拥有成本(TCO),不只是 License

记住:数据库选型不是一次性决策,而是随着业务发展持续演进的过程。