Redis 单线程问题 BigKey问题

news2024/11/27 20:24:21

前言

简单的redis基础类型以及常用操作我们都也已经介绍过了

现在今天我们来谈谈redis对于单线程是需要怎么理解的

以及redis假设遇见大key我们需要怎么去查询和删除呢???

redis单线程

假设有个人现在问你一个问题:redis是单线程的还是多线程的

这个问题本身就不严谨

就像问java有没有泛型是一样的

这和版本有关,redis在4之前是不存在多线程的

那么为什么呢,我们接下来聊

redis4也是仅仅在一些操作中简单支持了多线程

但是还是在redis6/7中才完全支持多线程

我们先说说这个单线程是什么意思吧

这里的单线程主要是说对于网络IO和键值对读写是由一个线程来完成的

可以理解为redis的工作线程是单线程的

但是redis的整体还是多线程的

比如aof集群复制数据等等    

单线程为啥快??

我们可以从两点来答

1.Redis使用内存操作,没有大量耗时的磁盘IO操作,性能较高

2.redis底层的数据结构使得他的大部分查找和操作都是O(1)的时间复杂度

3.redis使用了多路复用的技术来监听多个socket客户端,这样就可以避免IO阻塞的操作了

4.避免了上下文切换,省去了多线程竞争的开销,不会存在死锁的问题

IO多路复用

这里再介绍一下IO多路复用

其实我们理解的万事万物皆为文件是因为比如说各种网卡什么的都可以以文件形式表示

这里的IO多路复用我们可以理解为此时假设有三个用户和我建立连接,像做一些事情

但是如果其中某个资源迟迟没有结束就会出现对应的阻塞

这里IO多路复用就是一个线程监听多个socket

将返回的fd文件描述符丢给内核

当其中的任何一个文件描述符具备读写条件的时候就放进就绪队列

直接执行就绪队列的操作即可

就避免了线程的阻塞等等

那单线程这么好,为啥还用多线程呢???

1.时代的发展

2.比如通常删除一个key非常的快

但是删除一个大key就会导致这里卡顿或者阻塞

这里使用惰性删除就可以很好的解决这个问题

使用unlink来进行删除大key

3.还有就是对redis的主要瓶颈其实是内存和网络带宽

但是这里就有可能出现单个线程处理网络请求的速度比不上硬件处理的速度

所以现在对于读写还是使用单线程来操作

但是对于网络IO就使用多线程来操作了

归根结底还是硬件的发展使然

下面我们介绍一下一个redis请求的全线路流程吧

首先是主线程建立连接

放入等待队列

将socket分配给IO线程 

然后IO线程和对应的socket进行绑定  这里就是多线程

然后解析请求等操作也是多线程来完成的

执行结束之后交给主线程使用IO多路复用技术进行对应的操作

执行完成之后不是直接返回而是刷进缓冲区,等待IO线程回写socket

这里我们就可以发现这里的IO线程也是多线程的

只有主线程是单线程的操作

IO线程其实是多线程的操作 

redis默认的配置是不开启多线程的

我们可以通过对应的配置文件来开启多线程

 什么时候开启呢

假设这个时候redis出现了吞吐量不大,但是cpu此时占用率又不高,这个时候就可以开启多线程来提升效率

常用配置

BigKey问题

我先抛出几个常见的面试题

1.海量数据中查询出某个固定的前缀的key如何操作

2.你如何限制keys */flushdb/flushall等危险操作的误用?

3.memory usage命令是啥意思

4.多大算BigKey呢,如何发现并删除呢

5.BigKey的调优如何解决,惰性释放了解过嘛?

6.生产上有一千万个记录,怎么遍历

我们这里先写100w个数据进去

使用pipe管道写入数据库

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


cat /tmp/redisTest.txt | /opt/redis-7.0.0/src/redis-cli -h 127.0.0.1 -p 6379 -a 111111 --pipe


注意这里的地址端口都需要修改

这里假设需要查询不建议使用keys *

我们可以使用一个新命令

scan命令

对应的危险的命令我们可以在conf文件中将其标注注释掉

类似这样

我们可以尝试一下禁用keys *等操作

禁用完了就可以看到对应的指令已经无法使用了

假设我们正常使用keys * 来查询很可能造成一个阻塞,业务一接不上就缓存雪崩了

所以是非常危险的

这里我们就引入了scan命令来查询数据

主要就是几个参数

scan  游标  模糊查询表达式  查询的数量

这里的游标是迭代器返回的

我们使用这个指令会返回一个游标和一个数组

游标作为下一个查询的输入,从0开始,结束也是0

