大批量往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提供的管道 --pipe命令插入200W大批量数据
time cat /root/redisTest.txt | redis-cli -h 127.0.0.1 -p 6381 -a 123456 --pipe
time用于查看耗时多长
可以看出插入200w条数据,耗时才不到6秒,还是非常快的
尝试使用 keys * ,查看所有的key花费多长时间
花费29秒,但是如果遇到数量更大,网路状况更差等情况,时间将会进一步变长
keys *这个指令有致命的弊端,在实际环境中最好不要使用
这个指令没有offset、limit 参数,是要一次性吐出所有满足条件的 key,由于redis 是单线程的,其所有操作都是原子的,而keys算法是遍历算法,复杂度是O(n),如果实例中有千万级以上的key,这个指令就会导致Redis服务卡顿,所有读写Redis的其它的指令都会被延后甚至会超时报错,可能会引起缓存雪崩甚至数据库宕机。
生产上限制keys * /flushdb/flushall等危险命令以防止误删误用?
通过配置设置禁用这些命令,redis.conf在SECURITY这一 项中
如果就想遍历,但是又不用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 的游标时, 表示迭代已结束。例如:
在上面这个例子中, 第一次迭代使用 0 作为游标, 表示开始一次新的迭代。第二次迭代使用的是第一次迭代时返回的游标, 也就是命令回复第一个元素的值 —— 15
COUNT 选项
虽然 SCAN 命令不保证每次迭代所返回的元素数量, 但我们可以使用 COUNT 选项, 对命令的行为进行一定程度上的调整。 COUNT 选项的作用就是让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素。虽然这个选项只是对增量式迭代命令的一种提示(hint), 但是在大多数情况下, 这种提示都是有效的。
MATCH 选项
和 KEYS 命令一样,让命令只返回和给定模式相匹配的元素, 这一点可以通过在执行增量式迭代命令时, 通过给定 MATCH 参数来实现。
多大才算Big
大的内容不是key本身,而是它对应的value
string类型控制在10KB以内,hash、list、 set、 zset元素 个数不要超过5000
为什么list、hash、 set和zset个数超过5000就是bigkey?
list最多可以包含232-1个元素,接近43亿,hash也可以存储接近43个键值对…
确实理论上能存储这么多数据,但是实际上谁会存这么多数据呀?理论和实际还是有很大区别的
BigKey有哪些危害?
内存占用过大:BigKey会占用较多的内存空间,如果Redis中存在过多的BigKey,会导致Redis的内存占用过大,可能会引起系统性能下降、甚至OOM(Out of Memory)错误。
网络传输效率低下:当从Redis中读取BigKey时,由于数据量较大,会导致网络传输效率低下,造成读取延迟和网络拥堵。
数据备份和恢复困难:在进行Redis数据备份和恢复时,BigKey会增加备份和恢复的时间和成本,同时也会增加备份文件和恢复文件的大小。
内存碎片问题:当Redis删除一个BigKey时,由于其占用的内存空间较大,可能会导致内存碎片问题,从而影响Redis的内存管理效率。
如何产生?
社交类:比如某个明星的粉丝列表,典型案例粉丝逐步递增
汇总统计:某个报表,月日年经年累月的积累
如何发现?
命令:redis-cli --bigkeys
该命令的优点:
给出每种数据结构Top1bigkey,同时给出每种数据类型的键值个数+平均大小
该命令的缺点:
想查询大于10kb的所有key, --bigkeys参数就无能为力了,需要用到memory usage来计算每个键值的字节数
redis-cli --bigkeys -a 123456 -p 6381
命令:MEMORY USAGE 键
MEMORY USAGE 命令给出一个 key 和它的值在 RAM 中所占用的字节数。
返回的结果是 key 的值以及为管理该 key 分配的内存总字节数。
如何删除?
非字符串的bigkey,不要使用del删除,使用hscan、sscan、 zscan方式渐进式删除, 同时要注意防止bigkey过期时间自动删除问题(例如一个200万的zset设置1小时过期,会触发del操作,造成阻塞,且该操作不会出现在慢查询中
每次都一次删除一点,等到数据量小了之后,再一次性全部删除
BigKey生产调优
使用惰性删除,提高效率