当前位置: 首页 > article >正文

Redis 单线程真的是单线程吗?源码角度全面解析

Redis 是单线程的——这句话流传太广了以至于很多人真的以为 Redis 就一个线程在跑。但实际上如果你ps -ef或者top看一眼正在运行的 Redis 进程会发现线程数不止一个。到底怎么回事这篇文章从源码角度把这个问题彻底说清楚。先说结论Redis 的单线程指的是命令处理的主逻辑是单线程的。但 Redis 进程里实际上有主线程处理网络请求、执行命令、事件循环3 个后台线程异步处理关闭文件、AOF fsync、惰性释放子进程RDB 持久化、AOF 重写时 fork 出来的所以 Redis 不是严格意义上的单线程而是命令处理单线程。这个设计非常聪明后面会解释为什么。后台线程bio.c打开bio.c文件开头的注释写得很清楚This file implements operations that we need to perform in the background. Currently there is a single operation, that is a background close(2) system call.说currently a single operation是早期版本现在已经扩展了。看bio.h的定义#defineBIO_CLOSE_FILE0// 异步关闭文件#defineBIO_AOF_FSYNC1// 异步 AOF fsync#defineBIO_LAZY_FREE2// 异步释放内存#defineBIO_NUM_OPS3// 共 3 种后台任务Redis 启动时会创建 3 个后台线程voidbioInit(void){// 初始化锁、条件变量、任务队列for(j0;jBIO_NUM_OPS;j){pthread_mutex_init(bio_mutex[j],NULL);pthread_cond_init(bio_newjob_cond[j],NULL);pthread_cond_init(bio_step_cond[j],NULL);bio_jobs[j]listCreate();bio_pending[j]0;}// 创建 3 个线程for(j0;jBIO_NUM_OPS;j){if(pthread_create(thread,attr,bioProcessBackgroundJobs,arg)!0){serverLog(LL_WARNING,Fatal: Cant initialize Background Jobs.);exit(1);}bio_threads[j]thread;}}每个线程负责一种任务类型有自己的任务队列。主线程通过bioCreateBackgroundJob提交任务voidbioCreateBackgroundJob(inttype,void*arg1,void*arg2,void*arg3){structbio_job*jobzmalloc(sizeof(*job));job-timetime(NULL);job-arg1arg1;job-arg2arg2;job-arg3arg3;pthread_mutex_lock(bio_mutex[type]);listAddNodeTail(bio_jobs[type],job);bio_pending[type];pthread_cond_signal(bio_newjob_cond[type]);// 唤醒对应线程pthread_mutex_unlock(bio_mutex[type]);}后台线程的工作循环void*bioProcessBackgroundJobs(void*arg){unsignedlongtype(unsignedlong)arg;while(1){pthread_mutex_lock(bio_mutex[type]);// 没任务就等着if(listLength(bio_jobs[type])0){pthread_cond_wait(bio_newjob_cond[type],bio_mutex[type]);continue;}// 取任务listNode*lnlistFirst(bio_jobs[type]);jobln-value;pthread_mutex_unlock(bio_mutex[type]);// 执行任务if(typeBIO_CLOSE_FILE){close((long)job-arg1);}elseif(typeBIO_AOF_FSYNC){redis_fsync((long)job-arg1);}elseif(typeBIO_LAZY_FREE){if(job-arg1)lazyfreeFreeObjectFromBioThread(job-arg1);elseif(job-arg2job-arg3)lazyfreeFreeDatabaseFromBioThread(job-arg2,job-arg3);}pthread_mutex_lock(bio_mutex[type]);listDelNode(bio_jobs[type],ln);bio_pending[type]--;pthread_mutex_unlock(bio_mutex[type]);}}典型的生产者-消费者模型。为什么需要这些后台线程BIO_CLOSE_FILEclose()系统调用在某些情况下会阻塞。比如关闭一个大文件或者 NFS 文件系统。主线程阻塞会导致所有客户端都卡住所以放到后台线程做。BIO_AOF_FSYNCAOF 持久化需要定期fsync。这是个磁盘 IO 操作可能很慢。appendfsync everysec配置就是每秒做一次 fsync交给后台线程处理。BIO_LAZY_FREEUNLINK、FLUSHDB ASYNC、FLUSHALL ASYNC这些命令用到的。删除大 key比如包含几百万元素的 hash会阻塞主线程所以放到后台线程慢慢删。这是 Redis 4.0 引入的特性。子进程持久化RDB 快照和 AOF 重写会fork()子进程// rdb.cif((childpidfork())0){/* Child process */closeListeningSockets(0);redisSetProcTitle(redis-rdb-bgsave);// 执行持久化...exitFromChild(0);}// aof.cif((childpidfork())0){/* Child process */closeListeningSockets(0);redisSetProcTitle(redis-aof-rewrite);// 执行 AOF 重写...exitFromChild(0);}为什么用fork()而不是线程因为 fork 出来的子进程有父进程内存的完整副本写时复制可以安全地遍历所有数据做持久化不用担心主线程同时修改。如果是多线程就要加各种锁复杂度飙升。但 fork 有代价父进程内存越大fork 越慢。所以 Redis 官方建议单实例内存不要太大。主线程为什么是单线程的回到核心问题处理命令的主逻辑为什么用单线程几个原因1. 没锁的代价多线程意味着共享数据要加锁。Redis 数据结构复杂加锁会带来锁竞争开销死锁风险代码复杂度上升单线程完全避免这些问题。2. 瓶颈不在 CPURedis 大部分操作是内存操作速度极快。瓶颈通常在网络带宽客户端连接数大 key 操作多线程不一定能提升性能反而增加复杂度。3. 事件循环模型Redis 用 epoll/kqueue 做多路复用一个线程就能处理成千上万的并发连接。这种 IO 模型本身就是单线程友好的Nginx 也是类似设计。那些慢操作怎么办单线程最大的问题是一个操作慢了后面所有请求都得等。Redis 的应对策略1. 把操作拆细比如KEYS *会遍历所有 key很慢。Redis 后来加了SCAN每次只遍历一小部分用游标续传。2. 扔给后台线程惰性删除lazy free就是这个思路。UNLINK命令异步删除大 keyvoidunlinkCommand(client*c){if(server.lazyfree_lazy_server_del){// 异步删除bioCreateBackgroundJob(BIO_LAZY_FREE,NULL,NULL,key);}else{// 同步删除旧版本行为dbDelete(c-db,key);}}3. 用子进程持久化交给 fork 出来的子进程。4. 直接禁止KEYS命令在生产环境不建议用DEBUG SLEEP也是调试用的。那 Redis 6.0 的多线程 IO 是什么Redis 6.0 引入了多线程来处理网络 IO读写 socket但命令执行还是单线程。这个特性的代码在networking.c里主要解决的是网络带宽瓶颈问题。当客户端数据量很大时读写 socket 成了瓶颈可以用多个线程并行处理。但核心的数据结构操作、命令执行依然是单线程。总结线程/进程职责主线程事件循环、命令执行bio 线程 1异步关闭文件bio 线程 2异步 AOF fsyncbio 线程 3异步惰性释放子进程RDB 持久化、AOF 重写Redis 的单线程是指命令处理的主流程。但像文件关闭、fsync、大 key 删除这些可能阻塞的操作都用后台线程或子进程处理了。这是一个务实的设计选择。单线程简单、无锁、容易维护配合异步 IO 和后台任务足以应付绝大多数场景。如果真的需要更高性能正确的做法不是改 Redis 代码而是部署多个实例用集群分担压力。毕竟 Redis 本身就支持集群模式。

