Redis(九)——BigKey与MoreKey

1.线上为什么不能使用keys * ,flushdb,flushall命令?怎么禁用?

首先是为什么不能使用keys*,结合我们前几篇的内容我们可以知道,执行读写的主线程是单线程的,而且我们线上的数据一般是非常大的数量集,所以使用keys * 查全部的key的时候肯定需要很长的时间通常都是秒级的,数据越多就越长,相对于我们redis的其他命令来说,这个时间导致的线程阻塞是灾难级的(因为其他客户端命令必须等待keys*执行完成,才能执行),这样就可以理解为什么不能使用了吧。

然后这个flushdb,flushall命令就不用多说了,首先他是十分危险的,其次他删除数据时间虽然没有keys*慢,但是基本上也是秒级的,100w的数据大概是1-2秒,其他先不说,这个危险的命令线上肯定是不能使用的。

那怎么禁用这个命令?我们需要在redis的配置文件中找到security,然后找到rename-command 这个关键词,进行设置,把需要禁用的命令如rename-command keys ""这样配置好,就可以了。rename-command <需要禁用的命令> ""这个是语法格式,用来禁用命令的。

2.keys *被禁用我们应该使用什么来查询?

我们可以使用scan来进行扫描查询,这个是扫描命令的一些延续,语法格式都是一样的只是查询的数据类型不同罢了。大家可以去查看https://redis.com.cn/commands/scan.html

这个游标在我们学C的时候应该就有出现过,主包记得应该是11章还是10章反正就是讲文件的时候,我们之前说mysql的窗口函数的时候应该也说过,在redis中游标是从0开始的,也是从0结束的,为什么这么说?假如我们想查询所以是k1、k2、k3这种格式的key,那么查询的命令就是如下:scan 0 match k* 10,这个时候会返回你一个数组,第一个元素返回的就是下一次开始的游标,第二个就是这次查询到的key,如果这一次查询没有查到,那么就再查scan 100(假设返回的是100) match k* 10,然后我们再进行查询,返回的数据结构还是一样的,如果还没有我们以此类推,直到返回的游标是0了表示已经全部扫描完了,再扫描又是从头开始了。

3.什么是BigKey?什么是MoreKey?

首先我们先来看Bigkey,这个从字面上就很好理解,也就是是大建的意思,但其实指的是一个键的值非常大,这个key被称之为Bigkey,通常情况下String类型的大于10kb,hash、zset、set、lst等超过5k个成员的就被称之为BigKey,并不是因为数据类型放不下,而是因为值或者成员太多了造成了很多问题,比如说:我们删除的时候会阻塞,为什么上面已经说过了,异曲同工之秒属于是,还有就是网络拥堵,读取一个大key需要的网络带宽更大,延迟就更高,还有就是迁移问题、RDB、AOF保存问题、内存分布不均问题,迁移和RDB、AOF是因为BigKey迁移需要跟多的时间,bigKey会让集群中部分节点的内存压力过大。

好了我们再来看MoreKey,这个就是和bigKey相反了,bigkey是值键的值过大,而moreKey是相同前缀的键太多,和值没多大关系,通常情况下相同前缀的key大于10w就是morekey了,这种情况下就需要调整一下key的前缀了,morekey的危害有如下:首先就是内存碎片化,通常情况下morekey的值都不大,所以内存就会不连续,然后就是使用scan命令会变慢,查询的次数会变多,这个很好理解就不锁了,其他就是都是小问题了,所以morekey没有bigkey棘手。

4.怎么删除BigKey?怎么优化BigKey?

首先删除,我们除了string类型可以使用del外,其他的数据类型应该使用渐进式删除,也就是通过scan命令一遍一遍的查询,把每次查询出来的成员一步一步的使用del命令删除掉,等到scan的游标为0就可以删除key了,区别就是string直接删除key,而其他bigkey的数据类型需要先删除value中的成员,把成员删除完了才能删除key。

