转载: redis中的bigkey问题

reference:  https://www.modb.pro/db/459810

 

什么是bigkey

bigkey就是redis key/value体系中的大value问题。我们知道redis的底层数据存储结构中,有多种数据结构的实现。

String: 简单动态字符串

List: 双向链表、压缩列表 

Hash: 哈希表、压缩列表 

Sorted Set: 跳表、压缩列表 

Set: 整数列表

一般来说,bigkey在value是字符串类型时,表现为字符串的长度过长;value为复合类型(hash、list、set、zset)时,表现为包含的元素个数过多,或者成员总大小过大。

bigkey的危害

  1. 超时阻塞。由于redis单线程的特性,操作bigkey通常比较耗时,也就意味着阻塞redis的可能性很大,这样会造成客户端阻塞,造成慢查。

  2. 网络拥塞。bigkey意味着每次获取数据产生的网络流程较大。假设一个bigkey为1MB,客户端每秒访问1000,那么每秒产生1000MB的流量,对于千兆网卡(128MB/s)的服务器来说,可以说是灾难了。

  3. 内存空间不均匀。在集群模式下,由于bigkey的存在,会造成主机节点的内存不均匀,这样不利于集群对于内存的统一管理。

  4. 阻塞删除。删除一个大key造成主库较长时间的阻塞。

bigkey产生的原因

主要原因:程序设计地不合理。

常见的几种业务场景

社交类:粉丝列表,如果某些明星或者大V不精心设计的情况下,就是bigkey。

统计类:例如按天存储某项功能或者网站的用户集合,除非没几个人用,否则也会是bigkey。

缓存类:将数据从数据库load出来序列化放在redis里,这个方式经常用,但是有两个地方需要注意:第一,是不是要把所有字段都缓存;第二,有没有关联的数据。

怎么应对:在程序设计中,我们要对数据量的增长和边界有一个基本性的评估,做好技术选型和技术架构。

bigkey的发现和监控

痛点:监控程序带来redis性能损耗。

redis内置命令

debug object:阻塞其他请求

 MEMORY USAGE:时间复杂度O(N) 

获取key长度命令:STRLEN、HLEN、SCARD、ZCARD、LLEN、XLEN

MEMORY USAGE

给出一个key和它在RAM中占用的字节数,是一种内存维度的抽样算法, 计算key大小是通过抽样部分field来估算总大小。

时间复杂度O(N),N是抽样的个数。

返回的结果是key的值以及为管理该key分配的内存总字节数。

127.0.0.1:6379> MEMORY usage runoobkey samples 5
(integer) 160

memory usage默认抽样5个field来循环累加计算整个key的内存大小,样本的数量决定了key的内存大小的准确性和计算成本,样本越大,循环次数越多,计算结果更精确,性能消耗也越多。

redis-cli客户端

redis-cli --bigkeys

Redis提供了bigkeys参数能够使redis-cli以遍历的方式分析整个Redis实例中的所有Key并汇总以报告的方式返回结果。

优点:在线扫描,不阻塞服务。缺点:分析结果不可定制化。只能计算每种数据结构的top1。

bigkeys仅能分别输出Redis六种数据结构中的最大Key,如果你想只分析STRING类型或是找出全部成员数量超过10的HASH Key,那么bigkeys在此类需求场景下将无能为力。

开源工具

RDB文件扫描

redis-rdb-tools

https://github.com/sripathikrishnan/redis-rdb-tools?spm=a2c6h.12873639.article-detail.7.6e225a65k3bqC8

使用redis-rdb-tools工具以定制化方式找出大Key。

redis-rdb-tools 是一个 python 的解析 rdb 文件的工具,在分析内存的时候,我们主要用它生成内存快照。

主要有以下三个功能:

生成内存快照

转储成 json 格式

使用标准的 diff 工具比较两个 dump 文件

图片来源:https://www.cnblogs.com/cheyunhua/p/10598181.html

可以将CSV的数据导入到MySQL,这样就可以利用sql语句对Redis的内存数据进行各种分析。

rdr

https://github.com/xueqiu/rdr

./rdr show -p 8080 *.rdb

redis-rdb-cli

https://github.com/leonchen83/redis-rdb-cli

RDB持久化:是一种内存快照的形式,按照一定的频次进行快照落盘。

 

优点:这是一种理想化的选择,不会影响redis服务的进行。缺点:有些redis服务没有采用RDB持久化,不具有普遍性。时效性更差。

定制化

手动使用SCAN + TYPE并配合STRLEN等命令自己实现一个Redis实例级的大Key分析工具。

支持固定key值和key patten。在key patten中,通过scan pattern得到一定范围的key,再通过length函数对每种类型的key("HLEN""LLEN""SCARD""ZCARD""PFCOUNT""STRLEN")取值,得到对应的key的length。

如何优化big key?

1.合理优化数据结构。拆:将大的key,拆成小的key。压缩:对较大的数据进行压缩处理。

2.选择其他存储方案。比如文档性数据库MongoDB。

如何删除big key

推荐使用 UNLINK 命令,异步删除 bigkey,不影响主线程执行其他命令。在业务的低峰期使用 scan 命令查找 big key,对于类型为集合的key,可以使用脚本逐一删除里面的元素。

 

 

参考: 

https://segmentfault.com/a/1190000039953951

https://github.com/sripathikrishnan/redis-rdb-tools?spm=a2c6h.12873639.article-detail.7.6e225a65k3bqC8 

https://github.com/xueqiu/rdr

https://github.com/leonchen83/redis-rdb-cli

 

posted on 2023-06-26 19:27  alex.shu  阅读(55)  评论(0编辑  收藏  举报

导航