相关文章:

Redis 单线程真的是单线程吗?源码角度全面解析

Redis 是单线程的——这句话流传太广了,以至于很多人真的以为 Redis 就一个线程在跑。但实际上,如果你 ps -ef 或者 top 看一眼正在运行的 Redis 进程,会发现线程数不止一个。 到底怎么回事?这篇文章从源码角度把这个问题彻底说清…...

Kodi中文插件库终极指南:3分钟打造你的智能家庭影院

Kodi中文插件库终极指南:3分钟打造你的智能家庭影院 【免费下载链接】xbmc-addons-chinese Addon scripts, plugins, and skins for XBMC Media Center. Special for chinese laguage. 项目地址: https://gitcode.com/gh_mirrors/xb/xbmc-addons-chinese 还在…...

对 OS:TEP 的 MLFQ 策略的一点思考

1.SJF 调度算法SJF 没啥好说的, 书上讲的很清楚了, SJF 就是最短任务优先原则, 其设计初衷是想解决 FIFO 的糟糕的周转时间的问题.但是, 正如书上所说, 这玩意主打一个秩序井然, 只能处理所有任务同时到队列的情况, 要是某堆进程不按这套路出牌, 那 SJF 立马完蛋, 书上就有一个…...

终极Windows 11优化指南:Win11Debloat让你的系统重获新生

