使用 Redis 进行缓存:为您的应用程序加速

发布: (2026年1月2日 GMT+8 11:53)
8 min read
原文: Dev.to

Source: Dev.to

TechBlogs

什么是缓存?

在深入了解 Redis 之前,首先必须了解缓存的基本原理。缓存本质上是一种技术,用于将一部分数据存储在比原始来源更快、更易访问的位置。其目标是直接从缓存中提供后续对该数据的请求,从而显著降低延迟并减轻数据库或 API 等后端系统的负载。

考虑一个经常显示热门产品列表的 Web 应用程序。 与其每次请求该列表时都查询数据库,不如使用缓存机制将热门产品列表存放在内存中。下次请求到来时,应用程序直接从缓存中获取数据,这比数据库查询快了数个数量级。

为什么选择 Redis 作为缓存?

Redis(Remote Dictionary Server)是一款开源的内存数据结构存储系统,可用作数据库、缓存和消息中间件。其设计使其在缓存场景中表现尤为出色:

  • 内存操作: 读写速度极快。
  • 数据结构丰富: 字符串、列表、集合、有序集合、哈希等多种结构,支持复杂的缓存策略。
  • 持久化选项: 可选的 RDB 快照和 AOF 日志,防止数据丢失。
  • 高可用与可扩展性: Sentinel 和 Cluster 提供高可用和水平扩展。
  • 原子操作: 防止竞争条件,确保数据完整性。
  • 发布/订阅消息: 对缓存失效策略非常有用。

Source:

常用 Redis 缓存策略

1. 缓存旁路(Cache‑Aside)模式

缓存旁路(又称懒加载)模式被广泛使用。应用程序同时与缓存和主数据源交互。

工作原理

  1. 读取请求: 应用程序首先检查缓存。
  2. 缓存命中: 直接返回数据。
  3. 缓存未命中: 从主数据源(例如数据库)获取数据。
  4. 缓存填充: 将获取到的数据存入缓存,以供后续请求使用。
  5. 返回数据: 将数据返回给调用方。

示例(Python + redis-py

import redis

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

def get_user_data(user_id):
    cache_key = f"user:{user_id}"
    cached_data = r.get(cache_key)

    if cached_data:
        print(f"Cache hit for user {user_id}")
        return cached_data.decode('utf-8')   # Assuming data is stored as a string

    print(f"Cache miss for user {user_id}")
    # Simulate fetching from a database
    user_data_from_db = fetch_user_from_database(user_id)

    if user_data_from_db:
        # Store in Redis with an expiration time (e.g., 3600 s = 1 hour)
        r.set(cache_key, user_data_from_db, ex=3600)
        return user_data_from_db
    return None

def fetch_user_from_database(user_id):
    # In a real application, this would be a database query
    print(f"Fetching user {user_id} from database...")
    return f"User Data for {user_id}"

2. 写穿(Write‑Through)模式

在写穿模式中,数据会同时写入缓存和主数据源,确保缓存始终保持最新。

工作原理

  1. 写入请求: 应用程序先将数据写入缓存。
  2. 同步写入数据源: 紧接着将相同的数据写入主数据源。
  3. 确认: 只有在两次写入都成功后,操作才算完成。

优点

  • 保证缓存与数据源之间的数据一致性。

缺点

  • 由于必须成功完成两次写入,写入延迟可能会增加。

示例(Python)

import redis

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

def update_user_data(user_id, new_data):
    cache_key = f"user:{user_id}"

    # Write to cache first
    r.set(cache_key, new_data)

    # Then write to primary data source
    update_user_in_database(user_id, new_data)

    print(f"User {user_id} data updated in cache and database.")

def update_user_in_database(user_id, new_data):
    print(f"Updating user {user_id} in database with: {new_data}")

写后(Write‑Behind / Write‑Back)模式

写后模式通过延迟写入主数据源来提升写入性能。

工作原理

  • 写入请求: 应用程序立即将数据写入缓存。
  • 异步写入数据源: 缓存将写入操作排队,并在后台(通常以批次方式)持久化到主存储。

优点

  • 大幅降低写密集型工作负载的写入延迟。

缺点

  • 如果缓存服务器在后台写入完成前宕机,可能导致数据丢失。
  • 在通用缓存场景中使用较少。

缓存失效(Cache Invalidation)

缓存失效在主数据源发生变化时,删除或更新缓存中的陈旧数据。

常见失效技术

  • 生存时间(TTL): 为缓存条目设置过期时间。
  • 显式失效: 当底层数据被更新时,删除对应的缓存条目。
  • 写穿/写后: 这些模式本身就能保持一致性。
  • 事件驱动失效: 使用 Redis Pub/Sub 广播失效消息。

显式失效示例(Python)

def update_and_invalidate_user(user_id, updated_data):
    cache_key = f"user:{user_id}"

    # Update in primary data source
    update_user_in_database(user_id, updated_data)

    # Explicitly invalidate the cache entry
    r.delete(cache_key)
    print(f"User {user_id} data")
 updated and cache invalidated.")

高级 Redis 缓存使用案例

  • 会话管理: 在分布式服务器之间存储用户会话数据,以实现快速检索。
  • 速率限制: 使用带过期时间的计数器来限制每个用户/IP 的请求次数。
  • 队列: 实现任务队列,用于异步后台作业。
  • 排行榜: 利用有序集合实现实时排名系统。
  • 完整页面缓存: 缓存整个 HTML 页面,以在无需服务器端渲染的情况下提供内容。

Redis 缓存最佳实践

  • 选择合适的数据结构: 对象使用哈希,队列使用列表,排行榜使用有序集合等。
  • 实现适当的 TTL: 将过期时间与数据的波动性和可接受的陈旧度对齐。
  • 监控缓存性能: 跟踪命中率、延迟、内存使用和驱逐策略。
  • 优雅地处理缓存未命中: 在需要时确保回退到主数据源。
  • 考虑数据序列化: 对于复杂类型使用高效的格式,如 JSON 或 MessagePack。
  • 配置驱逐策略: 了解 LRULFUvolatile‑lru 等,以管理内存压力。
  • 最小化网络延迟: 在可能的情况下将 Redis 与应用服务器同机房部署。

结论

Redis 为构建高性能缓存层提供了坚实、灵活的基础。通过理解并应用诸如 Cache‑Aside(旁路缓存)和 Write‑Through(写入直通)等模式,您可以显著降低延迟、减轻数据库负载,并提升整体响应速度。尝试最适合您使用场景的策略,让 Redis 帮助您为软件注入强大动力。

Back to Blog

相关文章

阅读更多 »