当前位置:网站首页>How to deal with keys when Redis is large?
How to deal with keys when Redis is large?
2022-08-09 22:05:00 【technical trivia】
今天来聊聊,关于 Redis 大 key 的四个问题.
- 什么是 Redis 大 key?
- 大 key 会造成什么问题?
- 如何找到大 key ?
- 如何删除大 key?
什么是 Redis 大 key?
大 key 并不是指 key 的值很大,而是 key 对应的 value 很大.
一般而言,The following two cases are called large key:
- String 类型的值大于 10 KB;
- Hash、List、Set、ZSet The number of elements of type exceeds 5000个;
大 key 会造成什么问题?
大 key It will bring the following four effects:
- The client timed out and blocked.由于 Redis Executing the command is a single-threaded process,Then in operation big key will be more time consuming,那么就会阻塞 Redis,From the client's perspective,There is no response for a long time.
- cause network congestion.Get big every time key 产生的网络流量较大,如果一个 key 的大小是 1 MB,每秒访问量为 1000,Then it will be generated every second 1000MB 的流量,这对于普通千兆网卡的服务器来说是灾难性的.
- 阻塞工作线程.如果使用 del 删除大 key 时,会阻塞工作线程,Then there is no way to process subsequent commands.
- Uneven distribution of memory.cluster model in slot 分片均匀情况下,会出现数据和查询倾斜情况,部分有大 key 的 Redis 节点占用内存多,QPS 也会比较大.
如何找到大 key ?
1、redis-cli --bigkeys 查找大key
可以通过 redis-cli --bigkeys Command Find Large key:
redis-cli -h 127.0.0.1 -p6379 -a "password" -- bigkeys使用的时候注意事项:
- The best option is to execute the command on the slave node.因为主节点上执行时,会阻塞主节点;
- 如果没有从节点,那么可以选择在 Redis 实例业务压力的低峰阶段进行扫描查询,以免影响到实例的正常运行;或者可以使用 -i 参数控制扫描间隔,避免长时间扫描降低 Redis 实例的性能.
shortcomings of this method:
- This method can only return the largest of each type bigkey,无法得到大小排在前 N 位的 bigkey;
- 对于集合类型来说,This method only counts the number of elements in the collection,而不是实际占用的内存量.但是,There are many elements in a set,并不一定占用的内存就多.因为,It is possible that each element occupies a small amount of memory,这样的话,即使元素个数有很多,总内存开销也不大;
2、使用 SCAN Command Find Large key
使用 SCAN 命令对数据库扫描,然后用 TYPE 命令获取返回的每一个 key 的类型.
对于 String 类型,可以直接使用 STRLEN 命令获取字符串的长度,也就是占用的内存空间字节数.
对于集合类型来说,有两种方法可以获得它占用的内存大小:
- 如果能够预先从业务层知道集合元素的平均大小,那么,可以使用下面的命令获取集合元素的个数,然后乘以集合元素的平均大小,这样就能获得集合占用的内存大小了.List 类型:LLEN 命令;Hash 类型:HLEN 命令;Set 类型:SCARD 命令;Sorted Set 类型:ZCARD 命令;
- If the size of the elements written to the collection cannot be known ahead of time,可以使用 MEMORY USAGE 命令(需要 Redis 4.0 及以上版本),查询一个键值对占用的内存空间.
3、使用 RdbTools Tools look great key
使用 RdbTools 第三方开源工具,可以用来解析 Redis 快照(RDB)文件,找到其中的大 key.
比如,下面这条命令,将大于 10 kb 的 key Output to a table file.
rdb dump.rdb -c memory --bytes 10240 -f redis.csv如何删除大 key?
删除操作的本质是要释放键值对占用的内存空间,不要小瞧内存的释放过程.
释放内存只是第一步,为了更加高效地管理内存空间,在应用程序释放内存时,操作系统需要把释放掉的内存块插入一个空闲内存块的链表,以便后续进行管理和再分配.这个过程本身需要一定时间,而且会阻塞当前释放内存的应用程序.
所以,如果一下子释放了大量内存,空闲内存块链表操作时间就会增加,相应地就会造成 Redis 主线程的阻塞,If the main thread is blocked,All other requests may time out,Timeouts are increasing,会造成 Redis 连接耗尽,Various exceptions are generated.
因此,删除大 key 这一个动作,我们要小心.具体要怎么做呢?这里给出两种方法:
- 分批次删除
- 异步删除(Redis 4.0版本以上)
1、分批次删除
对于删除大 Hash,使用 hscan 命令,每次获取 100 个字段,再用 hdel 命令,每次删除 1 个字段.
Python代码:
def del_large_hash():r = redis.StrictRedis(host= 'redis-host1', port= 6379)
large_hash_key = "xxx" #Large to removehash键名
cursor = '0'
while cursor != 0:
# 使用 hscan 命令,每次获取 100 个字段
cursor, data = r.hscan(large_hash_key, cursor=cursor, count= 100)
for item in data.items():
# 再用 hdel 命令,每次删除1个字段
r.hdel(large_hash_key, item[ 0])
对于删除大 List,通过 ltrim 命令,每次删除少量元素.
Python代码:
def del_large_list():r = redis.StrictRedis(host= 'redis-host1', port= 6379)
large_list_key = 'xxx' #Large to removelist的键名
while r.llen(large_list_key)> 0:
#Only the rightmost is removed each time100个元素
r.ltrim(large_list_key, 0, -101)
对于删除大 Set,使用 sscan 命令,每次扫描集合中 100 个元素,再用 srem 命令每次删除一个键.
Python代码:
def del_large_set():r = redis.StrictRedis(host= 'redis-host1', port= 6379)
large_set_key = 'xxx' # Large to removeset的键名
cursor = '0'
while cursor != 0:
# 使用 sscan 命令,每次扫描集合中 100 个元素
cursor, data = r.sscan(large_set_key, cursor=cursor, count= 100)
for item in data:
# 再用 srem 命令每次删除一个键
r.srem(large_size_key, item)
对于删除大 ZSet,使用 zremrangebyrank 命令,每次删除 top 100个元素.
Python代码:
def del_large_sortedset():r = redis.StrictRedis(host= 'large_sortedset_key', port= 6379)
large_sortedset_key= 'xxx'
while r.zcard(large_sortedset_key)> 0:
# 使用 zremrangebyrank 命令,每次删除 top 100个元素
r.zremrangebyrank(large_sortedset_key, 0, 99)
2、异步删除
从 Redis 4.0 版本开始,可以采用异步删除法,用 unlink 命令代替 del 来删除.
这样 Redis 会将这个 key Put into an asynchronous thread for deletion,This will not block the main thread.
边栏推荐
- IS31FL3737B general 12 x 12 LED drive 40 QFN I2C 42 ma
- Cholesterol-PEG-Thiol,CLS-PEG-SH,胆固醇-聚乙二醇-巯基用于改善溶解度
- Overview of Security Analysis Technology for Smart Home Devices
- DP-Differential Privacy概念介绍
- IS31FL3737B 通用12×12 LED驱动器 I2C 42mA 40QFN
- 数据集成API如何成为企业数字化转型的关键?
- ClickHouse一种高性能分布式join查询模型(Colocate Join)
- 为什么数字钱包需要引入小程序生态
- 力扣383-赎金信——哈希映射数组法
- 双屏协作更高效,华硕灵耀X 双屏Pro 2022创作体验再升级
猜你喜欢
随机推荐
新出现的去中心化科学能够为科学领域带来什么?
没有 accept,我可以建立 TCP 连接吗?
小满nestjs(第四章 前置知识装饰器-实现一个GET请求)
mysql duplicate data group multiple latest records
【kali-权限提升】(4.2.6)社会工程学工具包(中):中间人攻击工具Ettercap
【NOI模拟赛】防AK题(生成函数,单位根,Pollard-Rho)
buuctf(探险2)
pytest框架之mark标记功能详细介绍
Prometheus Operator 通过additional 添加target
DSPE-PEG-Silane,DSPE-PEG-SIL,磷脂-聚乙二醇-硅烷修饰二氧化硅颗粒用
AttributeError: module ‘click‘ has no attribute ‘get_os_args‘
laravel报错:TokenMismatchException in VerifyCsrfToken.php line 68:
STM32WB55的FUS更新及协议栈固件烧写方法
【kali-权限提升】(4.2.7)社会工程学工具包:权限维持创建后门、清除痕迹
【深度学习】pix2pix GAN理论及代码实现
加工制造业智慧采购系统解决方案:助力企业实现全流程采购一体化协同
面试官:Redis 大 key 要如何处理?
MySQL笔记-06 基础SQL操作
CMake 安装升级更高版本
如何从800万数据中快速捞出自己想要的数据?