终极Windows 11优化指南:Win11Debloat让你的系统重获新生 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter and…...

cv_resnet101_face-detection_cvpr22papermogface保姆级教程:GPU显存占用监控与自动释放策略

cv_resnet101_face-detection_cvpr22papermogface保姆级教程:GPU显存占用监控与自动释放策略 1. 引言 如果你正在使用基于ResNet101的MogFace人脸检测模型,可能会遇到一个常见问题:GPU显存占用越来越高,最终导致程序崩溃。尤其是…...

LumiPixel Canvas Quest集成Vue.js:打造动态人像画廊管理后台

LumiPixel Canvas Quest集成Vue.js:打造动态人像画廊管理后台 1. 项目背景与需求分析 在数字内容创作领域,AI生成人像正成为设计师和内容创作者的重要工具。传统人工绘制方式耗时费力,而直接使用AI生成工具又缺乏系统化管理。我们团队最近用…...

Kandinsky-5.0-I2V-Lite-5s企业实操:单任务串行设计规避显存过载,保障服务稳定性

Kandinsky-5.0-I2V-Lite-5s企业实操:单任务串行设计规避显存过载,保障服务稳定性 1. 产品概述 Kandinsky-5.0-I2V-Lite-5s是一款轻量级图生视频模型,专为企业级稳定运行而优化。只需上传一张首帧图片,再补充运动或镜头描述&…...

Qwen3-14B私有部署镜像Visio流程图智能生成:从文本描述到架构图

Qwen3-14B私有部署镜像Visio流程图智能生成:从文本描述到架构图 1. 引言:技术文档绘图的痛点与解决方案 技术文档编写过程中,最耗时费力的环节之一就是绘制系统架构图和流程图。传统方式需要手动在Visio中拖拽图形、调整布局、添加连接线&a…...

UE5材质编辑器进阶:手把手教你创建并调用自定义ush函数库(附避坑指南)

UE5材质编辑器进阶:打造高效可复用的自定义ush函数库 在虚幻引擎5的材质创作中,重复编写相同的HLSL代码不仅效率低下,还容易引入错误。本文将带你深入理解如何创建并调用自定义ush函数库,提升材质开发的专业性和可维护性。 1. 为什…...

Flutter鸿蒙开发环境:从零到一,手把手解决环境配置与编译难题

1. 环境准备:搭建Flutter鸿蒙开发的基石 第一次接触Flutter鸿蒙开发时,环境配置就像盖房子的地基,看似简单却最容易踩坑。我在Windows系统上反复折腾了三天才搞定所有环境,这里把血泪经验总结成保姆级教程。首先需要明确的是&…...

Inconsolata字体高效使用实战指南:提升编程体验的专业字体方案

