Redis 大 key 问题一文通

1. 背景

最近对接了一个卧龙同事的接口,因为接口比较慢,所以打算对第三方接口加个缓存。但是会有大 key 的问题。设计过程中调研了一些解决方案,这里总结下。 关键字:Redis;大Key问题;

2. 大 key 会带来什么问题

我们都知道,redis 是单线程架构,日常的读写操作都是由一个线程完成。一旦某一个线程执行了大 key 的读写,就会影响之后所有命令的执行,进而影响 redis 实例甚至整个 redis 集群的稳定。

3. 什么才叫大 key

那么什么才叫大 key?普遍认同的规范是:

  1. value > 10kb,即认定为大 key
  2. 像list,set,hash 等容器类型的 redis key,元素数量 > 5000,即认定为大 key

现在我们知道了大 key 会来带什么问题,也知道了什么样的 key 才算大key。接下来我们看看都有哪些解决方案。

4. 解决方案一:压缩

适用于字符串类型的 redis key。采用压缩算法,将 key 压缩至可接受的范围内。压缩也是有讲究的,首先要选择无损的压缩算法,然后在压缩速率和压缩率之间也要权衡。比较常用的压缩算法/工具如下:

  • google snappy:无损压缩,追求压缩速度而不是压缩率(Compression rate)
  • message pack:无损压缩,仅适用于 json 字符串的压缩,可以得到一个更小的 JSON,官网是:msgpack.org/

5. 解决方案二:value 切片

适用于 list,set,hash 等容器类型的 redis key。规范要求容器的元素数量 < 5000,我们可以在写 redis 的时候做个逻辑,如果超过了 5000 的容器就做切片。

举个例子,现在有一个 list 类型的缓存 ,他包含 12000 个元素。是很典型的大key。 我们以 5000 为阈值,把 list 切分成三份:user_list_slice_1、user_list_slice_2、user_list_slice_3,另外还需要一个存储切片具体情况的key,所以还需要一个 user_list_ctl。 业务程序后续访问这个缓存的时候,先请求 user_list_ctl,解析出缓存的切分情况,再去请求具体的切片即可。

6. 解决方案三:抛弃大 key(discard)

大多数场景,我们是把 redis 当缓存用,缓存失效了就走数据库查出数据。我们可以设定一个阈值,如果缓存对象特别大的话,我们就抛弃这个key,不缓存,直接走数据库。这样不会影响 redis 正常的运作。

当然,这是个取巧的方案,灵感是来自线程池的拒绝策略(DiscardPolicy)。采用这个方案得确认直接抛弃不会影响业务,还需要确保不走缓存后的性能业务上能够接受。

7. 俯瞰一下,从架构的角度解决这个问题

千叮咛万嘱咐,大 key 问题造成的线上事故仍然没有断过,这个怎么解决? 我觉得有如下几个思路

  • 完善监控机制,有大 key 出现就及时告警
  • 封禁/限流能力,能够及时封禁大 key 的访问,降低业务影响(保命用)
  • 在服务和 redis 集群之间建设 proxy 层,在 proxy 做大 key 的处理(压缩或者切片处理),让业务开发无需感知大key。

8. 总结

总结一下,解决 redis 的大 key,我们常规有三种解决方案。一是压缩,而是切片,三是直接抛弃不缓存。

都看到这了,给个赞吧

都看到这了,给个赞吧

都看到这了,给个赞吧

相关推荐
martinzh7 分钟前
Spring AI 项目介绍
后端
Bug退退退12313 分钟前
RabbitMQ 高级特性之重试机制
java·分布式·spring·rabbitmq
小皮侠14 分钟前
nginx的使用
java·运维·服务器·前端·git·nginx·github
前端付豪16 分钟前
20、用 Python + API 打造终端天气预报工具(支持城市查询、天气图标、美化输出🧊
后端·python
爱学习的小学渣19 分钟前
关系型数据库
后端
武子康21 分钟前
大数据-33 HBase 整体架构 HMaster HRegion
大数据·后端·hbase
前端付豪22 分钟前
19、用 Python + OpenAI 构建一个命令行 AI 问答助手
后端·python
凌览23 分钟前
斩获 27k Star,一款开源的网站统计工具
前端·javascript·后端
Zz_waiting.25 分钟前
Javaweb - 10.4 ServletConfig 和 ServletContext
java·开发语言·前端·servlet·servletconfig·servletcontext·域对象
全栈凯哥25 分钟前
02.SpringBoot常用Utils工具类详解
java·spring boot·后端