1. 多大的 key 算大?

阿里云Redis 最佳实践中提到 合理的 Key 中 Value 的字节大小,推荐小于10 KB。过大的 Value 会引发数据倾斜、热点Key、实例流量或 CPU 性能被占满等问题,应从设计源头上避免此类问题带来的性能影响。那么 value Bytes >10kb 可以作为判断 大 key 的一个参考值。

2. 怎么发现大 Key ?

 --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 上扫描。

[张松鹤 > Redis 大 key 问题总结 > image2021-8-25_11-29-50.png]

主要就是 summary 部分的信息:

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

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

hash  类型  有 11485 个 key,最大的 key 是 'account_source_node_group_rel_236129' ,这个 key 有三个字段

string 类型 最大的 key 是 'cclive::dirtyword::accounts::join::6634678BEDA5BB7D' 占用内存空间  has 157374 bytes

set 类型 最大的 key 是 live_room_version' has 10 members

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

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

–-bigkeys 统计能直观的看出 string 类型 value 的大小,非 string 类型通常有以下两种方式统计:

(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 cclive::dirtyword::accounts::join::6634678BEDA5BB7D

          (integer) 157481

         127.0.0.1:6379> MEMORY USAGE user_concurrency_260468

          (integer) 312583

      # memory  命令统计的是一个预估值。从  string 类型的 user_concurrency_260468 结果看 :  memory 命令统计的是 157481 , –-bigkeys  summary 统计的是 157374 bytes

(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

       redis-memory-for-key  单 key 统计工具:(  –-bigkeys 统计结果里找到 list key  top1:  user_concurrency_260468  )

       root@vm1:~# redis-memory-for-key -s 127.0.0.1 -p 6379 -a "password" user_concurrency_260468

        [张松鹤 > Redis 大 key 问题总结 > image2021-8-25_14-30-16.png]

         # list  类型 的  user_concurrency_260468  , 153490 个 items 占用  Bytes 309250, 300kb。数据结构:quicklist

Rdbtools  第三方开源工具包

从 dump.rdb 快照文件统计(bgsave):  将所有 > 10kb 的 key 输出到一个 csv 文件
root@vm1:~# rdb dump.rdb -c memory --bytes 10240 -f live_redis.csv [张松鹤 > Redis 大 key 问题总结 > image2021-8-25_15-6-17.png]
  1. 如何优雅的删除 大 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 的方式清除。但是参数默认是关闭的。

补充:Redis key 淘汰策略 和 key 清除策略 (被动删除场景)

Redis 内存不够时 key 的淘汰策略 ,即超过了 maxmemory 的配置:

    配置参数  maxmemory-policy =volatile-lru 

noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。
allkeys-lru:当内存不足以容纳新写入数据时,移除最近最少使用的key。
allkeys-random:当内存不足以容纳新写入数据时,随机移除某个key。用数据丢失的风险。
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的 key 中,移除最近最少使用的 key。 建议配置的策略
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的 key 中,随机移除某个 key。 不管你过期不过期。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的 key 中,有更早过期时间的 key 优先移除。 Redis key 淘汰时的 清除策略:(淘汰策略 和 淘汰清除策略是两码事:淘汰策略决定了要淘汰谁,清除策略是我要如何清除淘汰的 key )

(1)惰性删除:(建议开启惰性清除策略 )

      ttl 过期的 key,不会立刻被清除,而是等下次访问时,判断过期了再自动清除。惰性删除避免了 cpu 要不停去轮询去主动发现哪个key 过期了节省了一定的 cpu 资源。配置 Lazyfree 机制惰性清除过期 key: lazyfree-lazy-expire on   (淘汰数据时,是否启用 Lazyfree)

      redis 内存使用达到maxmeory时,并设置了淘汰策略,在被动淘汰 key 时,开启 lazyfree异步清除机制: lazyfree-lazy-eviction on  (驱逐数据时,是否启用 Lazyfree)

      服务端被动清除某个 key 时,开启lazyfree异步清除机制: lazyfree-lazy-server-del on  (隐式删除服务器数据时,是否启用 Lazyfree)

(2)定时删除:( redis 默认策略 )

     redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。之所以是随机抽取,是为了避免Key过多,如果全量检查,会影响性能。redis不可能是扫描所有的 key去检查过期时间。

总结:

使用 Redis 4.0 以上的版本

–-bigkeys 、memory 命令 和  Rdbtools 工具 分析统计实例存在的 大 key

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

参考文档:

浅析Redis 4.0新特性之LazyFree: https://zhuanlan.zhihu.com/p/88024764

云数据库Redis开发运维规范 : https://help.aliyun.com/document_detail/251467.html

Redis 大 key 问题总结的更多相关文章

  1. Redis大 key的发现与删除方法全解析

    个推作为国内第三方推送市场的早期进入者,专注于为开发者提供高效稳定的推送服务,经过9年的积累和发展,服务了包括新浪.滴滴在内的数十万APP.由于我们推送业务对并发量.速度要求很高,为此,我们选择了高性 ...

  2. Redis大key的发现与删除方法全解析

    个推作为国内第三方推送市场的早期进入者,专注于为开发者提供高效稳定的推送服务,经过9年的积累和发展,服务了包括新浪.滴滴在内的数十万APP.由于我们推送业务对并发量.速度要求很高,为此,我们选择了高性 ...

  3. Redis 大 key 问题 & 问题分析 & 解决方案

    Redis 大 key 问题 & 问题分析 & 解决方案 Redis 什么是 Redis 大 key 单个key 存储的 value 很大 hash, set,zset,list 结构 ...

  4. 深度评测丨 GaussDB(for Redis) 大 Key 操作的影响

    本文分享自华为云社区<墨天轮评测:GaussDB(for Redis)大Key操作的影响>,作者: 高斯 Redis 官方博客. 在前一篇文章<墨天轮评测:GaussDB(for R ...

  5. 统计redis大key信息(前topN)

    相关包下载链接 https://github.com/sripathikrishnan/redis-rdb-tools/releaseshttps://pypi.org/project/python- ...

  6. redis 删除大key集合的方法

    redis大key,这里指的是大的集合数据类型,如(set/hash/list/sorted set),一个key包含很多元素.由于redis是单线程,在删除大key(千万级别的set集合)的时候,或 ...

  7. 如何提取Redis中的大KEY

    工作中,经常有些Redis实例使用不恰当,或者对业务预估不准确,或者key没有及时进行处理等等原因,导致某些KEY相当大. 那么大Key会带来哪些问题呢? 如果是集群模式下,无法做到负载均衡,导致请求 ...

  8. redis过期键删除策略以及大key删除方法

    今天遇到了一个前同事挖的坑,刷新缓存中商品信息时先让key过期,然后从数据库里取最新数据然后再放到缓存中,他是这样写的 redisTemplate.expire(CacheConst.GOOGS_PR ...

  9. Redis 的大 Key 对持久化有什么影响?

    作者:小林coding 图解计算机基础(操作系统.计算机网络.计算机组成.数据库等)网站:https://xiaolincoding.com 大家好,我是小林. 上周有位读者字节一二面时,被问到:Re ...

随机推荐

  1. sort、uniq、tr、cut、eval以及正则表达式

    sort.uniq.tr.cut.eval以及正则表达式 目录 sort.uniq.tr.cut.eval以及正则表达式 一.sort命令 1. sort的作用 2. 语法格式 3. 常用选项 4. ...

  2. Charles抓包工具介绍

    1.Charles是什么? Charles是一款基于http协议的代理服务器,通过称为电脑或者浏览器的代理,然后截取请求和请求结果达到分析抓包的目的. 2.Charles有哪些用途? (1)能够分析前 ...

  3. Spring Security探究之路之开始

    前言 在Spring Security介绍中,我们分析到了根据请求获取匹配的SecurityFilterChain,这个类中包含了一组Filter 接下来我们从这些Filter开始探究之旅 Sprin ...

  4. etcd受损节点重新加入集群

    文章目录 查看当前集群状态 删除受损etcd节点的数据 数据受损节点重新加入集群 修改etcd启动参数,重启etcd 由于自己的误操作,将A节点的etcd备份数据复制到B节点的etcd备份节点目录下, ...

  5. MyBatis中执行器Executor框架

    与JDK提供的Executor框架类似,MyBatis也提供了一套Executor框架,具体如下图: 其为Mybatis提供与数据库交互的功能,是一个典型的装饰器模式的应用--对JDBC功能的封装,同 ...

  6. Django视图与模板(6)

    前面记到数据库与模型(models)有联系,现在记录一下视图与模板,他们两个也有联系. 个人理解:视图就好像一个cpu,比较核心,就是用来处理问题的,又叫业务逻辑处理,他把处理完的结果插入到模板里面, ...

  7. 忘掉cmd.exe吧!选用优雅的控制台终端(ConsoleZ)

    1.使用cmd的烦恼 嵌入式开发经常会用到命令行工具,Windows系统自带的command line工具(cmd.exe)的简陋程度不用说大家都深有体会.使用cmd.exe有如下几个主要的烦恼: 没 ...

  8. Windows server 2012安装VM tools异常解决办法

    在VMWare虚拟机上安装Windows Server 2012之 后安装VMWare Tools时报如下错误信息: 问题:缺少KB2919355补丁 (先安装KB2919442,在安装KB29193 ...

  9. 【C# IO 操作】使用StringWriter和StringReader的好处

    当你有一组应用程序接口(API)只允许用Writer或Reader作为输入,但你又想使用String,这时可以用StringWriter或StringReader. 假设有下面这样一个process方 ...

  10. oj教程--坑

    1.OJ判断是只看输出结果的. 2.纯字符串用puts()输出. 3.有很多数学题是有规律的,直接推公式或用递归.循环. 4.擅用三目运算符 5.将乘法转换成加法减少时间 6.空间换时间 7.数组越界