然后可以支持前缀查询等等

最后的查询数量类似于limit

下面我们做一个简单的操作

查询5条数据

默认是查询十条数据

比如

scan 0

或者是前缀查询

对于删除也是一样,下面我们引入对应的删除操作

不可以使用flushdb 即使有异步选项进行补充

我们还是推荐使用渐进删除的方式来删除大量数据

多少数据算大key?

阿里文档写的是字符串超过10K算大key

这里的大key当然不是指key 而是键值对的value

对应的其他类型的hash list set等都是不超过5000个元素算大key

大key有什么坏处呢?

大key很可能导致内存分布不均

集群迁移困难

超市删除慢 

网络流量阻塞等等

常见的实际案例?

某个明星的粉丝列表    某个月突然剧增

或者是日积月累的汇总报表等等

怎么发现大key?

使用 --bigkey参数来发现

redis-cli  -a  password -p port   --bigkey

这里就会扫描出来当前实体

最大占用的是什么类型

占用多大字节数等等

这里我们就会发现最大的key是我们上次使用springboot存放的值

或者可以使用

memory usage key
查看大key的占用内存情况

渐进式删除

对于string数据类型来说,只要不是特别大可以使用del来删除

如果特别大可以使用unlink来删除对应的数据

unlink是后台启动了其他的线程去做一个异步的删除策略,也是不会产生阻塞的,较为安全

我们再演示一种hash数据类型如何删除?

我们这里就用到渐进式删除的策略了

其实就是我们一次删除一部分的值

在值被掏空之后

直接整个删除即可

下面展示对应的代码示例

对于其他的数据类型也是类似的,这里不做过多讲解

简单生产调优

这里是对于惰性释放的一些参数配置

配置了之后就可以导致redis删除的时候是开一个线程做异步删除的,无需阻塞

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1805078.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

@BeforeAll 和 @AfterAll 必须是 static 的原因

BeforeAll 和 AfterAll 必须是 static 的原因 执行时机&#xff1a; BeforeAll 方法在所有测试方法之前运行。AfterAll 方法在所有测试方法之后运行。 实例化前/后的执行&#xff1a; 因为 BeforeAll 是在所有测试方法执行之前运行的&#xff0c;所以它在任何一个测试实例创建…

微信机器人实现OCR识别录入数据

介绍 采用微信的hook插件&#xff0c;然后解析微信发来的数据图片&#xff0c;通过ocr识别 然后将数据落入execl表格中。同时有权限的人可以导出数据表格即可。 流程图 代码片 文本消息处理流程_robot.py elif msg.type 0x01: # 文本消息# 管理员列表dba_user_list [wxid_…

【C语言】函数递归 (包你懂的)

文章目录 1. 前言2. 递归的定义2.1 递归的思想2.2 递归的限制条件 3. 递归举例3.1 举例1&#xff1a;求n的阶乘3.1.1 分析和代码实现3.1.2 画图演示 3.2 举例2&#xff1a;顺序打印一个整数的每一位3.2.1 分析和代码实现3.2.3 画图演示 3.3 举例3&#xff1a;求第n个斐波那契数…

Unity动画录制工具在运行时录制和保存模型骨骼运动的方法录制动画给其他角色模型使用支持JSON、FBX等格式

如果您正在寻找一种在运行时录制和保存模型骨骼运动的方法&#xff0c;那么此插件是满足您需求的完美解决方案。 实时录制角色运动 将录制到的角色动作转为动画文件 将录制好的动作给新的角色模型使用&#xff0c;完美复制 支持导出FBX格式 操作简单&#xff0c;有按钮界面…

【原创】springboot+mysql村务档案管理系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

MySQL数据库操作基础(增删查改)

数据库操作基础(增删查改) 1.插入 1.1往数据表中插入一条数据 insert into 表名 values (值,值,值...)此处列出的这些值的数目和类型 要和表的相对应 1.2指定列插入 insert into 表名(列名) values (值);1.3一次插入多个记录 insert into 表名 values (值),(值)...一次插入…

深度学习500问——Chapter10:迁移学习(1)

文章目录 11.1 迁移学习基础知识 11.1.1 什么是迁移学习 11.1.2 为什么需要迁移学习 11.1.3 迁移学习的基本问题有哪些 11.1.4 迁移学习有哪些常用概念 11.1.5 迁移学习与传统机器学习有什么区别 11.1.6 迁移学习的核心及度量准则 11.1.7 迁移学习与其他概念的区别 11.1.8 什么…

达梦数据库相关SQL及适配Mysql配置总结

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

Leetcode 力扣109. 有序链表转换二叉搜索树 (抖音号:708231408)

