【数据库】【Redis】 vs【ClickHouse】
·
Redis vs ClickHouse 全维度对比:内存缓存之王 vs 列式分析怪兽
Redis 和 ClickHouse 是设计理念完全相反的两款数据库,前者是内存优先的实时数据结构服务器,后者是磁盘优先的列式 OLAP 分析引擎。它们的对比本质是 “快与更快、小与大、简单与复杂” 的权衡。
一、核心定位与设计哲学
| 维度 | Redis | ClickHouse |
|---|---|---|
| 官方定位 | In-Memory Data Structure Store | Open-Source Column-Oriented OLAP Database |
| 设计目标 | 毫秒级响应的实时数据处理 | 秒级分析PB 级数据的极速 OLAP |
| 存储介质 | 内存为主,磁盘持久化为辅 | 磁盘为主,依赖大内存缓存 |
| 核心场景 | 缓存、计数器、队列、实时计算 | BI 报表、日志分析、时序聚合、用户行为分析 |
| 数据模型 | 富数据结构(String/List/Set/ZSet/Hash/Bitmap) | 列式存储(每列独立文件,高压缩) |
一句话概括:Redis 是"内存中的万能瑞士军刀",ClickHouse 是"磁盘上的分析重炮"。
二、性能对比:延迟与吞吐量
读性能
| 场景 | Redis | ClickHouse | 胜者 | 原因 |
|---|---|---|---|---|
| 单 key 点查询 | 0.1-1ms | 5-20ms | Redis | 纯内存寻址,无磁盘 IO |
| 范围查询(1000 行) | 10-50ms (ZRANGE) | 5-10ms (列存压缩) | ClickHouse | 列存+向量化执行,扫描极快 |
| 聚合查询(COUNT/SUM) | 不支持 (需 Lua 脚本) | 0.5-2s (亿级数据) | ClickHouse | 预聚合+向量化,PB 级优化 |
| 全文搜索 | 支持 (RediSearch) | 支持 (倒排索引) | 平局 | 两者都通过插件扩展 |
| 向量相似度搜索 | 1-10ms (HNSW) | 10-100ms (实验性 ANN) | Redis | 内存索引,延迟更低 |
结论:Redis 赢在点查的极致延迟,ClickHouse 赢在批量扫描的吞吐量。
写性能
| 场景 | Redis | ClickHouse | 胜者 | 原因 |
|---|---|---|---|---|
| 单 key 写入 | 0.1-0.5ms | 不适用(最小批量写入) | Redis | 内存写入+异步刷盘 |
| 批量写入(10万行) | 500-1000ms (Pipeline) | 100-200ms (INSERT) | ClickHouse | 列存批量压缩,写入极快 |
| 实时流写入 | 10万 TPS | 5万 TPS (需攒批) | Redis | Stream 支持高吞吐 |
| 更新操作 | O(1) 极快 | 慢 (MergeTree 合并) | Redis | ClickHouse 不适合高频更新 |
结论:Redis 适合高频实时写入,ClickHouse 适合批量导入。
三、数据模型与存储结构
Redis:行式存储 + 富数据结构
# 存储示例:用户对象
HSET user:1001 name "tom" age 25 city "beijing"
# 物理结构:Hash 表,每个 field-value 独立存储
# 内存占用:约 100 字节(含指针开销)
# 存储示例:排行榜
ZADD game_rank 1000 "player1" 2000 "player2"
# 物理结构:跳表 + Hash 表,双份内存
特点:
- 内存占用高:每个 key-value 都有额外指针开销(约 50 字节)
- 数据结构丰富:10+ 种数据结构,覆盖大部分业务场景
- 编码优化:小数据用 ziplist/intset 节省内存
ClickHouse:列式存储 + 极致压缩
-- 建表
CREATE TABLE user_behavior (
user_id UInt64,
event_time DateTime,
event_type String,
product_id UInt64,
amount Decimal(10, 2)
) ENGINE = MergeTree()
ORDER BY (user_id, event_time);
-- 物理存储(每个列独立文件)
/user_behavior/
├── user_id.bin # 列存文件(压缩后 1GB)
├── user_id.mrk2 # 标记文件
├── event_time.bin # 列存文件(压缩后 0.5GB)
├── event_type.bin # 列存文件(压缩后 0.8GB)
└── ... # 每列一个文件
特点:
- 压缩率超高:LZ4/ZSTD 压缩,10-20 倍压缩比(1TB 原始数据 → 50GB 存储)
- 列存优势:只读取查询涉及的列,减少 IO
- 不支持事务:无法回滚,适合 append-only 场景
压缩对比:
| 数据类型 | Redis 内存占用 | ClickHouse 磁盘占用 | 压缩比 |
|---|---|---|---|
| 1 亿行日志 | 约 50GB | 约 2.5GB | 20:1 |
四、扩展性与高可用架构
Redis:主从 + Sentinel + Cluster
架构演进路径:
单机 → 主从复制(备份)→ 哨兵模式(自动故障转移)→ Cluster(分片扩展)
# Cluster 分片(16384 槽位)
Master1 (slots 0-5460) → Slave1
Master2 (slots 5461-10922) → Slave2
Master3 (slots 10923-16383) → Slave3
扩展能力:
- 垂直扩容:升级内存(上限 512GB)
- 水平扩容:Cluster 分片,支持 PB 级数据
- 高可用:Sentinel/Cluster 自动故障转移(秒级)
限制:
- 多 key 操作受限:跨槽位
MSET失败 - 事务受限:只支持单槽位事务
- 内存成本:PB 级数据需要 数十台 服务器,成本极高
ClickHouse:分片 + 副本(Shared-Nothing)
-- 分布式表(逻辑表)
CREATE TABLE user_behavior_distributed AS user_behavior
ENGINE = Distributed(cluster_name, database, user_behavior, rand());
-- 本地表(物理存储)
CREATE TABLE user_behavior_local (
user_id UInt64,
...
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/user_behavior', '{replica}')
ORDER BY (user_id, event_time);
-- 架构(6 分片 2 副本)
Shard1(Replica1, Replica2)
Shard2(Replica1, Replica2)
...
Shard6(Replica1, Replica2)
扩展能力:
- 水平扩展:增加分片,线性提升写入和查询性能
- 高可用:副本机制,单节点故障自动切换
- 低成本:PB 级数据只需 3-5 台 服务器(压缩后数据量小)
限制:
- 扩容复杂:增加分片需重新平衡数据(
ALTER TABLE ... MOVE PARTITION) - 写入吞吐:单节点写入约 50-100MB/s,需批量导入
五、持久化与数据安全
| 维度 | Redis | ClickHouse |
|---|---|---|
| 持久化机制 | RDB(快照)+ AOF(日志) | WAL + MergeTree 定期合并 |
| 数据丢失风险 | 最多丢 1 秒数据(AOF everysec) | 不丢数据(立即落盘) |
| 恢复速度 | 快(加载 RDB) | 慢(需合并 parts) |
| 备份方式 | BGSAVE + 文件拷贝 | ALTER TABLE … FREEZE |
| 容灾方案 | 主从复制/哨兵/Cluster | 副本 + 异地复制 |
| 适用场景 | 缓存可容忍少量丢失 | 分析数据必须持久化 |
ClickHouse 持久化优势:
- Write-Ahead Log:写入即落盘,crash 后不丢数据
- MergeTree 引擎:数据 part 不可变,支持 原子替换分区
六、SQL 与查询能力
Redis:弱 SQL 支持,命令式操作
# 无标准 SQL,使用特定命令
GET user:1001:name
HGETALL user:1001
ZRANGE game_rank 0 10
扩展:
- RediSearch:支持类 SQL 查询
FT.SEARCH idx "@name:tom" - RedisJSON:支持 JSONPath 查询
- 无复杂 JOIN/聚合:需 Lua 脚本或客户端实现
ClickHouse:标准 SQL + 丰富分析函数
-- 标准 SQL 支持
SELECT user_id, sum(amount) as total_amount
FROM user_behavior
WHERE event_date >= '2024-01-01'
GROUP BY user_id
HAVING total_amount > 1000
ORDER BY total_amount DESC
LIMIT 100;
-- 高级分析函数
SELECT
user_id,
sumIf(amount, event_type = 'purchase') as purchase_amount,
avgIf(amount, event_type = 'refund') as refund_avg,
uniqExact(product_id) as distinct_products
FROM user_behavior
GROUP BY user_id;
优势:
- 完整 SQL 支持:几乎覆盖标准 SQL 语法
- 向量化执行:SIMD 指令加速,查询极快
- 丰富聚合函数:
uniqExact、sumIf、quantile等
七、典型应用场景对比
用 Redis 的场景
// 1. 缓存热点数据
String userJson = redis.get("user:" + userId);
if (userJson == null) {
userJson = db.queryUser(userId);
redis.setex("user:" + userId, 3600, userJson);
}
// 2. 分布式锁
RLock lock = redisson.getLock("lock:order:" + orderId);
lock.tryLock(10, TimeUnit.SECONDS);
// 3. 实时排行榜
ZADD game_rank user_score user_id
// 4. 计数器/限速器
INCR user:daily:request:count
EXPIRE user:daily:request:count 86400
// 5. 消息队列(Stream)
XADD orders * order_id 1001 status "paid"
// 6. 布隆过滤器(防穿透)
BF.ADD bloom:product product_id
总结:实时、高频、低延迟的场景
用 ClickHouse 的场景
-- 1. 用户行为分析
SELECT event_type, count() as cnt, uniqExact(user_id) as uv
FROM user_behavior
WHERE event_date >= today() - 7
GROUP BY event_type;
-- 2. 日志分析(ELK 替代)
SELECT toStartOfHour(log_time) as hour, count() as log_count
FROM nginx_logs
WHERE status_code >= 500
GROUP BY hour
ORDER BY hour DESC;
-- 3. 时序数据监控
SELECT
toStartOfMinute(metric_time) as minute,
avg(cpu_usage) as avg_cpu
FROM system_metrics
WHERE metric_time >= now() - INTERVAL 1 HOUR
GROUP BY minute;
-- 4. A/B 测试效果分析
SELECT
experiment_group,
sumIf(conversion, converted = 1) / count() as conversion_rate
FROM ab_test_results
GROUP BY experiment_group;
总结:批量、分析、聚合的场景
混合架构:互补而非替代
应用层
├── 实时高频请求 → Redis(缓存、计数、锁)
└── 离线分析查询 → ClickHouse(报表、日志、行为分析)
数据流向:
日志/行为数据 → Kafka → Flink/Spark → ClickHouse(批量导入)
↓
热点数据 → Redis(TTL 缓存)
示例:
- 用户实时余额:Redis String(高频更新)
- 用户月度账单:ClickHouse(批量聚合)
八、成本与硬件需求
| 成本项 | Redis(Cluster) | ClickHouse | 优势方 |
|---|---|---|---|
| 内存 | TB 级(数据全内存) | GB 级(缓存热点) | ClickHouse |
| 磁盘 | 小(RDB/AOF 备份) | 大(原始数据 10-20 倍压缩) | Redis(运行时) |
| CPU | 中(单线程,多核利用低) | 高(向量化,多核满载) | 取决于查询复杂度 |
| 网络 | 高(主从同步、Gossip) | 中(批量导入) | ClickHouse |
| 服务器数量 | 多(PB 级需 50-100 台) | 少(PB 级 3-10 台) | ClickHouse |
| 运维复杂度 | 高(分片、槽位、故障转移) | 中(SQL 管理) | ClickHouse |
| 人力成本 | 高(需 Redis 专家) | 中(DBA 可上手) | ClickHouse |
TCO 对比(PB 级):
- Redis Cluster:50 台 256GB 内存服务器 ≈ $500k/年
- ClickHouse:5 台 2TB SSD 服务器 ≈ $50k/年
九、功能特性对比
| 功能 | Redis | ClickHouse | 备注 |
|---|---|---|---|
| 事务 | ✅ 单命令原子性 | ❌ 不支持 | Redis 部分支持 Lua 脚本事务 |
| 复杂 JOIN | ❌ 不支持 | ✅ 完整支持 | ClickHouse 支持多表关联 |
| 子查询 | ❌ 不支持 | ✅ 完整支持 | ClickHouse 支持嵌套子查询 |
| 窗口函数 | ❌ 不支持 | ✅ 支持 | ClickHouse 支持 ROW_NUMBER() 等 |
| 物化视图 | ❌ 不支持 | ✅ 支持自动更新 | ClickHouse 预聚合利器 |
| 数据更新 | ✅ O(1) 极快 | ❌ 慢(异步 Merge) | ClickHouse 更新通过 ALTER … UPDATE |
| TTL 自动过期 | ✅ 内置 | ✅ 支持列级 TTL | 两者都支持 |
| 备份恢复 | ✅ RDB/AOF | ✅ 分区冻结 + 拷贝 | ClickHouse 备份更快 |
| 权限管理 | ✅ ACL | ✅ RBAC + 行级权限 | ClickHouse 更细粒度 |
| GIS 支持 | ✅ GEO 命令 | ✅ 实验性 | Redis 更成熟 |
| JSON 支持 | ✅ RedisJSON | ✅ 原生 JSON 类型 | ClickHouse JSONEachRow 引擎 |
十、选型决策树
需要毫秒级响应?
├── 是 → 数据量 < 100GB?
│ ├── 是 → Redis(缓存、计数器、锁)
│ └── 否 → Redis Cluster(分片扩展)
│
需要复杂分析查询?
├── 是 → 数据量 > 1TB?
│ ├── 是 → ClickHouse(PB 级 OLAP)
│ └── 否 → PostgreSQL/MySQL(中小规模分析)
│
需要高并发写入?
├── 是 → Redis(10 万+ TPS)
└── 否 → ClickHouse(批量导入)
混合架构(推荐):
实时层(Redis)+ 分析层(ClickHouse)+ 离线层(Hive)
十一、总结
Redis 是内存中的瑞士军刀,解决高频实时问题;ClickHouse 是磁盘上的分析重炮,解决批量查询问题。两者不是竞争关系,而是黄金搭档——Redis 扛住流量洪峰,ClickHouse 深挖数据价值。选型时记住: Redis 赢在延迟,ClickHouse 赢在吞吐;Redis 赢在简单,ClickHouse 赢在分析。
更多推荐
所有评论(0)