Redis 应用场景

记录一些 Redis 应用场景

作为版本号

  • 场景:
    • CS 架构、微服务模式下,服务端提供一个接口可以查询大量数据,以数组形式返回; 数据量如此之大,以至于保存在 MySQL 和 Redis 都会导致请求延迟过大,无法应对高并发场景。
    • Server 端采用本地内存缓存的形式应对高并发场景,缓存会设置超时时间
    • 某些情况下,数据数组会发生变化,CS 之间以先推后拉的形式通知,即服务端先通知客户端,客户端再查询最新数据
  • 问题: 存在下面可能的时序:
    1. Client 刚调用了查询接口,创建了本地缓存
    2. Server 更新了数组,通知 Client 拉取
    3. Client 拉取时,由于缓存未超时,拉取到了旧数据
  • 方案:
    • 在 Redis 中用一个整型的 key 作为版本号
    • 当写入数据之后,利用Incr原子性的升高版本号,然后再发通知
    • 在缓存的 key 设计中,把版本号作为 key 的一部分
    • 查询时先查出最新版本号,再查询/建立缓存,避免使用旧数据
  • 优点:
    • 既解决了
  • 改进:
    • 上面流程并没有及时释放旧缓存,如果并发修改数据,会导致缓存残留 OOM。 可以在发现版本号变化(查询时)后,开启一个异步处理,短时间内就可清理无用的旧缓存

作为任务队列

微博头条评论区排序显示

  • 基本排序方法

  • 关注好友优先显示

特殊场景

Lua 脚本 VS SPOP

问题: 需要将一个集合中的数据一次性取出

方案 1: SPOP key [count] 该命令在 redis3.2 之后提供,可以一次取出集合中的多个元素。

方案 2: 利用 lua 脚本,将元素取出并删除,实现原子操作。这样不用依赖 redis3.2 版本以上就可以实现。

  • 使用 lua 脚本时要注意,如果要兼容 cordis,在同一个脚本中涉及的 key 要在一个分片上。

方案 3: 利用SMEMBERS将所有元素取出,然后用SREM一次性删除这些取出的元素,之后再开始对元素进行处理。虽然操作不是原子的,但是也符合取出后再处理的逻辑。