- 为啥不能有大key;
- 有一些方法,避免大key;
- 有大key,安全删除大key;
what: 什么是大key问题
就是一个key的value特别大,比如一个hashmap中存了超多k,v;
或者一个列表key中存了超长列表,等等;
多大算大: hashmap中有100w的k,v => 1s延迟;
删除大Key的时间复杂度: O(N), N代表大key里的值数量,因为redis是单线程一个个删。
所以删大key也会卡qps。
开发规范
单key大小
Redis限制每个String类型value大小不超过512MB, 实际开发中,不要超过10KB,否则会对CPU和网卡造成极大负载。 hash、list、set、zset元素个数不要超过5000。
理论上限: 每个hashset里头元素数量< 2^32.
key的数量
官方评测: 单实例2.5亿
理论上限: 32位,2^32。约40亿
测试删除大key
可以用slowlog
命令来查看删除耗时:
1 | DEL big_key1 |
why: 为啥不能有大key
redis的基础假设是每个操作都很快,所以设计成单线程处理;
所以如果有大key,基础设计就不成立了,会阻塞;
问题:
- 数据倾斜,部分redis分片节点存储占用很高;
- 查询突然很慢,qps降低;
How: 如何避免大key
分治法,加一些key前缀\后置分解(如时间、哈希前缀、用户id后缀);
安全删除大key
- 首先要找到大key才能删除;
- 如何删除;
找到大key、删除大Key
当版本<4.0
1、导出rdb文件分析: bgsave
, redis-rdb-tool
;
2、命令: redis-cli --bigkeys
,找出最大的key;
3、自己写脚本扫描;
4、单个key查看: debug object key
: 查看某个key序列化后的长度,每次看1个key的信息,比较没效率。
删除大Key:
分解删除操作:
list: 逐步ltrim;
zset: 逐步zremrangebyscore;
hset: hscan出500个,然后hdel删除;
set: sscan扫描出500个,然后srem删除;
依次类推;
当版本>=4.0
寻找大key
命令: memory usage
删除大key: lazyfree机制
unlink
命令:代替DEL命令;
会把对应的大key放到BIO_LAZY_FREE
后台线程任务队列,然后在后台异步删除;
类似的异步删除命令:
1 | flushdb async: 异步清空数据库 |
异步删除配置:
1 | slave-lazy-flush: slave接受完rdb文件后,异步清空数据库; |