给定一个单链表的头节点 head &#xff0c;其中的元素 按升序排序 &#xff0c;将其转换为 平衡 二叉搜索树。 示例 1: 输入: head [-10,-3,0,5,9] 输出: [0,-3,9,-10,null,5] 解释: 一个可能的答案是[0&#xff0c;-3,9&#xff0c;-10,null,5]&#xff0c;它表示所示的高…

每日一题——Python实现PAT乙级1042 字符统计(举一反三+思想解读+逐步优化)

一个认为一切根源都是“自己不够强”的INTJ 个人主页&#xff1a;用哲学编程-CSDN博客专栏&#xff1a;每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 优点 缺点和改进建议 时间复杂度分析 空间复杂度分析 改进后的代码 我…

关键字、保留字、标识符

关键字 关键字是被 Java 赋予了特定含义的英文单词。 关键字的字母全部小写。 保留字 现有的 Java 版本尚未使用&#xff0c;但是以后版本可能会作为关键字使用。自己命名标识符时需要避免使用这些保留字。 保留字有&#xff1a;byValue, cast, future, generic, inner, op…

数据并非都是正态分布:三种常见的统计分布及其应用

你有没有过这样的经历&#xff1f;使用一款减肥app&#xff0c;通过它的图表来监控自己的体重变化&#xff0c;并预测何时能达到理想体重。这款app预测我需要八年时间才能恢复到大学时的体重&#xff0c;这种不切实际的预测是因为应用使用了简单的线性模型来进行体重预测。这个…

【吊打面试官系列-Mysql面试题】BLOB 和 TEXT 有什么区别 ?

大家好&#xff0c;我是锋哥。今天分享关于 【BLOB 和 TEXT 有什么区别&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; BLOB 和 TEXT 有什么区别 &#xff1f; BLOB 是一个二进制对象&#xff0c;可以容纳可变数量的数据。TEXT 是一个不区分大小写的 BLOB。 1…

Java 语言概述 -- Java 语言的介绍、现在、过去与将来

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 001 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…

使用proteus仿真51单片机的流水灯实现

proteus介绍&#xff1a; proteus是一个十分便捷的用于电路仿真的软件&#xff0c;可以用于实现电路的设计、仿真、调试等。并且可以在对应的代码编辑区域&#xff0c;使用代码实现电路功能的仿真。 汇编语言介绍&#xff1a; 百度百科介绍如下&#xff1a; 汇编语言是培养…

Knife4j 生成 API 文档

文章目录 Knife4j 简介使用步骤Knife4j 常用注解的列表案例注意 Knife4j 简介 Knife4j 是一个增强的 Swagger 文档生成工具&#xff0c;提供了更加友好的界面和更多功能&#xff0c;使得 API 文档更加美观且易于使用。它是基于 Spring Boot 和 Swagger 进行封装的&#xff0c;…

【下篇】从 YOLOv1 到 YOLOv8 的 YOLO 物体检测模型历史

YOLO 型号之所以闻名遐迩,主要有两个原因:其速度和准确性令人印象深刻,而且能够快速、可靠地检测图像中的物体。上回我解释了YoloX, 今天从Yolov6开始。 YOLOv6:面向工业应用的单级物体检测框架 美团视觉人工智能事业部(Meituan Vision AI Department)于 2022 年 9 月在…

《精通ChatGPT:从入门到大师的Prompt指南》第4章:避免常见错误

第4章&#xff1a;避免常见错误 在使用ChatGPT进行Prompt编写时&#xff0c;常见的错误可能会大大影响生成内容的质量和准确性。本章将详细讨论这些错误&#xff0c;并提供如何避免它们的建议。 4.1 不明确的指令 在使用ChatGPT时&#xff0c;一个常见的问题是指令不够明确。…

Vue3中的常见组件通信之$attrs

Vue3中的常见组件通信之$attrs 概述 ​ 在vue3中常见的组件通信有props、mitt、v-model、 r e f s 、 refs、 refs、parent、provide、inject、pinia、slot等。不同的组件关系用不同的传递方式。常见的撘配形式如下表所示。 组件关系传递方式父传子1. props2. v-model3. $re…

LLVM Cpu0 新后端4

想好好熟悉一下llvm开发一个新后端都要干什么&#xff0c;于是参考了老师的系列文章&#xff1a; LLVM 后端实践笔记 代码在这里&#xff08;还没来得及准备&#xff0c;先用网盘暂存一下&#xff09;&#xff1a; 链接: https://pan.baidu.com/s/1V_tZkt9uvxo5bnUufhMQ_Q?…