然后我们再来看看如何优化Bigkey,lazy freeing 这个配置再redis的配置文件中,这些配置就能优化bigkey的问题,主要的解决思路就是异步删除,因为不止有bigkey会导致阻塞,还有大量过期时间相同的key清理的时候也会阻塞。

配置项 默认值 作用 适用场景 性能影响 风险
**lazyfree-lazy-eviction**​ no 是否开启Lazy Free用于maxmemory策略的驱逐操作。 如果设置为yes,当Redis因为内存达到上限而需要删除键时,会尝试使用Lazy Free。 内存淘汰策略为volatile-*或allkeys-*时 减少淘汰阻塞,提高响应速度 内存回收延迟,可能短暂内存压力
**lazyfree-lazy-expire**​ no 是否开启Lazy Free用于键的过期删除。 如果设置为yes,当Redis发现某个键已经过期并需要删除时,会尝试使用Lazy Free。 大量键同时过期场景 避免过期键删除阻塞主线程 过期键不会立即释放内存
**lazyfree-lazy-server-del**​ no 如果是yes则异步处理RENAME/DEL等命令 执行RENAME、DEL等服务器命令时 减少命令执行阻塞时间 删除操作有延迟
**lazyfree-lazy-user-del**​ no 如果是yes则将DEL命令自动转为UNLINK 所有DEL命令执行场景 DEL自动非阻塞,兼容性好 内存不会立即释放
**repl-disable-lazyfree**​ no 如果是yes则在主从复制中使用lazyfree 需要强一致性复制场景 保持同步复制,数据一致 可能增加主节点阻塞风险

5.如何查看bigkey?怎么计算key值的大小?

我们可以使用这个命令进行查看都有哪些bigkeys,这个命令需要在Linux中执行,不是在redis中执行的,他会扫描真个数据库,然后把bigkey给你列出来,

复制代码
"命令": "redis-cli -h host -p port --bigkeys",
# 扫描整个数据库
Biggest string found 'user:session:123' has 1024 bytes
Biggest hash found 'product:stats' has 10000 fields
Biggest list found 'message:queue' has 50000 items
Biggest set found 'user:tags' has 20000 members
Biggest zset found 'leaderboard' has 30000 members""",
            "优点": "官方工具,简单易用",
            "缺点": "扫描期间影响性能,不能实时"

另外我们可以使用memory usage <键名>来查看这个key的值占了多少个字节。

复制代码
        {
            "方法": "MEMORY USAGE", 
            "命令": "MEMORY USAGE key_name", 
            "输出示例": "127.0.0.1:6379> MEMORY USAGE user:profile:123\n(integer) 1048576",
            "优点": "精确查看单个键内存使用", 
            "缺点": "需要知道键名,不能批量" 
        },

总结

本篇主要讲的就是Bigkey和MoreKey相关的内容。

相关推荐
百***81273 小时前
【HTML+CSS】使用HTML与后端技术连接数据库
css·数据库·html
6***3493 小时前
MySQL项目
数据库·mysql
木井巳3 小时前
【MySQL数据库】数据库基础
数据库·mysql
Wang's Blog3 小时前
MySQL: 查询全流程深度解析与性能优化实践指南
数据库·mysql·性能优化
一 乐4 小时前
宠物管理|宠物共享|基于Java+vue的宠物共享管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·springboot·宠物
Wang's Blog4 小时前
MongoDB小课堂: 高级查询操作符与游标管理综合指南之深度整合逻辑操作符、字段处理、数组查询与游标控制的最佳实践
数据库·mongodb
垂金烟柳4 小时前
MongoDB GridFS 历史数据自动化清理实践
数据库·mongodb·自动化
白露与泡影4 小时前
MySQL中的12个良好SQL编写习惯
java·数据库·面试
foundbug9994 小时前
配置Spring框架以连接SQL Server数据库
java·数据库·spring
q***31894 小时前
mysql 迁移达梦数据库出现的 sql 语法问题 以及迁移方案
数据库·sql·mysql