参考文档:
【原创】谈谈redis的热key问题如何解决
JAVA秘籍之Redis BigKey
1. hot key
1.1 什么是热点 key 问题
其实 热 key 问题说来也很简单,就是瞬间有几十万的请求去访问 redis 上某个固定的 key,从而压垮缓存服务的情况。其实生活中也是有不少这样的例子。比如 XX 明星结婚。那么关于 XX 明星的 Key 就会瞬间增大,就会出现热数据问题。
1.2 怎么发现热点 key
方式一
凭借业务经验,比如秒杀。
方式二
在客户端收集。
缺点:对客户端代码造成入侵。
方式三
在 proxy 层收集
有些集群架构是下面这样的,Proxy 可以是 Twemproxy,是统一的入口。可以在 Proxy 层做收集上报,但是缺点很明显,并非所有的 redis 集群架构都有 proxy。
方式四
用 redis 自带命令
- monitor 命令,该命令可以实时抓取出 redis 服务器接收到的命令,然后写代码统计出热 key 是啥。当然,也有现成的分析工具可以给你使用,比如 redis-faina。但是该命令在高并发的条件下,有内存增暴增的隐患,还会降低 redis 的性能。
- hotkeys 参数,redis 4.0.3 提供了redis-cli 的热点 key 发现功能,执行 redis-cli 时加上 –hotkeys 选项即可。但是该参数在执行的时候,如果 key 比较多,执行起来比较慢。
1.3 热点 key 解决方案
1.3.1 利用二级缓存
比如利用 ehcache,或者一个 HashMap 都可以。在你发现热 key 以后,把热 key 加载到系统的 JVM 中。
针对这种热 key 请求,会直接从 jvm 中取,而不会走到 redis 层。
假设此时有十万个针对同一个 key 的请求过来,如果没有本地缓存,这十万个请求就直接怼到同一台 redis 上了。
现在假设,你的应用层有 50 台机器,OK,你也有 jvm 缓存了。这十万个请求平均分散开来,每个机器有 2000 个请求,会从 JVM 中取到 value 值,然后返回数据。避免了十万个请求怼到同一台 redis 上的情形。
1.3.2 备份热 key
这个方案也很简单。不要让 key 走到同一台 redis 上不就行了。我们把这个 key,在多个 redis 上都存一份不就好了。接下来,有热 key 请求进来的时候,我们就在有备份的 redis 上随机选取一台,进行访问取值,返回数据。
假设 redis 的集群数量为 N,步骤如下图所示
2. big key
2.1 什么是 bigkey
在 Redis 中,一个字符串最大 512 MB,一个二级数据结构(例如hash、list、set、zset)可以存储大约40亿个(2^32-1)个元素,但实际上中如果下面两种情况,我就会认为它是 bigkey。
- 字符串类型:它的 big 体现在单个 value 值很大,一般认为超过 10KB 就是 bigkey。
- 非字符串类型:哈希、列表、集合、有序集合,它们体现在元素个数太多。
2.2 危害
- 内存空间不均匀
- 超时堵塞
- 网络拥塞
- 迁移困难
2.3 如何发现
- redis-cli --bigkeys
- memory usage
2.4 如何优化
2.4.1 拆分
big list: list1、list2、...listN
big hash:可以做二次的hash,例如hash%100
日期类:key20190320、key20190321、key_20190322。
2.4.2 本地缓存
减少访问 redis 次数,降低危害,但是要注意这里有可能因此本地的一些开销(例如使用堆外内存会涉及序列化,bigkey 对序列化的开销也不小)