深入理解Redis线程模型

Redis数据

redis数据保存在内存,但是会持久化到硬盘

Redis线程

Redis的整体线程模型可以简单解释为 客户端多线程,服务端单线程。也就是可以多个客户端同时连接。

  • 核心线程模型:单线程 + 多路复用
    Redis 的主线程负责处理所有客户端请求,采用 Reactor 模式,使用 epoll(Linux)或 select/kqueue(其他平台) 实现 I/O 多路复用。
    在这里插入图片描述

Redis4.X以前的版本,都是采⽤的纯单线程。但是在2018年10⽉份,Redis5.x版本进⾏了⼀次⼤的核⼼代码重构。 到Redis6.x和7.x版本中,开始⽤⼀种全新的多线程机制来提升后台⼯作。尤其在现在的Redis7.x版本中,Redis后端的很多⽐较费时的操作,⽐如持久化RDB,AOF⽂件、unlink异步删除、集群数据同步等,都是由额外的线程执⾏的。例如,对于 FLUSHALL操作,就已经提供了异步的⽅式。

使用Redis如何保证指令原⼦性

1. 复合指令

Redis内部提供了很多复合指令,例如MSET(HMSET)、GETSET、SETNX、SETEX等都是原子性的。

2. Redis事务

像MySQL⼀样,Redis也提供了事务机制,但是略有不同。redis的事务就像批处理文件,执行一批指令,即使中间有错误也会继续往下执行,不会自动回滚。
```bash
help @transactionsDISCARD (null)  -- 放弃事务 
summary: Discards a transaction.
since: 2.0.0
EXEC (null)  --执⾏事务 
summary: Executes all commands in a transaction.
since: 1.2.0MULTI (null)  -- 
开启事务 
summary: Starts a transaction.
since: 1.2.0UNWATCH (null)  --去掉监听 
summary: Forgets about watched keys of a transaction.
since: 2.2.0WATCH key [key ...]   --监听某⼀个key的变化。如果没被修改 → 执行事务。如果有任意 key 被改 → 事务取消,不执行命令。unwatch后才可恢复
summary: Monitors changes to keys to determine the execution of a transaction.
since: 2.2.0```
- Redis事务失败如何回滚Redis中结合watch实现的事务回滚,不是回滚数据,⽽是回滚操作。1. 如果事务是在EXEC执⾏前失败(⽐如事务中的指令敲错了,或者指令的参数不对),那么整个事务的操作都不会执⾏。2. 如果事务是在EXEC执⾏之后失败(⽐如指令操作的key类型不对),那么事务中的

其他操作都会正常执⾏,不受影响。
- 事务执⾏过程中出现失败了怎么办
1. 只要客户端执⾏了EXEC指令,那么就算之后客户端的连接断开了,事务就会⼀直进⾏下去。
2. 事务有可能造成数据不⼀致。当EXEC指令执⾏后,Redis会先将事务中的所有操作都先记录到AOF⽂件中,然后再执⾏具体的操作。如果已写入aof但是事务在执行过程中服务端出现了非正常宕机,会造成AOF中记录的操作,与数据不符合。下次服务启动时,⽆法正常启动。可以redis-check-aof⼯具修复AOF⽂件,将这些不完整的事务操作记录移除掉,即可正常启动。

3. Pipeline

在 Redis 中,Pipeline(管道)是一种批量发送命令、减少网络开销的技术机制。与简单无watch的事务一样只保证一起执行,不保证一起成功一起失败。
在这里插入图片描述
在这里插入图片描述

在Linux上编辑⼀个⽂件 command.txt

set count 1
incr count
incr count
incr count

然后启动redis客户端携带参数

cat command.txt | redis-cli -a 123qweasd --pipe

4. lua脚本

lua语⾔最⼤的特点是他的线程模型是单线程的模式。
Redis 内置支持 Lua,可以通过 EVAL 命令执行一段脚本。脚本在 Redis 中一次性执行完,中途不会被其他命令打断。

eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second

lua脚本中,可以使⽤redis.call函数来调⽤Redis的命令。

eval "local initcount = redis.call('get', KEYS[1]) local a = tonumber(initcount) local b = tonumber(ARGV[1]) if a >= b then redis.call('set', KEYS[1], a) return 1 end redis.call('set', KEYS[1], b) return 0" 1 "stock_1" 10

不要在Lua脚本中出现死循环和耗时的运算,否则redis会阻塞,将不接受其他的命令。管道pipeline不会阻塞redis

  • Redis中有⼀个配置参数lua-time-limit 5000来控制Lua脚本的最⻓控制时间。默认5秒钟。当lua脚本执⾏时间超过了这个时⻓,Redis会对其他操作返回⼀个BUSY错误,⽽不会⼀直阻塞。
  • 尽量使⽤只读脚本Redis 从 7.0 起支持 EVAL_RO 命令(只读版 EVAL), 强制执行只读 Lua 脚本,更安全,避免误写

5. Redis Function

