NoSQL 对比选型
大约 11 分钟约 3329 字
NoSQL 对比选型
简介
NoSQL 数据库是为了解决传统关系型数据库在大数据量、高并发和灵活数据模型方面的局限而诞生的非关系型数据库。不同类型的 NoSQL 数据库在数据模型、一致性保证、适用场景等方面差异显著。本文将对 Redis、MongoDB、Elasticsearch 和 Cassandra 四款主流 NoSQL 数据库进行对比分析,帮助开发者根据业务需求做出正确的技术选型。
特点
Redis
核心特性与适用场景
# Redis 数据类型与使用场景
# | 数据类型 | 适用场景 | 示例 |
# |------------|----------------------------|---------------------|
# | String | 缓存、计数器、分布式锁 | 用户会话、API 限流 |
# | Hash | 对象存储 | 用户信息、商品详情 |
# | List | 消息队列、最新列表 | 消息列表、最新动态 |
# | Set | 去重、集合运算 | 标签、共同好友 |
# | ZSet | 排行榜、延迟队列 | 积分排行、定时任务 |
# | Stream | 消息流 | 事件流、日志流 |
# 1. 缓存(最常见用法)
SET user:1001 '{"name":"张三","email":"zhangsan@example.com"}' EX 3600
GET user:1001
# 2. 分布式锁
SET lock:order:1001 "unique_token" NX EX 30
# NX: 仅在 key 不存在时设置
# EX 30: 30 秒后自动过期
# 释放锁(使用 Lua 脚本保证原子性)
EVAL "
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end
" 1 lock:order:1001 unique_token
# 3. 限流器(滑动窗口)
# 使用 ZSet 实现滑动窗口限流
MULTI
ZREMRANGEBYSCORE api_limit:user:1001 0 -1001
ZADD api_limit:user:1001 <current_timestamp> <unique_id>
ZCARD api_limit:user:1001
EXPIRE api_limit:user:1001 60
EXEC
# 4. 排行榜
ZADD leaderboard:score 9500 "user:A"
ZADD leaderboard:score 8800 "user:B"
ZADD leaderboard:score 9200 "user:C"
# 获取 Top 10
ZREVRANGEBYSCORE leaderboard:score +inf -inf WITHSCORES LIMIT 0 10
# 5. 消息队列(Stream)
XADD orders:stream * orderId 1001 userId 100 amount 299.00
XREAD COUNT 10 BLOCK 5000 STREAMS orders:stream $
XGROUP CREATE orders:stream order-processors $ MKSTREAM
XREADGROUP GROUP order-processors consumer1 COUNT 1 STREAMS orders:stream >Redis 集群方案
# Redis 集群模式对比
# | 模式 | 说明 | 优点 | 缺点 |
# |-------------|----------------------|--------------|-----------------|
# | 主从复制 | 一主多从 | 读写分离 | 手动故障转移 |
# | Sentinel | 哨兵自动故障转移 | 自动高可用 | 单点写入瓶颈 |
# | Cluster | 分片集群 | 水平扩展 | 限制较多 |
# Redis Cluster 配置
# redis.conf
# cluster-enabled yes
# cluster-config-file nodes.conf
# cluster-node-timeout 5000
# 创建集群(6 节点,3 主 3 从)
# redis-cli --cluster create \
# 192.168.1.101:6379 192.168.1.102:6379 192.168.1.103:6379 \
# 192.168.1.104:6379 192.168.1.105:6379 192.168.1.106:6379 \
# --cluster-replicas 1
# Redis 适用场景总结
# - 高频读写的缓存层
# - 分布式锁
# - 实时排行榜
# - 消息队列(轻量级)
# - 会话管理
# - 限流计数MongoDB
核心特性与适用场景
// MongoDB 文档模型(JSON/BSON)
// 灵活的 Schema,支持嵌套文档和数组
// 1. 文档操作
db.products.insertOne({
name: "笔记本电脑",
price: 5999.00,
category: "电子产品",
specs: {
cpu: "Intel i7-13700H",
ram: "16GB",
storage: "512GB SSD"
},
tags: ["办公", "高性能", "轻薄"],
stock: 100,
createdAt: new Date()
});
// 批量插入
db.products.insertMany([
{ name: "鼠标", price: 199.00, category: "配件" },
{ name: "键盘", price: 699.00, category: "配件" }
]);
// 2. 查询
// 基本查询
db.products.find({ category: "电子产品", price: { $gte: 3000 } });
// 嵌套文档查询
db.products.find({ "specs.cpu": { $regex: /i7/ } });
// 数组查询
db.products.find({ tags: "办公" });
// 投影(只返回需要的字段)
db.products.find(
{ category: "电子产品" },
{ name: 1, price: 1, _id: 0 }
);
// 3. 聚合管道
db.orders.aggregate([
{ $match: { status: "completed", createdAt: { $gte: ISODate("2026-04-01") } } },
{ $group: {
_id: "$category",
totalRevenue: { $sum: "$amount" },
orderCount: { $sum: 1 },
avgAmount: { $avg: "$amount" }
}},
{ $sort: { totalRevenue: -1 } },
{ $limit: 10 }
]);
// 4. 索引
db.products.createIndex({ category: 1, price: -1 });
db.products.createIndex({ name: "text" }); // 全文索引
db.products.createIndex({ location: "2dsphere" }); // 地理空间索引
// 5. 变更流(Change Stream)— 实时数据同步
const changeStream = db.orders.watch();
changeStream.on("change", (change) => {
console.log("变更类型:", change.operationType);
console.log("变更数据:", change.fullDocument);
});-- MongoDB 适用场景
-- | 场景 | 说明 |
-- |------------------|----------------------------|
-- | 内容管理系统 | 灵活的文档模型适合各种内容类型 |
-- | 用户画像 | 嵌套文档存储用户属性和行为 |
-- | IoT 数据采集 | 高写入吞吐量,灵活 Schema |
-- | 日志存储 | 大数据量写入,自动分片扩展 |
-- | 实时分析 | 聚合管道支持复杂分析 |
-- | 移动应用后端 | JSON 原生支持,与移动端契合 |Elasticsearch
核心特性与适用场景
// Elasticsearch 索引和搜索
// 1. 创建索引(定义 Mapping)
PUT /products
{
"mappings": {
"properties": {
"name": { "type": "text", "analyzer": "ik_max_word" },
"description": { "type": "text", "analyzer": "ik_max_word" },
"category": { "type": "keyword" },
"price": { "type": "float" },
"brand": { "type": "keyword" },
"tags": { "type": "keyword" },
"stock": { "type": "integer" },
"createdAt": { "type": "date" }
}
}
}
// 2. 插入文档
POST /products/_doc/1
{
"name": "Apple MacBook Pro 14英寸",
"description": "搭载 M3 Pro 芯片,18GB 内存,高性能笔记本电脑",
"category": "笔记本电脑",
"price": 14999.00,
"brand": "Apple",
"tags": ["办公", "创意", "高性能"],
"stock": 50
}
// 3. 全文搜索
GET /products/_search
{
"query": {
"multi_match": {
"query": "高性能笔记本",
"fields": ["name^3", "description"],
"type": "best_fields"
}
},
"highlight": {
"fields": {
"name": {},
"description": {}
}
}
}
// 4. 复合查询(全文搜索 + 过滤 + 聚合)
GET /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "description": "笔记本" } }
],
"filter": [
{ "term": { "category": "笔记本电脑" } },
{ "range": { "price": { "gte": 3000, "lte": 15000 } } }
],
"should": [
{ "term": { "brand": "Apple" } }
]
}
},
"sort": [
{ "_score": { "order": "desc" } },
{ "price": { "order": "asc" } }
],
"aggs": {
"brand_distribution": {
"terms": { "field": "brand", "size": 10 }
},
"price_stats": {
"stats": { "field": "price" }
}
}
}
// 5. 日志分析(ELK 技术栈)
GET /app-logs-*/_search
{
"query": {
"bool": {
"must": [
{ "match": { "level": "ERROR" } }
],
"filter": [
{ "range": { "@timestamp": { "gte": "now-1h" } } }
]
}
},
"aggs": {
"error_by_service": {
"terms": { "field": "service.name" }
},
"error_over_time": {
"date_histogram": {
"field": "@timestamp",
"calendar_interval": "5m"
}
}
}
}-- Elasticsearch 适用场景
-- | 场景 | 说明 |
-- |------------------|------------------------------|
-- | 电商搜索 | 全文搜索、筛选、排序、聚合 |
-- | 日志分析 | ELK 技术栈,实时日志检索和分析 |
-- | 应用搜索 | 站内搜索、自动补全、纠错 |
-- | 监控告警 | 指标存储、异常检测 |
-- | 地理搜索 | LBS 应用,附近搜索 |
-- | 安全分析 -- SIEM 安全信息与事件管理 |Cassandra
核心特性与适用场景
-- Cassandra 是一个分布式宽列存储数据库
-- 设计目标:高可用、线性可扩展、无单点故障
-- 1. 创建 Keyspace(类似数据库)
CREATE KEYSPACE myapp
WITH replication = {
'class': 'NetworkTopologyStrategy',
'datacenter1': 3 -- 每个数据中心 3 个副本
};
USE myapp;
-- 2. 创建表
CREATE TABLE user_activities (
user_id UUID,
activity_date DATE,
activity_time TIMESTAMP,
activity_type TEXT,
details TEXT,
device TEXT,
PRIMARY KEY ((user_id, activity_date), activity_time)
) WITH CLUSTERING ORDER BY (activity_time DESC)
AND compaction = {'class': 'TimeWindowCompactionStrategy',
'compaction_window_size': 1,
'compaction_window_unit': 'DAYS'}
AND ttl = 2592000; -- 默认 30 天过期
-- 3. 插入数据
INSERT INTO user_activities (user_id, activity_date, activity_time, activity_type, details, device)
VALUES (
uuid(),
'2026-04-12',
toTimestamp(now()),
'page_view',
'{"page": "/products/123", "referrer": "google.com"}',
'Chrome/Windows'
);
-- 4. 查询(必须包含完整分区键)
SELECT * FROM user_activities
WHERE user_id = e4a7c8b0-1234-11ee-be56-0242ac120002
AND activity_date = '2026-04-12'
ORDER BY activity_time DESC
LIMIT 50;
-- 5. 时间序列表设计
CREATE TABLE sensor_data (
sensor_id UUID,
date DATE,
timestamp TIMESTAMP,
temperature FLOAT,
humidity FLOAT,
pressure FLOAT,
PRIMARY KEY ((sensor_id, date), timestamp)
) WITH CLUSTERING ORDER BY (timestamp DESC)
AND default_time_to_live = 7776000; -- 90 天
-- 批量插入(使用 BATCH)
BEGIN BATCH
INSERT INTO sensor_data (sensor_id, date, timestamp, temperature, humidity, pressure)
VALUES (uuid(), '2026-04-12', '2026-04-12 10:00:00', 25.5, 60.0, 1013.2);
INSERT INTO sensor_data (sensor_id, date, timestamp, temperature, humidity, pressure)
VALUES (uuid(), '2026-04-12', '2026-04-12 10:05:00', 25.7, 59.8, 1013.1);
APPLY BATCH;-- Cassandra 适用场景
-- | 场景 | 说明 |
-- |------------------|-------------------------------|
-- | IoT 数据采集 -- 高写入吞吐量,时间序列存储 |
-- | 用户活动追踪 | 海量写入,按用户+时间查询 |
-- | 推荐系统 | 大规模数据存储,低延迟读取 |
-- | 消息系统 | 高可用写入,时间线存储 |
-- | 日志存储 | 海量日志写入,按时间范围查询 |综合对比
技术选型对比
-- 四款 NoSQL 数据库综合对比
-- | 维度 | Redis | MongoDB | Elasticsearch | Cassandra |
-- |-------------|--------------------|--------------------|--------------------|--------------------|
-- | 数据模型 | Key-Value | Document | Document (倒排索引) | Wide Column |
-- | 存储方式 | 内存为主 | 磁盘 | 磁盘(Lucene) | 磁盘(LSM Tree) |
-- | 读写性能 | 极高(微秒级) | 高(毫秒级) | 较高(毫秒级) | 高(毫秒级写入) |
-- | 查询能力 | 简单 | 较强 | 极强(全文搜索) | 有限(需设计查询) |
-- | 事务支持 | 有限(MULTI) | 4.0+ 支持 | 不支持 | 轻量级(BATCH) |
-- | 扩展方式 | Cluster 分片 | Sharding | 分片 | 无主架构,线性扩展 |
-- | 一致性 | 可配置 | 可配置 | 最终一致 | 可调一致性 |
-- | 数据量 | 受内存限制 | TB 级 | TB-PB 级 | PB 级 |
-- | 学习曲线 | 低 | 中 | 中高 | 高 |
-- 选型决策参考
-- | 业务需求 | 推荐 | 原因 |
-- |-------------------------|-------------------|--------------------------|
-- | 高性能缓存 | Redis | 内存存储,微秒级响应 |
-- | 灵活 Schema 的文档存储 | MongoDB | JSON 文档,Schema Free |
-- | 全文搜索 | Elasticsearch | 倒排索引,强大的搜索能力 |
-- | 海量写入 + 高可用 | Cassandra | 无主架构,线性扩展 |
-- | 实时排行榜 | Redis (ZSet) | 有序集合,天然排序 |
-- | 内容管理/用户画像 | MongoDB | 嵌套文档,灵活查询 |
-- | 日志分析和搜索 | Elasticsearch -- ELK 技术栈 |
-- | IoT 时序数据 | Cassandra | 高写入,按时间分区 |
-- | 分布式锁 | Redis | 原子操作,过期机制 |
-- | 地理位置搜索 | Elasticsearch | 地理空间查询 |混合使用策略
-- 现代应用通常组合使用多种数据库
-- 典型架构示例:电商系统
-- | 组件 | 数据库 | 职责 |
-- |----------------|----------------|----------------------|
-- | 商品/订单核心 | MySQL/PostgreSQL | 事务型数据存储 |
-- | 缓存层 | Redis | 热点数据缓存、分布式锁 |
-- | 搜索服务 | Elasticsearch | 商品搜索、日志分析 |
-- | 用户行为记录 | MongoDB | 灵活的用户行为数据 |
-- | 推荐数据 | Cassandra | 海量用户行为数据存储 |
-- 数据同步策略
-- 1. 应用双写:代码层面同时写入两个数据库
-- 优点:简单 缺点:一致性问题
-- 2. CDC(Change Data Capture):通过 Binlog 同步
-- 优点:解耦 缺点:有延迟
-- 3. 消息队列:通过 Kafka 等中间件同步
-- 优点:可靠 缺点:增加系统复杂度优点
缺点
总结
NoSQL 数据库的选型应该从业务需求出发:Redis 适合缓存和高性能键值操作,MongoDB 适合灵活的文档存储,Elasticsearch 适合全文搜索和日志分析,Cassandra 适合海量写入和高可用场景。在实际项目中,通常会组合使用关系型数据库和多款 NoSQL 数据库,各取所长。选型的关键在于理解每种数据库的设计哲学和适用边界,避免用错工具解决问题。
关键知识点
- 数据库主题一定要同时看数据模型、读写模式和执行代价。
- 很多性能问题不是 SQL 语法问题,而是索引、统计信息、事务和数据分布问题。
- 高可用、备份、迁移和治理与查询优化同样重要。
- 先把数据模型、访问模式和执行代价绑定起来理解。
项目落地视角
- 所有优化前后都保留执行计划、样本 SQL 和关键指标对比。
- 上线前准备回滚脚本、备份点和校验方案。
- 把连接池、锁等待、慢查询和容量增长纳入日常巡检。
- 保留执行计划、样本 SQL、索引定义和优化前后指标。
常见误区
- 脱离真实数据分布讨论索引或分片。
- 只看单条 SQL,不看整条业务链路的事务和锁。
- 把测试环境结论直接等同于生产环境结论。
- 脱离真实数据分布设计索引。
进阶路线
- 继续向执行计划、存储引擎、复制机制和数据治理层深入。
- 把主题与 ORM、缓存、消息队列和归档策略联动起来思考。
- 沉淀成数据库设计规范、SQL 审核规则和变更流程。
- 继续深入存储引擎、复制机制、归档与冷热分层治理。
适用场景
- 当你准备把《NoSQL 对比选型》真正落到项目里时,最适合先在一个独立模块或最小样例里验证关键路径。
- 适合数据建模、查询优化、事务控制、高可用和迁移治理。
- 当系统开始遇到慢查询、锁冲突、热点数据或容量增长时,这类主题价值最高。
落地建议
- 先分析真实查询模式、数据量级和写入特征,再决定索引或分片策略。
- 所有优化结论都结合执行计划、样本数据和监控指标验证。
- 高风险操作前准备备份、回滚脚本与校验 SQL。
排错清单
- 先确认瓶颈在 CPU、I/O、锁等待、网络还是 SQL 本身。
- 检查执行计划是否走错索引、是否发生排序或全表扫描。
- 排查长事务、隐式类型转换、统计信息过期和参数嗅探。
复盘问题
- 如果把《NoSQL 对比选型》放进你的当前项目,最先要验证的输入、输出和失败路径分别是什么?
- 《NoSQL 对比选型》最容易在什么规模、什么边界条件下暴露问题?你会用什么指标或日志去确认?
- 相比默认实现或替代方案,采用《NoSQL 对比选型》最大的收益和代价分别是什么?
