Redis 使用场景:缓存、队列与限流

Backend2026-10-05TryQuickToolBox

你构建了一个正在获得关注的 Web 应用,但随着流量增长,你注意到数据库查询变慢,偶尔还会超时。服务器在负载下苦苦挣扎,用户抱怨延迟。你需要一个快速的内存数据存储来卸载重复性任务并管理流量高峰。Redis 是许多后端挑战的首选解决方案,在本文中,我们将探讨三个实际使用场景:缓存、队列和限流。

为什么选择 Redis?

Redis 是一个开源的内存键值存储,以其速度和多功能性而闻名。它支持字符串、哈希、列表、集合和有序集合等数据结构,适用于各种任务。与传统数据库不同,Redis 将数据保存在 RAM 中,提供亚毫秒级延迟。它还提供持久化选项、复制和集群以实现高可用性。

1. 使用 Redis 进行缓存

缓存是最常见的 Redis 使用场景。通过将频繁访问的数据存储在 Redis 中,可以减轻主数据库的负载并加快响应时间。例如,如果你的应用显示热门产品列表,你可以将查询结果缓存几分钟。

如何实现缓存

  1. 检查缓存:在查询数据库之前,检查数据是否存在于 Redis 中。
  2. 如果找到(缓存命中):返回缓存的数据。
  3. 如果未找到(缓存未命中):查询数据库,将结果存储到 Redis 中并设置过期时间(TTL),然后返回数据。

以下是使用 redis-py 的 Python 示例:

import redis
import json

r = redis.Redis(host='localhost', port=6379, db=0)

def get_products():
    cache_key = 'products:popular'
    cached = r.get(cache_key)
    if cached:
        return json.loads(cached)
    # 模拟数据库查询
    products = [{'id': 1, 'name': 'Product A'}, {'id': 2, 'name': 'Product B'}]
    r.setex(cache_key, 300, json.dumps(products))  # 缓存 5 分钟
    return products

最佳实践:使用有意义的缓存键,设置适当的 TTL,并考虑缓存失效策略。对于频繁变化的数据,使用较短的 TTL 或实现写穿缓存。

2. 使用 Redis 实现队列

Redis 列表和流非常适合构建简单的消息队列。它们允许你将耗时的任务(如发送电子邮件或处理图像)从请求-响应周期中解耦,从而改善用户体验和可扩展性。

使用列表作为队列

你可以使用 LPUSH 将任务添加到列表中,并使用 BRPOP 从另一端原子地弹出任务。这创建了一个 FIFO 队列。

生产者:

r.lpush('email_queue', json.dumps({'to': 'user@example.com', 'subject': 'Welcome'}))

消费者(在工作进程中):

while True:
    _, job = r.brpop('email_queue', timeout=30)
    if job:
        process_email(json.loads(job))

注意事项:Redis 列表很简单,但缺少确认等高级功能。对于更健壮的需求,可以考虑 Redis Streams,它支持消费者组和消息确认。

3. 使用 Redis 进行限流

限流保护你的 API 免受滥用并确保公平使用。Redis 的原子操作使其成为实现限流器的理想选择。一种常见的算法是滑动窗口计数器,但更简单的固定窗口方法也很有效。

固定窗口限流器

为每个用户递增计数器并设置过期时间。如果计数器超过限制,则拒绝请求。

def is_allowed(user_id, limit=100, window=60):
    key = f'rate_limit:{user_id}'
    current = r.incr(key)
    if current == 1:
        r.expire(key, window)
    return current