在 Redis 中,**Redis Function(函数)**是 Redis 7.0 引入的新功能,作为对传统 EVAL / EVALSHA 的增强 —— 支持将 Lua 脚本函数化、模块化、持久化,从而带来更安全、结构化、更易部署和复用的脚本执行方式。
例如,可以在服务器上新增⼀个mylib.lua⽂件。在⽂件中定义函数。

#!lua name=mylib
local function my_hset(keys, args)local hash = keys[1]local time = redis.call('TIME')[1]return redis.call('HSET', hash, '_last_modified_', time, unpack(args))
end
redis.register_function('my_hset', my_hset)

注意,脚本第⼀⾏是指定函数的命名空间,不是注释,不能少

使⽤Redis客户端,将这个函数加载到Redis中

cat mylib.lua | redis-cli -a 123qweasd -x FUNCTION LOAD REPLACE

FUNCTION LOAD LUA "$(cat mylib.lua)"

调用函数

FUNCTION CALL my_hset 1 myhash myfile "some value"

Function注意点

  • Function同样也可以进⾏只读调⽤。
  • 如果在集群中使⽤Function,⽬前版本需要在各个节点都⼿动加载⼀次。Redis不会在集群中进⾏Function同步
  • Function是要在服务端缓存的,所以不建议使⽤太多太⼤的Function。
  • Function和Script⼀样,也有⼀系列的管理指令。使⽤指令 help @scripting ⾃⾏了解。

6. Redis指令原⼦性总结

以上介绍的各种机制,其实都是Redis改变指令执⾏顺序的⽅式。在这⼏种⼯具中,Lua脚本通常会是项⽬中⽤得最多的⽅式。在很多追求极致性能的⾼并发场景,Lua脚本都会担任很重要的⻆⾊。

Redis中的Bigkey问题

在Redis中,BigKey问题指的是某些键(Key)对应的值(Value)非常大,例如包含了大量元素的 list、set、hash、zset,或者是超长的字符串。这种“超大键”可能会引发性能、内存和可用性的问题。
在Redis客户端指令中,提供了两个扩展参数,可以帮助快速发现这些BigKey

redis-cli --help--bigkeys
Sample Redis keys looking for keys with many 
elements (complexity).--memkeys
Sample Redis keys looking for keys consuming a lot of memory.

Redis线程模型总结

Redis的线程模型整体还是多线程的,只是后台执⾏指令的核⼼线程是单线程的。整
个线程模型可以理解为还是以单线程为主。基于这种单线程为主的线程模型,不同
客户端的各种指令都需要依次排队执⾏。

Redis为什么使用单线程

Redis 在性能、实现复杂度和应用场景之间做了权衡。redis的性能瓶颈不在cpu而在内存。使用单线程,是因为绝大多数操作本身就非常快,再配合 I/O 多路复用机制,可以在单线程中轻松支撑大量高并发请求,同时避免多线程带来的锁竞争和复杂性。

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

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

相关文章

「Python教案」输入输出函数的使用

课程目标 1.知识目标 能使用input()输入函数和print()输出函数实现人机之间的交互。能够合理的确定输入数据的数据类型,并进行数据类型转换。能够使用格式化字符串(f-string)将数据动态输出。 2.能力目标 能够使用…

医疗影像中,DICOM点云、三角面片实体混合渲染(VR)

此文章,涉及到专业性比较强,所以,大部分的内容,基本上都是示例代码的形式出现。以下的技术路径,完全经过实践验证,并且效果很好,可以放心使用。 1 概述 在医学影像中,对DICOM的渲染…

【C/C++】线程状态以及转换

