Redis的MoreKey和BigKey问题

文章目录

  • 1、MoreKey案例
  • 2、BigKey案例

1、MoreKey案例

大批量往Redis里面插入200w测试数据key

在Linux Bash下面执行,插入200w数据

for((i=1;i<=200*10000;i++)); do echo "set k$i v$i">>/root/redisTest.txt;done;

使用命令 tail -10 redisTest.txt 查看最后10行记录

Redis的MoreKey和BigKey问题_第1张图片

通过redis提供的管道 --pipe命令插入200W大批量数据

time cat /root/redisTest.txt | redis-cli -h 127.0.0.1 -p 6381 -a 123456 --pipe

time用于查看耗时多长

Redis的MoreKey和BigKey问题_第2张图片

可以看出插入200w条数据,耗时才不到6秒,还是非常快的

尝试使用 keys * ,查看所有的key花费多长时间

Redis的MoreKey和BigKey问题_第3张图片

花费29秒,但是如果遇到数量更大,网路状况更差等情况,时间将会进一步变长
keys *这个指令有致命的弊端,在实际环境中最好不要使用

这个指令没有offset、limit 参数,是要一次性吐出所有满足条件的 key,由于redis 是单线程的,其所有操作都是原子的,而keys算法是遍历算法,复杂度是O(n),如果实例中有千万级以上的key,这个指令就会导致Redis服务卡顿,所有读写Redis的其它的指令都会被延后甚至会超时报错,可能会引起缓存雪崩甚至数据库宕机。

生产上限制keys * /flushdb/flushall等危险命令以防止误删误用?
通过配置设置禁用这些命令,redis.conf在SECURITY这一 项中

Redis的MoreKey和BigKey问题_第4张图片

配置完成,重新启动,再次实验
Redis的MoreKey和BigKey问题_第5张图片

如果就想遍历,但是又不用keys * 避免卡顿,那该怎么办呢?
此时可以使用scan命令,类似mysql中的limit,但不完全相同,它用于迭代数据库中的数据库键

Redis SCAN 命令及其相关命令 SSCAN, HSCAN ZSCAN 命令都是用于增量遍历集合中的元素

SCAN 命令用于迭代当前数据库中的数据库键
SSCAN 命令用于迭代集合键中的元素
HSCAN 命令用于迭代哈希键中的键值对
ZSCAN 命令用于迭代有序集合中的元素(包括元素成员和元素分值)

redis SCAN 命令基本语法如下:

SCAN cursor [MATCH pattern] [COUNT count]
cursor - 游标。
pattern - 匹配的模式。
count - 指定从数据集里返回多少元素,默认值为 10 。

以上列出的四个命令都支持增量式迭代, 它们每次执行都只会返回少量元素, 所以这些命令可以用于生产环境, 而不会出现像 KEYS 命令、 SMEMBERS 命令带来的问题 —— 当 KEYS 命令被用于处理一个大的数据库时, 又或者 SMEMBERS 命令被用于处理一个大的集合键时, 它们可能会阻塞服务器达数秒之久。

SCAN 命令的基本用法:
SCAN 命令是一个基于游标的迭代器,每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。

SCAN 返回一个包含两个元素的数组, 第一个元素是用于进行下一次迭代的新游标, 而第二个元素则是一个数组, 这个数组中包含了所有被迭代的元素。当 SCAN 命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代,而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。例如:

Redis的MoreKey和BigKey问题_第6张图片

在上面这个例子中, 第一次迭代使用 0 作为游标, 表示开始一次新的迭代。第二次迭代使用的是第一次迭代时返回的游标, 也就是命令回复第一个元素的值 —— 15

COUNT 选项

虽然 SCAN 命令不保证每次迭代所返回的元素数量, 但我们可以使用 COUNT 选项, 对命令的行为进行一定程度上的调整。 COUNT 选项的作用就是让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素。虽然这个选项只是对增量式迭代命令的一种提示(hint), 但是在大多数情况下, 这种提示都是有效的。

Redis的MoreKey和BigKey问题_第7张图片

MATCH 选项

和 KEYS 命令一样,让命令只返回和给定模式相匹配的元素, 这一点可以通过在执行增量式迭代命令时, 通过给定 MATCH 参数来实现。

Redis的MoreKey和BigKey问题_第8张图片

2、BigKey案例

多大才算Big

大的内容不是key本身,而是它对应的value
string类型控制在10KB以内,hash、list、 set、 zset元素 个数不要超过5000

为什么list、hash、 set和zset个数超过5000就是bigkey?
list最多可以包含232-1个元素,接近43亿,hash也可以存储接近43个键值对…
确实理论上能存储这么多数据,但是实际上谁会存这么多数据呀?理论和实际还是有很大区别的

BigKey有哪些危害?

  1. 内存占用过大:BigKey会占用较多的内存空间,如果Redis中存在过多的BigKey,会导致Redis的内存占用过大,可能会引起系统性能下降、甚至OOM(Out of Memory)错误。

  2. 网络传输效率低下:当从Redis中读取BigKey时,由于数据量较大,会导致网络传输效率低下,造成读取延迟和网络拥堵。

  3. 数据备份和恢复困难:在进行Redis数据备份和恢复时,BigKey会增加备份和恢复的时间和成本,同时也会增加备份文件和恢复文件的大小。

  4. 内存碎片问题:当Redis删除一个BigKey时,由于其占用的内存空间较大,可能会导致内存碎片问题,从而影响Redis的内存管理效率。

如何产生?

社交类:比如某个明星的粉丝列表,典型案例粉丝逐步递增
汇总统计:某个报表,月日年经年累月的积累

如何发现?

命令:redis-cli --bigkeys

该命令的优点:
给出每种数据结构Top1bigkey,同时给出每种数据类型的键值个数+平均大小

该命令的缺点:
想查询大于10kb的所有key, --bigkeys参数就无能为力了,需要用到memory usage来计算每个键值的字节数

redis-cli --bigkeys -a 123456 -p 6381

Redis的MoreKey和BigKey问题_第9张图片

命令:MEMORY USAGE 键

MEMORY USAGE 命令给出一个 key 和它的值在 RAM 中所占用的字节数。
返回的结果是 key 的值以及为管理该 key 分配的内存总字节数。

在这里插入图片描述

如何删除?

非字符串的bigkey,不要使用del删除,使用hscan、sscan、 zscan方式渐进式删除, 同时要注意防止bigkey过期时间自动删除问题(例如一个200万的zset设置1小时过期,会触发del操作,造成阻塞,且该操作不会出现在慢查询中

比如:
Redis的MoreKey和BigKey问题_第10张图片

每次都一次删除一点,等到数据量小了之后,再一次性全部删除

如果是字符串的BigKey,则用unlink
Redis的MoreKey和BigKey问题_第11张图片

BigKey生产调优

Redis的MoreKey和BigKey问题_第12张图片

使用惰性删除,提高效率

你可能感兴趣的:(Redis,redis,数据库,缓存,BigKey问题,MoreKey问题)