加群联系作者vx:xiaoda0423
仓库地址:webvueblog.github.io/JavaPlusDoc...
webvueblog.github.io/JavaPlusDoc...
点击勘误issues,哪吒感谢大家的阅读
架构懂了就来了解数据库存储扩展千亿读写
一键可用的三档假设(你直接选)
档位 | 峰值写入 W (条/s) | 单行大小 R (字节) | 热数据保留 T (天) | 适用场景 |
---|---|---|---|---|
A 保守 | 50,000 | 200 | 30 | 早期 PoC / 小规模上线 |
B 均衡(推荐) | 200,000 | 300 | 30(热)+ 180(温) | 典型 IoT/日志明细 |
C 激进 | 1,000,000 | 500 | 30(热)+ 365(温) | 海量设备/重分析 |
说明:热数据 放 OLTP/时序/列式集群用于线上与报表;温/冷数据分层到 ClickHouse + 对象存储。
关键资源测算(已算好,可直接用)
(经验公式:Kafka 分区≈W/5k;OLTP 分片≈W/10k;Redis 分片≈(0.1×W)/50k;吞吐(MB/s)=W×R/1e6)
A 保守(5 万写/s,200B,30 天)
- Kafka :≈ 10 分区(建议 3--4 台 broker 起步)
- OLTP 分片 (MySQL+Vitess 或 TiDB):≈ 5 分片
- Redis Cluster :≈ 1 分片(假设 10% 写入走状态存取)
- 入口吞吐 :≈ 10 MB/s
- ClickHouse 存储 (仅热 30 天;压缩后≈原始/3):≈ 8.64 TB (无副本);RF=2 ≈ 17.28 TB
B 均衡(20 万写/s,300B,热 30 天 + 温 180 天)
-
Kafka :≈ 40 分区(建议 6--8 broker)
-
OLTP 分片 :≈ 20 分片(倾向 TiDB 降低运维复杂度)
-
Redis Cluster :≈ 1 分片(0.1×W 假设)
-
入口吞吐 :≈ 60 MB/s
-
ClickHouse(热 30 天) :压缩后≈ 51.84 TB ;RF=2 ≈ 103.68 TB
-
ClickHouse(温 180 天) :压缩后≈ 311.04 TB ;RF=2 ≈ 622.08 TB
建议:温数据落分层存储 (HDD/对象存储 + S3 Cache),并用物化视图/预聚合显著降体量。
C 激进(100 万写/s,500B,热 30 天 + 温 365 天)
-
Kafka :≈ 200 分区(建议 12--16 broker)
-
OLTP 分片 :≈ 100 分片(强烈建议 TiDB/CockroachDB)
-
Redis Cluster :≈ 2 分片(按 10% 写入估算)
-
入口吞吐 :≈ 500 MB/s
-
ClickHouse(热 30 天) :压缩后≈ 144 TB ;RF=2 ≈ 288 TB
-
ClickHouse(温 365 天) :压缩后≈ 5,256 TB ;RF=2 ≈ 10,512 TB
必须做冷热分层 + 强预聚合 + 近实时明细裁剪(比如明细仅保留 7--14 天)。
跨地域多活怎么选?
-
不多活 / 同城双活 (推荐起步): 事务库同城多副本;Kafka 多 AZ;ClickHouse 分片跨 AZ。RPO≈0,RTO 分钟级。
-
异地灾备(Active-Passive) : 生产 Region 全量,异地 异步 复制(TiCDC/Debezium→Kafka→下游)。写延迟最低,RPO 秒级。
-
异地多活(Active-Active):
- 强一致多活 (跨区共识):写延迟受 RTT 影响,适合读多写少 或按业务键做就地写入(CockroachDB/TiDB 多区域表位置信策)。
- 最终一致多活 (推荐 IoT):每区本地落库 + Kafka Mirror 做跨区汇聚,冲突用业务键/时间戳解决。写入延迟最低,但对一致性要求要"可最终一致"。
现在就能落地的小蓝图(按"均衡档")
- 入口:Kafka(40 分区,acks=all,幂等生产者,压缩 lz4/zstd)
- 事务库:TiDB(3 TiKV×N,按 20 分片规模起步;或 MySQL+Vitess 20 分片)
- 缓存 :Redis Cluster(起 3--6 节点,1--2 分片;Key 设计含哈希标签
{deviceId}
) - 分析:ClickHouse(热 30 天:建议 4--6 分片×2 副本起步,分层存储)
- CDC:TiCDC/Debezium → Kafka → ClickHouse/ES/缓存回填
- 分区策略 :事务库按
device_id, ts
复合主键 + 按日/周分区 ;CHPARTITION BY toYYYYMMDD(ts) ORDER BY (device_id, ts)
+ TTL
目标拆解(两种常见场景)
- 场景 A:1000 亿总数据量(长期沉淀) 例:IoT/日志/交易明细累计 1000 亿行。
- 场景 B:超高吞吐(持续写入/查询) 例:峰值 20--200 万条/秒写入,实时查询。
下面给你可落地的架构与选型。
架构蓝图(通用且好落地)
- 入口层(写入解耦):Kafka / Pulsar(写入缓冲、削峰、重放、顺序性)
- 在线事务库(强一致、主业务):MySQL(分库分表/ Vitess) / PostgreSQL(Citus) / NewSQL(TiDB / CockroachDB / OceanBase)
- 热 Key/实时状态:Redis Cluster / Aerospike / Scylla(KV 毫秒级读写)
- 时序/明细分析:ClickHouse / Pinot / Druid(列式 + 分区,近实时 OLAP)
- 搜索:OpenSearch / Elasticsearch(全文检索、模糊查)
- CDC/数据流:Debezium/TiCDC → Kafka → ClickHouse(离线与实时打通)
- 冷存/归档:对象存储(S3/OSS/COS)+ 冷分区 TTL
核心思想:写入用日志(Kafka)解耦,OLTP 只做强一致交易,OLAP/时序做大吞吐分析,状态查询走 KV。CQRS + 分层存储。
怎么选数据库(一句话攻略)
-
强一致交易:
- 小规模先 MySQL 单机 → 读写分离 → 分库分表 → Vitess 或 ShardingSphere。
- 一步到位选 TiDB/CockroachDB/OceanBase(分布式事务、自动水平扩展)。
-
超高写 & 时序/明细分析 :ClickHouse (MergeTree 家族)或 Pinot/Druid。
-
实时状态/排行榜/会话 :Redis Cluster(哈希槽、Pipeline、Lua 原子)。
-
全文搜索 :OpenSearch/ES(注意写入背压、刷新间隔)。
-
KV 超大规模且持久化 :Aerospike/ScyllaDB(低延迟、可持久化)。
容量与分片估算(手把手)
- 吞吐估算 : 假设 1000 万设备、每分钟 1 次上报 → 10,000,000 / 60 ≈ 166,666 次/秒 写入。
- Kafka 分区数 (保守每分区 5k msg/s): 166,666 / 5,000 ≈ 34 分区(取 48/64 方便均衡)。
- OLTP 分片数 (保守每分片 10k 写/s): 166,666 / 10,000 ≈ 17 分片(取 24),每分片主从复制。
- 存储估算 : 1000 亿行 × 100B/行 ≈ 10 TB 原始 ;复制因子 3 → 30 TB ; 索引与额外列粗略 ×2 → ~60 TB(放在列式/对象存储更省)。
表设计与分区(示例)
OLTP(TiDB/MySQL + Vitess):按业务键 + 时间分库分表,避免热点。
sql
-- 设备上报明细(事务库:写入 + 最近短期查询)
CREATE TABLE device_event_202508 (
device_id BIGINT NOT NULL,
ts DATETIME NOT NULL,
evt_type TINYINT NOT NULL,
payload JSON,
PRIMARY KEY (device_id, ts) -- 复合主键,利于范围查询
) PARTITION BY RANGE COLUMNS(ts) (
PARTITION p20250801 VALUES LESS THAN ('2025-08-02'),
PARTITION p20250802 VALUES LESS THAN ('2025-08-03'),
-- 每日/每周分区,便于冷热分离与快速清理
);
时序/分析(ClickHouse):按天/周分区,排序键放查询维度。
sql
CREATE TABLE events_local ON CLUSTER cluster_3r3s
(
device_id UInt64,
ts DateTime,
evt_type UInt8,
v Float64,
payload String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/events_local', '{replica}')
PARTITION BY toYYYYMMDD(ts)
ORDER BY (device_id, ts)
TTL ts + INTERVAL 180 DAY TO VOLUME 'cold'; -- 180 天后走冷存
Redis(热数据/状态):
- Key 设计:
dev:{deviceId}:stat
,哈希结构; - 哈希标签 :
{deviceId}
保证同一设备落同槽,降低跨槽多键操作; - 开启 Pipeline、合理
tcp-keepalive
,禁用大 Lua 脚本长阻塞。
写入链路与幂等
-
入口 → Kafka (
acks=all
,幂等生产者,开启压缩) -
消费入库:
- OLTP:批量写 (500--1k 批),失败重试 + 幂等键(device_id+ts 或业务 id);
- 分析:Kafka → ClickHouse Kafka 引擎 / 自研 Sink(大批量、列式友好)。
-
CDC:OLTP 变更 → Debezium/TiCDC → Kafka → 下游(ES、ClickHouse、缓存回填)。
查询路径(QPS 高时要分层)
- 强一致/交易查询 → OLTP(MySQL/TiDB)
- 状态/排行榜/首页秒开 → Redis
- 报表/聚合/多维分析 → ClickHouse/Pinot(Pre-Aggregation + 物化视图)
- 搜索 → OpenSearch(定时/实时索引)
典型配置要点(踩坑少)
- MySQL/InnoDB :
binlog_format=ROW
,sync_binlog=1
(强一致)、innodb_flush_log_at_trx_commit=1
;分表用 Vitess/ShardingSphere 管理路由。 - PostgreSQL :连接池 PgBouncer ,声明式分区,Citus 做分布式。
- Kafka :
min.insync.replicas=2
(RF=3),保留策略基于时间/大小;消费者组max.poll.records
控制批量。 - ClickHouse :MergeTree 系列,
max_partitions_per_insert_block
合理;写入尽量大批;冷热分层 + TTL。 - Redis :Cluster,合理
hash-max-ziplist-entries
等小对象优化,不要在主线程做重型 Lua。 - ES/OpenSearch :写入用大批量 Bulk,降低刷新频率(
refresh_interval
),映射固定字段类型,避免动态映射爆炸。
分阶段扩容路线图
- Phase 0(< 每秒 2 万写):MySQL 主从 + Redis,ClickHouse 单集群小规模,Kafka 6--12 分区。
- Phase 1(~10 万写/s):Vitess/TiDB/Citus 上线;Kafka 32--64 分区;ClickHouse 3--6 分片×3 副本;Redis Cluster 6--12 分片。
- Phase 2(~20--50 万写/s) :多 Region 同城双活/两地三中心;跨 Region 采用异步复制 + 最终一致;ES/ClickHouse 做冷热分层与成本优化。
- Phase 3(>50 万写/s & 1000 亿级总量) :OLTP 只保留近 7--30 天,长期落列式 + 对象存储;索引窄化;精细化限流与降级。
你现在就能用的最小闭环(结合你常用栈:Java + Kafka + Redis + MySQL)
- Kafka 入口(分区按
hash(deviceId)%N
,acks=all
,幂等生产者) - MySQL → Vitess 或直接 TiDB 做事务与强一致
- Redis Cluster 做设备实时状态/首页
- ClickHouse 承接 Kafka 明细(近实时分析 + 报表)
- CDC(TiCDC/Debezium)把交易变更送到 Kafka,再同步到下游(ES/ClickHouse/缓存)
- 数据生命周期:OLTP 仅保留近数据,ClickHouse 分区 + TTL,冷数据上云存储
反模式(尽量别踩)
- 试图用 一个数据库 同时搞事务 + 高并发写 + 大规模分析
- 无分区的大表:删除/归档会把库打爆
- 盲目 主从读扩 扛写入:写放大、复制延迟一来就炸
- ES 当主库(事务一致性要求高的场景)
- Redis 当数据库(需要强一致/持久就别这么干)