Inconsolata字体高效使用实战指南:提升编程体验的专业字体方案 【免费下载链接】Inconsolata Development repo of Inconsolata Fonts by Raph Levien 项目地址: https://gitcode.com/gh_mirrors/in/Inconsolata 作为开发者,我们每天与代码打交道…...

网络调试无从下手?Fiddler中文版让HTTP问题排查效率提升10倍的秘密

网络调试无从下手?Fiddler中文版让HTTP问题排查效率提升10倍的秘密 【免费下载链接】zh-fiddler Fiddler Web Debugger 中文版 项目地址: https://gitcode.com/gh_mirrors/zh/zh-fiddler 在当今复杂的网络环境中,开发者和测试工程师经常面临HTTP请…...

Hackintool:面向黑苹果爱好者的硬件配置诊断与优化工具

Hackintool:面向黑苹果爱好者的硬件配置诊断与优化工具 【免费下载链接】Hackintool The Swiss army knife of vanilla Hackintoshing 项目地址: https://gitcode.com/gh_mirrors/ha/Hackintool 黑苹果配置过程中,硬件兼容性问题常常成为用户最头…...

Janus-Pro-7B开发者案例:基于Gradio API构建私有AI内容中台

Janus-Pro-7B开发者案例:基于Gradio API构建私有AI内容中台 1. 项目概述 Janus-Pro-7B是DeepSeek发布的一款统一多模态理解与生成模型,它通过创新的架构设计解决了传统模型在理解与生成任务上的冲突问题。该模型支持图像问答、OCR识别、图表分析等理解…...

AI报告文档审核赋能人才培养:IACheck打造环境检测人机协同审核虚拟仿真新体系

在环境检测行业持续走向精细化与规范化的过程中,报告审核能力逐渐成为影响整体质量的重要因素。然而,与检测设备和分析技术不断升级相比,审核人员的培养却长期依赖经验积累与“师带徒”模式,这种方式虽然能够传递实践经验&#xf…...

告别创作瓶颈:像素剧本圣殿应用指南,打造你的专属剧本工作站

告别创作瓶颈:像素剧本圣殿应用指南,打造你的专属剧本工作站 1. 像素剧本圣殿简介 像素剧本圣殿是一款基于Qwen2.5-14B-Instruct深度微调的专业剧本创作工具。它将AI推理能力与8-Bit复古美学完美融合,为创作者提供沉浸式的剧本开发体验。 …...

知识获取受限?5款开源工具助你合法解锁付费内容

知识获取受限?5款开源工具助你合法解锁付费内容 【免费下载链接】bypass-paywalls-chrome-clean 项目地址: https://gitcode.com/GitHub_Trending/by/bypass-paywalls-chrome-clean 你是否曾在学术研究关键时刻被期刊付费墙阻挡?是否因新闻网站的…...

Jetson Nano实战:FFmpeg与Nginx的RTMP推流配置全解析

1. Jetson Nano与RTMP推流基础认知 第一次接触Jetson Nano做视频推流时,我对着这块信用卡大小的开发板研究了整整三天。这块搭载了128核NVIDIA Maxwell GPU的小家伙,其实是个隐藏的视频处理高手。RTMP协议就像快递公司的"当日达"服务&#xff…...

R Markdown网站生成器使用教程:如何快速搭建技术文档网站 [特殊字符]

R Markdown网站生成器使用教程:如何快速搭建技术文档网站 📊 【免费下载链接】rmarkdown Dynamic Documents for R 项目地址: https://gitcode.com/gh_mirrors/rm/rmarkdown R Markdown是一个强大的动态文档生成工具,能够将代码、输出…...

深圳小学数学期末试卷创新题型引热议,数学与文学跨界融合成焦点

1. 当数学题遇上古诗词:深圳试卷创新设计背后的教育逻辑 深圳某区五年级数学期末卷上的一道"跨界题"最近在家长群炸开了锅。题目要求学生分析函数单调性后,将其与《琵琶行》中琵琶女的情感变化对应起来。这种"数学古诗文"的混搭模式…...

