MongoDB 与 Redis:文档数据库与键值缓存
学习者将对比 MongoDB 丰富的查询模型与 Redis 基于内存的键值处理速度,并判断哪些工作负载适合分别使用它们。
MongoDB 与 Redis:文档数据库与键值缓存 是 CoddyKit 上的免费 MongoDB Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 MongoDB Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 MongoDB Academy 课程共包含 4 节课。
不同工具适用于不同任务
MongoDB 和 Redis 都是 NoSQL 数据库,但解决的是根本不同的问题。MongoDB 是通用文档数据库,专为丰富的查询能力、灵活的模式和持久化存储而设计。Redis 是内存数据结构存储,专为亚毫秒级延迟、简单的访问模式以及临时或半持久化数据而设计。理解何时使用其中一种、何时将两者结合使用,是一项重要的架构技能。
MongoDB 的核心优势
当您需要以下能力时,MongoDB 表现出色:丰富的查询能力(按任意字段、嵌套文档和数组进行筛选);灵活的模式(不同文档可以拥有不同字段);持久化存储(通过可配置的写关注级别,使数据在重启后仍然保留);较大的文档容量(最大 16 MB,而 Redis 受字符串大小限制);以及用于复杂服务端转换的聚合管道。MongoDB 适合作为应用程序的主数据存储。
Redis 的核心优势
当您需要以下能力时,Redis 表现出色:亚毫秒级延迟(数据完全存储在 RAM 中);简单的键值访问(按键 get/set,无需复杂查询);丰富的数据结构(字符串、列表、集合、有序集合、哈希和流,全部存储在内存中);原子操作(递增、push、pop——无需事务即可避免竞态条件);以及每个键内置 TTL,可自动过期。Redis 适合缓存、会话、队列以及发布/订阅。
经典模式:MongoDB 与 Redis 搭配使用
大多数生产应用会同时使用两者:将 MongoDB 作为主要的持久化数据存储,将 Redis 作为其前端的缓存层。应用会先检查 Redis(缓存命中 → 立即返回),未命中时再回退到 MongoDB(缓存未命中 → 查询 MongoDB → 将结果以 TTL 存入 Redis)。这种模式可以大幅降低 MongoDB 的负载,并将 Redis 亚毫秒级的响应时间带给用户。
const redis = require('redis').createClient()
const client = await MongoClient.connect(process.env.MONGO_URI)
async function getProduct(productId) {
const cacheKey = 'product:' + productId
// 1. Check Redis cache
const cached = await redis.get(cacheKey)
if (cached) return JSON.parse(cached) // cache hit
// 2. Cache miss — fetch from MongoDB
const product = await client.db('shop').collection('products').findOne({ _id: new ObjectId(productId) })
// 3. Store in Redis with 5-minute TTL
await redis.setEx(cacheKey, 300, JSON.stringify(product))
return product
}使用 Redis 存储会话
HTTP 会话需要基于 key 的快速查找(会话 ID → 会话数据)、自动过期(TTL 等于会话超时时间)以及高并发能力。这些要求使 Redis 成为理想选择,而 MongoDB 用于会话存储则功能过剩。connect-redis 是一个常用的 Node.js 库,可以将 Redis 直接接入 Express 会话中间件,替代默认的内存存储。
const session = require('express-session')
const RedisStore = require('connect-redis').default
app.use(session({
store: new RedisStore({ client: redis }),
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: { secure: true, maxAge: 3600000 } // 1 hour
}))
// Session data stored in Redis — instant lookup, auto-expiry使用 Redis 进行速率限制
速率限制要求以原子方式统计每个用户在每个时间窗口内的请求数。Redis 的 INCR 命令会递增计数器,并且该操作具有原子性,因此非常适合此场景。可以使用类似 rate:userId:minute 的 key,并为其设置 60 秒的 TTL;每次请求时递增计数器,如果计数器超过限制就拒绝请求。在 MongoDB 中实现这一功能需要使用事务,复杂得多。
async function checkRateLimit(userId, maxRequests = 100) {
const key = 'rate:' + userId + ':' + Math.floor(Date.now() / 60000)
const count = await redis.incr(key)
if (count === 1) {
await redis.expire(key, 60) // set TTL on first increment
}
if (count > maxRequests) {
throw new Error('Rate limit exceeded')
}
return { remaining: maxRequests - count }
}使用 Redis 有序集合构建排行榜
Redis 有序集合(ZADD、ZRANGE、ZRANK)非常适合实时排行榜。每个成员都有一个分数,Redis 会自动按排序顺序维护这些成员。获取排名前 100 的玩家或查找某个玩家的排名只需 O(log N),比在大型集合上执行 MongoDB 的 find().sort().limit() 查询快得多。
// Add/update player score
await redis.zAdd('leaderboard:game', [
{ score: 9842, value: 'player:alice' },
{ score: 7210, value: 'player:bob' }
])
// Top 10 players (highest scores)
const top10 = await redis.zRange('leaderboard:game', 0, 9, { REV: true, WITHSCORES: true })
// Player's rank (0-indexed)
const rank = await redis.zRevRank('leaderboard:game', 'player:alice')
console.log('Alice rank:', rank + 1)MongoDB 优于 Redis 的场景
在以下情况下,应选择 MongoDB 而不是 Redis:数据必须可靠地经受重启(Redis 持久化是可选的,而且速度较慢);需要跨多个字段执行复杂查询;文档大小超过几兆字节;需要跨多个文档执行 ACID 事务;或者数据集大于可用 RAM(Redis 必须将数据装入内存,而 MongoDB 可以将数据分页到磁盘)。对于核心领域数据——用户、订单和产品——MongoDB 是正确的存储选择。
Redis 优于 MongoDB 的场景
在以下情况下,应选择 Redis 而不是 MongoDB:需要亚毫秒级响应时间且 RAM 预算允许;访问模式是基于 key 的查找,无需按值搜索;数据是临时性的(会话、缓存、临时状态);需要发布/订阅消息或简单的任务队列;或者需要使用原子计数器递增来实现速率限制、浏览次数统计或库存占用。
数据模型比较
MongoDB 将数据组织为集合中的 BSON 文档——每个文档都可以具有包含数组和子文档的丰富嵌套结构。Redis 将数据组织为key → value 对,其中 value 可以是字符串、列表、集合、有序集合或哈希,但嵌套结构并非其原生能力。MongoDB 文档可以按任意字段查询;Redis value 只能通过其准确的 key(或集合/有序集合成员)访问。这一根本差异决定了其他所有权衡。
// MongoDB: query by any field
db.users.find({ city: 'Istanbul', age: { $gte: 18 } })
// Redis: access only by key (no ad-hoc field queries)
await redis.hGetAll('user:alice123') // get all fields of Alice's hash
// No equivalent to 'find all users in Istanbul' without a secondary index持久化与耐久性比较
MongoDB 的写入默认具有耐久性——使用 w: majority 时,只有在写入被复制到副本集的大多数成员并写入日志后,写入才会得到确认。Redis 的持久化是可选的:RDB 快照会定期保存数据集(两次快照之间的数据可能在崩溃时丢失),而AOF 日志记录可以配置为实现接近持久化的写入,但会增加延迟。对于任务关键型数据,MongoDB 能提供更强的耐久性保证。
快速检查
测试您对本课 MongoDB 与 NoSQL 数据库概念的理解。
课程回顾
本课您学习了:MongoDB 和 Redis 解决的是不同问题——MongoDB 用于可进行丰富查询的持久化数据,Redis 用于以内存数据为基础的亚毫秒级 key 访问;经典模式是同时使用两者——将 MongoDB 作为主要存储,将 Redis 作为缓存和临时数据层;此外,Redis 擅长会话、速率限制、排行榜和发布/订阅,而 MongoDB 擅长复杂查询、大型文档和持久化领域数据。接下来我们将比较 MongoDB 与 Cassandra。
用 AI 导师学习 JavaScript — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 30
- 课程
- 120
常见问题解答
「MongoDB 与 Redis:文档数据库与键值缓存」课时是免费的吗?
是的 — 「MongoDB 与 Redis:文档数据库与键值缓存」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 MongoDB Academy 课程的其余内容,请升级到 CoddyKit PRO。 MongoDB Academy 课程共包含 4 节课。
「MongoDB 与 Redis:文档数据库与键值缓存」这节课中我会学到什么?
学习者将对比 MongoDB 丰富的查询模型与 Redis 基于内存的键值处理速度,并判断哪些工作负载适合分别使用它们。 你通过在浏览器中直接运行的动手代码来练习 MongoDB Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 MongoDB Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 MongoDB Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「MongoDB 与 Redis:文档数据库与键值缓存」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 MongoDB Academy 课中编写并运行代码吗?
能。每节 MongoDB Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- MongoDB 与 Redis:文档数据库与键值缓存
- MongoDB 与 Cassandra:行星级写入
- MongoDB 与 DynamoDB:云原生权衡
- 何时使用 Neo4j 等图数据库