文章目录 线程状态以及转换1 基本状态1.1 新建(New)1.2 就绪(Ready / Runnable)1.3 运行中(Running)1.4 阻塞/等待(Blocked / Waiting / Sleeping)1.5 挂起(Suspended&am…

Python与自动驾驶数据集处理:构建智能驾驶的基石

Python与自动驾驶数据集处理:构建智能驾驶的基石 在自动驾驶技术的快速发展中,数据始终是最核心的驱动力。自动驾驶系统依赖于大量的传感器数据(激光雷达、摄像头、GPS等),通过深度学习算法不断优化决策,使车辆能够自主感知、理解道路环境并做出合理决策。而 Python 作为…

【菜狗work前端】小程序加if判断时不及时刷新 vs Web

零、前提&#xff1a; 实现input输入数字不大于10000&#xff08;需要配合typenumber&#xff0c;maxlength5&#xff0c;这里没写&#xff09; 一、探究代码&#xff1a; <input v-model"model1" input"changeModel1" placeholder"请输入拒收件…

【Netty】- NIO基础2

阻塞模式 客户端代码 public class Client {public static void main(String[] args) throws IOException {SocketChannel sc SocketChannel.open();sc.connect(new InetSocketAddress("localhost", 8080));// sc.write(Charset.defaultCharset().encode("he…

【WebRTC】源码更改麦克风权限

WebRTC源码更改麦克风权限 仓库: https://webrtc.googlesource.com/src.git分支: guyl/m125节点: b09c2f83f85ec70614503d16e4c530484eb0ee4f

cocos creator使用jenkins打包微信小游戏,自动上传资源到cdn,windows版运行jenkins

cocos 版本2.4.11 在windows上jenkins的具体配置和部署&#xff0c;可参考上一篇文章cocos creator使用jenkins打包流程&#xff0c;打包webmobile_jenkins打包,发布,部署cocoscreator-CSDN博客 特别注意&#xff0c;windows上运行jenkins需要关闭windows自己的jenkins服务&a…

力扣刷题(第三十六天)

灵感来源 - 保持更新&#xff0c;努力学习 - python脚本学习 多数元素 解题思路 这道题是要找出数组中出现次数超过一半的元素。有几种不同的方法可以解决这个问题&#xff1a; 哈希表统计法&#xff1a;遍历数组&#xff0c;用哈希表统计每个元素的出现次数&#xff0c;…

关于读取CH584单片机的IO电平出现到的乌龙

本来是调用的库里的 uint8_t get_wake_up_sta (void) {return GPIOB_ReadPortPin(GPIO_Pin_10);//return cc_gpio_get_in_io (WAKUP_CH);} 然后读出来是0&#xff0c;我都配置上拉了。 搞不到原因。 最后是CH584单片机只有0和非零两种状态&#xff0c;读出来1024被转换成无…

Opencv常见学习链接(待分类补充)

文章目录 1.常见学习链接 1.常见学习链接 1.Opencv中文官方文档 2.Opencv C图像处理&#xff1a;矩阵Mat 随机数RNG 计算耗时 鼠标事件 3.Opencv C图像处理&#xff1a;亮度对比度饱和度高光暖色调阴影漫画效果白平衡浮雕羽化锐化颗粒感 4.OpenCV —— 频率域滤波&#xff…

anaconda、miniconda、conda的关系及miniconda安装

anaconda、miniconda、conda的关系及miniconda安装 文章目录 前言正文定义关系Linux安装miniconda新建一个python3.8环境 参考 前言 本文用于记录关于Anaconda、conda和Miniconda的定义及其关系的总结123&#xff1a; 正文 定义 conda 一个跨平台的开源包管理和环境管理工具…

2024-2025年AI领域重大事件深度解析:技术革命、产业重构与未来挑战

一、技术突破&#xff1a;从多模态到具身智能的跨越式演进 1. 生成式AI的“核爆级”升级 多模态融合&#xff1a;OpenAI的GPT-4o实现文本、图像、语音的实时交互&#xff0c;GPQA基准测试得分达87.7%&#xff0c;在科学推理和编程任务中表现卓越1。谷歌的Gemini 2.0 Flash支持…

城市地下“隐形卫士”:激光甲烷传感器如何保障燃气安全?

城市“生命线”面临的安全挑战 城市地下管网如同人体的“血管”和“神经”&#xff0c;承载着燃气、供水、电力、通信等重要功能&#xff0c;一旦发生泄漏或爆炸&#xff0c;将严重影响城市运行和居民安全。然而&#xff0c;由于管线老化、违规施工、监管困难等问题&#xff0…

融云 uni-app IMKit 上线,1 天集成,多端畅行

融云 uni-app IMKit 正式上线&#xff0c;支持一套代码同时运行在 iOS、Android、H5、小程序主流四端&#xff0c;集成仅需 1 天&#xff0c;并可确保多平台的一致性体验。 融云 uni-app IMKit 在 Vue 3 的高性能加持下开发实现&#xff0c;使用 Vue 3 Composition API&#x…

《Claude:人工智能界的璀璨新星》

一、Claude 登场&#xff1a;AI 新时代的震撼开篇 在科技飞速发展的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经成为推动社会进步和创新的核心力量。从智能语音助手到自动驾驶汽车&#xff0c;从图像识别技术到自然语言处理&#xff0c;AI 正以惊人的速度渗透到我…

Python中tqdm进度条工具和enumerate函数的使用详解

tqdm进度条工具 tqdm 是 Python 中一个非常流行的 进度条显示工具库&#xff0c;常用于迭代操作的可视化&#xff0c;比如训练神经网络、批量数据处理等任务。 一、tqdm 是什么&#xff1f; tqdm 全称是 taqaddum&#xff08;阿拉伯语&#xff0c;意为“进展”&#xff09;&a…

yum命令常用选项

刷新仓库列表 sudo yum repolist清理 Yum 缓存并生成新的缓存 sudo yum clean all sudo yum makecache验证 EPEL 源是否已正确启用 sudo yum repolist enabled安装软件包 sudo yum install <package-name> -y更新软件包 sudo yum update -y仅更新指定的软件包。 su…

linux debug技术

Linux是当今应用最广泛的免费和开源操作系统&#xff0c;它是一个复杂的分布式操作系统。它的内核的强大和灵活性已成为引用它的原因之一。在掌握Linux内核的过程中&#xff0c;调试工具可以帮助开发人员获得更深入的反思和理解。下面有25种不可或缺的Linux内核调试工具&#x…

【LinkedList demo 内部类讲说】

LinkedList demo 内部类讲说 1. Node节点2.MyLinkedList3. LinkedListTest 测试类 1. Node节点 public class Node<T> {private Node<T> pre;private Node<T> next;private T data;public Node() {}public Node getPre() {return pre;}public void setPre(N…