AMD Ryzen系统管理单元深度调试:SMUDebugTool技术解析与实战指南

AMD Ryzen系统管理单元深度调试:SMUDebugTool技术解析与实战指南 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: …...

霜儿-汉服-造相Z-Turbo作品集:看看AI能生成多美的汉服少女图

霜儿-汉服-造相Z-Turbo作品集:看看AI能生成多美的汉服少女图 1. 惊艳开篇:AI汉服艺术的魅力 当传统汉服遇上现代AI技术,会碰撞出怎样的火花?霜儿-汉服-造相Z-Turbo给出了令人惊叹的答案。这个基于Xinference部署的文生图模型服务…...

PS插件加载失败?手把手教你用注册表修复PS2017-2022扩展未签署问题

PS插件加载失败?手把手教你用注册表修复PS2017-2022扩展未签署问题 当你在Photoshop中安装新插件时,突然弹出"扩展未经正确签署"的错误提示,这种挫败感我深有体会。作为一名长期与PS插件打交道的设计师,这个问题几乎成…...

SpringBoot项目实战:用Java海康SDK搞定摄像头录像与门禁人脸下发(附完整代码)

SpringBoot企业级实战:海康威视SDK深度集成与智能安防系统开发 1. 企业级安防系统架构设计 在智能园区和现代化办公环境中,视频监控与门禁管理的无缝集成已成为刚需。海康威视作为全球领先的安防解决方案提供商,其设备SDK的深度集成能够为Jav…...

Java外部函数接口不是“能用就行”——从内存泄漏、线程崩溃到ABI不兼容,这9类致命缺陷正在 silently 摧毁你的微服务

第一章:Java外部函数接口(JEP 454)核心原理与演进脉络Java外部函数接口(Foreign Function & Memory API,JEP 454)标志着Java平台原生互操作能力的根本性重构。它取代了长期受限且易出错的JNI&#xff0…...

Notepad--:国产跨平台文本编辑器的终极指南与快速上手

Notepad--:国产跨平台文本编辑器的终极指南与快速上手 【免费下载链接】notepad-- 一个支持windows/linux/mac的文本编辑器,目标是做中国人自己的编辑器,来自中国。 项目地址: https://gitcode.com/GitHub_Trending/no/notepad-- Note…...

自指宇宙学形式化验证套件 (Coq‑SRU v1.2.0)

自指宇宙学形式化验证套件 (Coq‑SRU v1.2.0)技术摘要 正式整编版 项目标识:Coq Formalization of Self‑Referential Universe (Coq‑SRU) 版本:v1.2.0(对齐《世毫九自指宇宙学》理论第三部分) 代码仓库:https://git…...

MDS vs PCA:哪种降维方法更适合你的数据?

MDS与PCA深度对比:从算法原理到实战选型指南 当面对高维数据时,降维技术就像一把打开数据奥秘的钥匙。在众多降维方法中,多维尺度变换(MDS)和主成分分析(PCA)是最常被比较的两种经典技术。它们都能将复杂的高维数据简化为更易理解的二维或三维…...

全能解析工具UniExtract2:多格式提取的效率革命

全能解析工具UniExtract2:多格式提取的效率革命 【免费下载链接】UniExtract2 Universal Extractor 2 is a tool to extract files from any type of archive or installer. 项目地址: https://gitcode.com/gh_mirrors/un/UniExtract2 在数字化信息处理领域&…...

还在用老掉牙的HashTab?2024年最新文件哈希校验工具横向评测(附下载)

2024年文件哈希校验工具终极指南:告别过时方案,拥抱高效验证 还在为文件完整性验证发愁?每次下载重要软件都要反复核对哈希值却找不到趁手工具?作为从业十年的信息安全顾问,我见证了哈希校验工具从简陋到专业的演变。今…...