redis做缓存的时候如何感知数据库变化

redis做缓存的时候如何感知数据库变化
最新回答
紫夜雪舞

2020-08-19 07:23:23

Redis 作为缓存时感知数据库变化的核心机制包括以下几种:

1. KEYS 命令 + 主动轮询
  • 原理:通过 KEYS 命令查找匹配特定模式的键(如包含数据库记录 ID 的键),定期扫描并删除已变更的缓存键。
  • 实现方式

    在数据库更新时,记录变更的记录 ID 或表名。

    定时任务(如每分钟)执行 KEYS 命令匹配相关键(如 user:*),并调用 DEL 删除。

  • 缺点:KEYS 是阻塞命令,键数量大时性能差,不推荐生产环境使用。
2. EXPIRE 命令 + 短过期时间
  • 原理:为缓存键设置较短的过期时间(如 5 分钟),依赖过期自动失效。
  • 实现方式

    写入缓存时设置 EXPIRE key 300。

    数据库更新后,不主动删除缓存,而是等待自然过期。

  • 缺点:存在短暂的数据不一致(过期前仍可能读到旧数据)。
3. Pub/Sub 订阅数据库变更
  • 原理:利用 Redis 的发布/订阅功能,数据库更新时主动通知缓存服务。
  • 实现方式

    数据库触发器:在数据库更新时(如 MySQL 的 binlog 或触发器),将变更事件(如 user:123:updated)发布到 Redis 频道。

    缓存服务订阅:Redis 订阅该频道,收到消息后删除对应键(如 DEL user:123)。

  • 优点:实时性强,适合高一致性场景。
  • 缺点:需额外开发数据库到 Redis 的通知中间件。
4. Lua 脚本 + 原子性操作
  • 原理:通过 Lua 脚本在 Redis 服务器端执行复杂逻辑(如检查时间戳或版本号)。
  • 实现方式

    缓存数据时存储版本号或时间戳(如 SET user:123 "data" EX 3600 和 SET user:123:version 1)。

    读取时通过 Lua 脚本比较版本号,若版本不一致则返回空并触发缓存更新。

  • 优点:原子性强,减少网络开销。
  • 缺点:需设计合理的版本管理逻辑。
5. 第三方库与工具
  • 推荐方案

    Spring Cache + Redis:通过 @CacheEvict 注解在数据库更新时自动清除缓存。

    Canal:监听 MySQL 的 binlog,解析变更后操作 Redis。

    Redisson:提供分布式锁和缓存失效的封装 API。

  • 优点:简化开发,集成度高。
如何选择?
  • 低一致性需求:用 EXPIRE + 短过期时间。
  • 高实时性:Pub/Sub 或 Canal 监听 binlog。
  • 复杂业务逻辑:Lua 脚本或第三方库(如 Redisson)。
  • 避免使用:生产环境慎用 KEYS 命令。
最佳实践建议
  1. 双写一致性:先更新数据库,再删除缓存(而非更新缓存),避免并发问题。
  2. 异步处理:通过消息队列(如 Kafka)解耦数据库和缓存操作。
  3. 本地缓存 + Redis:多级缓存(如 Caffeine + Redis)减少 Redis 压力。

通过组合上述机制,可以平衡性能、一致性和实现复杂度。例如,用 Canal 监听 binlog + Redis Pub/Sub 通知,既能保证实时性,又避免频繁轮询。