Redis 大 key 问题处理总结

原创
2021/08/26 18:10
阅读数 174

大家好,最近一直忙于工作,文章鸽了一段时间,后续会慢慢填坑。今天,给大家分享篇我们团队小伙伴的总结 《Redis 大key问题处理总结》,可谓干货满满。


Redis 大 key 问题处理总结

通过文章你能获得:

目录

在日常Redis的使用中,我们都遇到过因为key存储了过大的数据而造成请求缓慢甚至阻塞的情况,这个时候就需要排查Redis的大key去优化业务了,下面提供一些排查方案总结,仅供参考。

多大的 key 算大

阿里云Redis 最佳实践中提到:

合理的 Key 中 Value 的字节大小,推荐小于10 KB。过大的 Value 会引发数据倾斜、热点Key、实例流量或 CPU 性能被占满等问题,应从设计源头上避免此类问题带来的性能影响。

那么 value Bytes >10kb 可以作为判断 大 key 的一个参考值。

怎么发现大 key

1、string类型可使用命令 --bigkeys

--bigkeys 是 redis 自带的命令,对整个 Key 进行扫描,统计 string,list,set,zset,hash 这几个常见数据类型中每种类型里的最大的 key。string 类型统计的是value 的字节数;另外 4 种复杂结构的类型统计的是元素个数,不能直观的看出 value 占用字节数,所以 --bigkeys 对分析 string 类型的大 key 是有用的,而复杂结构的类型还需要一些第三方工具。( 元素个数少,不一定 value 不大;元素个数多,也不一定 value 就大)

root@vm1:~# redis-cli -h 127.0.0.1 -p 6379 -a "password" --bigkeys 

--bigkeys 是以 scan 延迟计算的方式扫描所有 key,因此执行过程中不会阻塞 redis,但实例存在大量的 keys 时,命令执行的时间会很长,这种情况建议在 slave 上扫描。

image

主要就是 summary 部分的信息,分析可知:

该实例一共 有 52992 个 key,总占用内存空间:bytes is 1470203;

list 类型 有 15 个 key,最大的 key 有 153462 个元素;list 类型的 key 占了 00.03%,平均大小 10232.67 Bytes。

hash  类型  有 11485 个 key,最大的 key 是有三个字段。

string 类型 最大的 key 占用内存空间 157374 bytes。

set 类型 最大的 key 有 10 个元素。

streams 类型是开源版本 5.0 支持的新的数据类型,pub/sub 类型的增强版。

–-bigkeys 其实就是找出类型中最大的 key,最大的 key 不一定是大 key,最大的 key 都不超过 10kb 的话,说明不存在大 key。但某种类型如果存在较多的大key (>10kb),只会统计 top1 的那个 key,如果要统计所有大于 10kb 的 key,需要用第三方工具 扫描rdb持久化文件。

2/ 非 string 类型通常有以下两种方式统计:

  • 2.1/ Redis 4.0 以后的版本:支持 了  memory 命令查看 key 的大小
root@vm1:~# redis-cli -h 127.0.0.1 -p 6379 -a "password"
127.0.0.1:6379> MEMORY USAGE keyname1
(integer) 157481
127.0.0.1:6379> MEMORY USAGE keyname2
(integer) 312583

memory  命令统计的是一个预估值。与 –-bigkeys  summary 统计的略有出入。

  • 2.2/ Rdbtools 工具包:Rdbtools 是 python写的 一个第三方开源工具,用来解析 Redis 快照文件。除了解析 rdb 文件,还提供了 统计单个 key 大小的工具。
 # 如下安装
 git clone https://github.com/sripathikrishnan/redis-rdb-tools
 cd redis-rdb-tools sudo && python setup.py install

Rdbtools  第三方开源工具包, 从 dump.rdb 快照文件统计(bgsave), 将所有 > 10kb 的 key 输出到一个 csv 文件

root@vm1:~# rdb dump.rdb -c memory --bytes 10240 -f live_redis.csv 

如何优雅的删除大 key

4.0 以前 string,list,set,hash  不同数据类型的大 key,删除方式有所不同。一般有两种情况:del 命令删除单个很大的 key  和  del 批量删除 大 key。直接 del 命令粗暴的删大 key 容易造成 redis 线程阻塞。4.0 以前要优雅的删除就是针对不同的类型 写脚本,拆分链表,hash 表,分批删除。

4.0 版本以后官方对 删 大key 有了特别优化,支持了 lazy free 功能, 通常不需要开发脚本就可以删。

4.0 以后如何优雅的删除大 key 呢?

1/ 主动删除大 key

127.0.0.1:6379> UNLINK mykey

unlink 命令是  del 的异步版本,由 Lazyfree 机制实现。Lazyfree 机制的原理是在删除的时候只进行逻辑删除,把 key 释放操作放在 bio (Background I/O)单独的子线程中惰性处理,减少删除大 key 对 redis 主线程的阻塞,有效地避免因删除大key带来的性能问题。unlink 即使在批量删除 大 key 时,也不会对阻塞造成阻塞。

2/ 被动删除大 key

被动删除是指 Redis 自身的 key 清除策略,一个 大 key 过期或者被淘汰时,如何被清除,会不会导致阻塞?4.0 以前自动清除是有可能阻塞主线程的。

4.0 以后的版本,被动删除策略是可选的配置参数,允许 以 Lazyfree 的方式清除。但是参数默认是关闭的,可配置如下参数开启。

lazyfree-lazy-expire on    # 过期惰性删除
lazyfree-lazy-eviction on    # 超过最大内存惰性删除
lazyfree-lazy-server-del on    # 服务端被动惰性删除

总结

  • 使用 Redis 4.0 以上的版本

  • –-bigkeysmemory 命令 和  Rdbtools 工具 分析统计实例存在的 大 key

  • 大 key 问题,主动删除无条件使用 UNLINK 异步,被动删除时配置 lazyfree 惰性删除。

最后,根本上解决大 key 问题要从开始时就避免使用大 key。

参考文档

  • 浅析Redis 4.0新特性之LazyFree

  • 云数据库Redis开发运维规范


本文分享自微信公众号 - 码农吴先生(CoderMrWu)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部
返回顶部
顶部