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. ◆JAVA加密解密-3DES

    从数据安全谈起       当你使用网银时,是否担心你的银行卡会被盗用?     当你和朋友用QQ进行聊天时,是否担心你的隐私会被泄露?     作为开发者,编写安全的代码比编写优雅的代码更重要,因为 ...

  2. IP地址与子网划分

    IP地址与子网划分 目录 IP地址与子网划分 一.IP地址(Internet Protocol Address) 1.IP地址的表示 2.IP地址的组成 3.IP地址的分类 (1)A类IP地址 (2) ...

  3. 使用Hot Chocolate和.NET 6构建GraphQL应用(8) —— 实现Mutate添加数据

    系列导航 使用Hot Chocolate和.NET 6构建GraphQL应用文章索引 需求 在讨论完GraphQL中的查询需求后,这篇文章我们将演示如何实现GraphQL中的数据添加任务. 思路 在G ...

  4. 【HDU6687】Rikka with Stable Marriage(Trie树 贪心)

    题目链接 大意 给定\(A,B\)两个数组,让他们进行匹配. 我们称\(A_i\)与\(B_j\)的匹配是稳定的,当且仅当目前所剩元素不存在\(A_x\)或\(B_y\)使得 \(A_i\oplus ...

  5. Solution -「AGC 004E」「AT 2045」Salvage Robots

    \(\mathcal{Description}\)   Link.   有一个 \(n\times m\) 的网格.每个格子要么是空的,要么有一个机器人,要么是一个出口(仅有一个).每次可以命令所有机 ...

  6. Solution -「USACO 2020.12 P」Sleeping Cows

    \(\mathcal{Description}\)   Link.   有 \(n\) 个牛棚,大小为 \(t_{1..n}\),\(n\) 头奶牛,大小为 \(s_{1..n}\),奶牛只能住进不小 ...

  7. c++ 字符串替换程序 p324

    字符串替换程序 C++ Primer 324页 // replace:从str字符串中查找oldVal字符串,如果找到就替换成newVal字符串. void replace(string &s ...

  8. Vue2.0源码学习(6) - 组件注册

    组件注册 前言 在 Vue.js 中,除了它内置的组件如 keep-alive.component.transition.transition-group 等,其它用户自定义组件在使用前必须注册.在开 ...

  9. ZCC2410同步升压变换芯片

    ZCC2410???? 22V/25A同步升压变换器  ZCC2410是一种高效率.高功率密度.宽输入范围.电流模式升压变换器.该转换器集成了一个10mΩ.24V电源开关和一个同步门高转换器效率的驱动 ...

  10. linux历史命令审计

    一.添加历史命令记录 1.首先在/etc/profile中添加 export HISTORY_FILE=/var/log/Command/Command.log export PROMPT_COMMA ...