谈谈BigKey的理解

我们都知道Redis是一种kv键值对存储数据的非关系型数据库,当一个key的value值过大时,就会出现BigKey的问题,最直接的影响就是会影响我们redis的性能和稳定,所以我们需要清除和排查BigKey

首先多大算大Key?

一般情况下:

  • String 类型的 key 对应的value超过 10 MB。
  • list、set、hash、zset等集合类型,集合元素个数超过 5000个、

其实在实际开发中,对于大Key的定义也不是固定的,根据业务场景做出不同的判断

BigKey一般是如何产生的

在 各种不同的场景下都可能会出现BigKey问题,一般都是程序设计不当,对数据规模计划不清导致的

1、社交类:粉丝列表,逐步递增或者粉丝太多
2、统计类:如果按天存储某项功能或网站的用户集合,除非没几个人用,否则必定是bigkey
3、缓存类:作为数据库数据的冗余存储

BigKey会造成什么危害?

1.内存空间不均匀

在集群模式下,BigKey的存在会导致内存空间不均匀,这样不利于集群对内存的统一管理,无法做到负载均衡,并且集群的迁移也会十分困难

2.超时阻塞

由于Redis在命令串行执行时采用单线程,这也导致了操作BigKey操作会十分耗时,造成阻塞

3.网路阻塞

bigkey 也就意味着每次获取要产生的网络流量较大。假设一个 bigkey 为 1MB,客户端每秒访问量为 1000,那么每秒产生 1000MB 的流量,对于普通的千兆网卡(按照字节算是 128MB/s)的服务器来说简直是灭顶之灾。

4.阻塞删除

有个 bigkey,对它设置了过期时间,当它过期后会被删除,如果使用 Redis 4.0 之前的版本,过期 key 是异步删除,就会存在阻塞 redis 的可能性,而且这个过期删除不会从慢查询发现(因为这个删除不是客户端产生的,是内部循环事件)。

如何查找BigKey

1.通过bigkeys命令

优点

给出每种数据结构Top 1 bigkey,同时给出每种数据类型的键值个数+平均大小

不足

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

2.MEMORY USAGE key

如何优雅的删除BigKey

SCAN命令

特点:

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

 

SCAN 返回一个包含两个元素的数组, 

第一个元素是用于进行下一次迭代的新游标, 

第二个元素则是一个数组, 这个数组中包含了所有被迭代的元素。如果新游标返回零表示迭代已结束。

 

SCAN的遍历顺序

非常特别,它不是从第一维数组的第零位一直遍历到末尾,而是采用了高位进位加法来遍历。之所以使用这样特殊的方式进行遍历,是考虑到字典的扩容和缩容时避免槽位的遍历重复和遗漏。

String类型:

一般直接使用DEL,如果是BigKey使用unlink进行异步删除

DEL key [key ...]

del命令会直接删除指定的键以及与之相关联的值。如果键不存在,则不执行任何操作。del命令不会释放已经分配的内存,因此如果有需要释放内存的场景,需要使用Redis提供的其他命令。

del命令是一种同步命令,即它会阻塞客户端,直到所有指定的键都被删除为止。在删除大量键的情况下,del命令可能会导致Redis服务器阻塞一段时间。因此,在删除大量键时,应该考虑使用异步删除方式,以避免阻塞客户端。

UNLINK key [key ...]

其中,key是要删除的键名。可以指定多个键名,删除多个键。如果指定的键不存在,则会被忽略。

与del命令不同的是,unlink命令会异步地删除指定的键以及与之相关联的值。即,它会将要删除的键添加到一个待删除的列表中,并立即返回,不会阻塞客户端。Redis服务器会在后台异步地删除待删除列表中的键。

使用unlink命令的好处是可以减少删除操作的阻塞时间。在删除大量键的情况下,unlink命令可以使Redis服务器更快地响应客户端请求。

Hash类型:

使用hscan每次获取少量filed-value,在使用hdel删除每一个filed

List类型:

使用ltrim渐进式逐步删除

Set类型:

使用sscan每次获取部分元素,再用srem删除每个元素

Zset类型:

使用zscan每次获取部分元素,再使用ZREMRANGEBYRANK删除每个元素

BIGKEY生产调优

lazyfree-lazy-server-del

针对有些指令在处理已存在的键时,会带有一个隐式的DEL键的操作。如rename命令,当目标键已存在,redis会先删除目标键,如果这些目标键是一个big key,那就会引入阻塞删除的性能问题。 此参数设置就是解决这类问题,建议可开启。

slave-lazy-flush

针对slave进行全量数据同步,slave在加载master的RDB文件前,会运行flushall来清理自己的数据场景,

参数设置决定是否采用异常flush机制。如果内存变动不大,建议可开启。可减少全量同步耗时,从而减少主库因输出缓冲区爆涨引起的内存使用增长。

 后台删除之lazyfree机制

为了解决redis使用del命令删除大体积的key,或者使用flushdb、flushall删除数据库时,造成redis阻塞的情况,在redis 4.0引入了lazyfree机制,可将删除操作放在后台,让后台子线程(bio)执行,避免主线程阻塞。

生产上如何限制keys*/flushdb/flushall等危险命令?

通过配置设置禁用这些命令或者替换这些命令

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力学习的小飞侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值