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

Redis后台任务有哪些

Redis后台任务

为了有更好的性能表现,redis对于一些比较耗时的操作会异步执行,不阻塞线上请求。文章从源码(redis7.0)来看,aof、rdb文件的关闭,aof文件的刷盘以及部分内存释放会采用异步方式,在后台线程中执行。接下来我们看下这些具体的任务以及后台任务的具体实现。

Redis后台任务类型

在源码中的bio.h bio.c文件是redis后台线程任务的实现逻辑,包含以下三类任务:

/* Background job opcodes */
#define BIO_CLOSE_FILE    0 /* Deferred close(2) syscall. */
#define BIO_AOF_FSYNC     1 /* Deferred AOF fsync. */
#define BIO_LAZY_FREE     2 /* Deferred objects freeing. */
#define BIO_NUM_OPS       3
  1. 关闭文件,包括socket、数据文件的关闭。redis中主要是aof和rdb文件的close。
    异步close
  2. 刷盘,内容由内存到磁盘的过程,通常是异步写的,首先会写入page cahe,刷盘就是将修改的数据从page cache同步到磁盘。
    异步fsync
  3. 释放内存。
    异步释放

实现思路

异步任务实现逻辑
三类异步任务对应三个任务队列,分别不同的函数进行任务提交,任务队列是一个list,每个list对应一个消费线程。

  • void bioCreateCloseJob(int fd, int need_fsync); 提交异步关闭任务
  • void bioCreateFsyncJob(int fd); 提交异步刷盘任务
  • void bioCreateLazyFreeJob(lazy_free_fn free_fn, int arg_count, ...); 提交异步释放任务

源码分析

初始化

在启动初始化完成后,main函数会调用InitServerLast做一些系统准备完毕后的其他初始化工作,其中就包括后台线程任务初始化初void bioInit(void);

  • 初始化每个线程用到的互斥锁、信号量、消费队列(bio_jobs)和队列长度(bio_pending)
  • 计算线程栈大小
  • 初始化每个线程,线程句柄函数bioProcessBackgroundJobs,每个线程会先进行设置名称(redis_set_thread_title)、绑核(redisSetCpuAffinity)、设置信号(pthread_sigmask),然后进入while(1)循环执行。
/* Initialize the background system, spawning the thread. */
void bioInit(void) {pthread_attr_t attr;pthread_t thread;size_t stacksize;int j;/* Initialization of state vars and objects */for (j = 0; j < BIO_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;}/* Set the stack size as by default it may be small in some system */pthread_attr_init(&attr);pthread_attr_getstacksize(&attr,&stacksize);if (!stacksize) stacksize = 1; /* The world is full of Solaris Fixes */while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2;pthread_attr_setstacksize(&attr, stacksize);/* Ready to spawn our threads. We use the single argument the thread* function accepts in order to pass the job ID the thread is* responsible of. */for (j = 0; j < BIO_NUM_OPS; j++) {void *arg = (void*)(unsigned long) j;if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,arg) != 0) {serverLog(LL_WARNING,"Fatal: Can't initialize Background Jobs.");exit(1);}bio_threads[j] = thread;}
}

线程任务

每个线程的执行的函数都是同一个,在这个函数中根据不同的函数入参进行区别。

  • 首先是等待该线程对应的队列非空
  • 非空时从任务队列中取出头节点任务 ln->value
  • 根据不同的type类型分别执行刷盘、关闭文件、异步释放等操作
  • 执行完毕后删除节点。这里有个细节是广播bio_step_cond,是为了释放查询待执行任务数时加的锁(查询进来时,刚好有任务在执行,此时等待这个任务执行完毕)。
    while(1) {listNode *ln;/* The loop always starts with the lock hold. */if (listLength(bio_jobs[type]) == 0) {pthread_cond_wait(&bio_newjob_cond[type],&bio_mutex[type]);continue;}/* Pop the job from the queue. */ln = listFirst(bio_jobs[type]);job = ln->value;/* It is now possible to unlock the background system as we know have* a stand alone job structure to process.*/pthread_mutex_unlock(&bio_mutex[type]);/* Process the job accordingly to its type. */if (type == BIO_CLOSE_FILE) {if (job->fd_args.need_fsync) {redis_fsync(job->fd_args.fd);}close(job->fd_args.fd);} else if (type == BIO_AOF_FSYNC) {/* The fd may be closed by main thread and reused for another* socket, pipe, or file. We just ignore these errno because* aof fsync did not really fail. */if (redis_fsync(job->fd_args.fd) == -1 &&errno != EBADF && errno != EINVAL){int last_status;atomicGet(server.aof_bio_fsync_status,last_status);atomicSet(server.aof_bio_fsync_status,C_ERR);atomicSet(server.aof_bio_fsync_errno,errno);if (last_status == C_OK) {serverLog(LL_WARNING,"Fail to fsync the AOF file: %s",strerror(errno));}} else {atomicSet(server.aof_bio_fsync_status,C_OK);}} else if (type == BIO_LAZY_FREE) {job->free_args.free_fn(job->free_args.free_args);} else {serverPanic("Wrong job type in bioProcessBackgroundJobs().");}zfree(job);/* Lock again before reiterating the loop, if there are no longer* jobs to process we'll block again in pthread_cond_wait(). */pthread_mutex_lock(&bio_mutex[type]);listDelNode(bio_jobs[type],ln);bio_pending[type]--;/* Unblock threads blocked on bioWaitStepOfType() if any. */pthread_cond_broadcast(&bio_step_cond[type]);}

提交任务

任务提交比较简单,通过上述三个Create接口实例化一个bio_job 然后追加到对应的list尾部。
bio_job使用了union,对于close和刷盘来说使用fd_args, 对于异步释放来说使用free_args。

typedef union bio_job {/* Job specific arguments.*/struct {int fd; /* Fd for file based background jobs */unsigned need_fsync:1; /* A flag to indicate that a fsync is required before* the file is closed. */} fd_args;struct {lazy_free_fn *free_fn; /* Function that will free the provided arguments */void *free_args[]; /* List of arguments to be passed to the free function */} free_args;
} bio_job;

总结

redis 针对大文件关闭、大内存释放、刷盘这些操作,分别使用对应的后台线程防止其阻塞线上请求,保证线上请求的高性能。其实现方式比较清晰,每种后台任务对应一个链表实现的消费队列和一个后台线程作为消费者,前台请求只需要通过提交函数向队列中追加待执行任务即可。实现清晰、简洁,也有一些细节,例如后台线程要屏蔽 watchdog, 这里不再深究。

相关文章:

Redis后台任务有哪些

Redis后台任务 为了有更好的性能表现&#xff0c;redis对于一些比较耗时的操作会异步执行&#xff0c;不阻塞线上请求。文章从源码(redis7.0)来看&#xff0c;aof、rdb文件的关闭&#xff0c;aof文件的刷盘以及部分内存释放会采用异步方式&#xff0c;在后台线程中执行。接下来…...

TPair<TKey, TValue> 键值对

在 Delphi&#xff08;或更准确地说是 Object Pascal&#xff0c;Delphi 的编程语言&#xff09;中&#xff0c;TList<T> 是泛型列表的一个实现&#xff0c;其中 T 是列表中元素的类型。TPair<TKey, TValue> 是一个包含两个元素的记录&#xff08;record&#xff0…...

【杂谈】城市规划教育的危与机

城市规划教育的危与机 &#xff08;赵燕菁 原文为作者在 第21届中国城市规划学科发展论坛上的发言&#xff0c;有删减和改动&#xff09;如有侵权&#xff0c;立即删除 过去几年&#xff0c;尤其是从2022年后房地产市场的下行开始&#xff0c;中国的城市规划陷入前所未有的危…...

金融工程--pine-script 入门

背景 脚本基本组成 指标 常见的趋势类指标&#xff1a;均线类(MAs)、支撑/压力位(Support/Resistance)、趋势线(Trend Lines)、趋势通道(Trend Channels)、一目均衡表(Ichimoku)和 艾略特波浪(ElliotWave)。 均线指标 策略 策略种类 在TradingView上&#xff0c;有许多交易…...

Vue3 跨标签页或跨窗口通信

在 Vue 应用中&#xff0c;跨标签页或跨窗口的通信通常涉及到两个或多个浏览器标签页之间的信息共享。由于每个标签页或窗口都是独立的 JavaScript 执行环境&#xff0c;它们不能直接通过 Vue 或其他 JavaScript 库来直接相互通信。但是&#xff0c;有一些方法可以实现这种跨标…...

Ollama: 使用Langchain的OllamaFunctions

1. 引言 Function call Langchain的Ollama 的实验性包装器OllamaFunctions&#xff0c;提供与 OpenAI Functions 相同的 API。因为网络的原因&#xff0c;OpenAI Functions不一定能访问&#xff0c;但如果能通过Ollama部署的本地模型实现相关的函数调用&#xff0c;还是有很好…...

java质数的判断 C语言指针变量的使用

1. public static void main(String[] args) {Scanner scnew Scanner(System.in);System.out.println("请输入一个值");int num sc.nextInt();boolean flagtrue;for (int i2;i<num;i){if (num%i0){flagfalse;break;}}if (flag){System.out.println(num"是一…...

TensorFlow面试整理-TensorFlow 数据处理

在 TensorFlow 中,数据处理是构建和训练深度学习模型的重要环节。高效地管理、预处理和增强数据可以显著提高模型的训练效率和性能。TensorFlow 提供了强大的 tf.data API 来帮助处理各种数据集。下面是 TensorFlow 数据处理的详细介绍: 1. tf.data.Dataset API tf.data API …...

vue路由的基本使用

vue路由的基本使用 vue-router简介一、路由配置和使用1、安装2、创建路由实例2、在组件中引用路由 router-view ,如APP根组件中直接引用&#xff1a;3、最后还需要把路由挂载到APP实例中&#xff0c;在main.js中注册路由&#xff1a; 二、路由重定向与别名三、声明式导航1、传统…...

数据结构分类

数据结构(data structure)是计算机存储、组织数据的方式&#xff0c;是带有结构特性的数据元素的集合。是相互之间存在一种或多种特定关系的数据元素的集合&#xff0c;即带“结构”的数据元素的集合。这种“结构”指的是数据元素之间存在的关系&#xff0c;分为逻辑结构和存储…...

【STM32】 TCP/IP通信协议--LwIP介绍

LwIP&#xff08;Lightweight IP&#xff09;是一个轻量级的TCP/IP协议栈&#xff0c;专为嵌入式系统设计&#xff0c;以较小的资源消耗实现完整的网络功能。本文将详细介绍LwIP的基本概念、特点、与TCP/IP的区别以及如何在STM32上使用LwIP实现TCP/IP通信。 1. LwIP的定义和设…...

一些面试题整理

第一章、基础 以下是对上述10道面试题的参考答案&#xff1a; 一、Java语言及性能调优 答案&#xff1a; 线程安全问题是指多个线程同时访问共享资源时可能出现的数据不一致或错误的情况。例如&#xff0c;多个线程同时对一个共享变量进行写操作&#xff0c;如果没有适当的同…...

端口号和ip地址一样吗?区别是什么

在网络通信的世界里&#xff0c;端口号和IP地址是两个不可或缺的概念&#xff0c;它们各自扮演着独特的角色&#xff0c;共同维系着数据在网络中的有序传输。然而&#xff0c;对于许多初学者而言&#xff0c;这两者往往容易被混淆&#xff0c;认为它们是同一事物的不同表述。那…...

深入探讨全流量回溯分析与网络性能监控系统

AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具 随着数据量的急剧增加&#xff0c;传统的网络监控手段面临诸多挑战。在此背景下&#xff0c;全流量回溯分析和网络性能监控系统成为了保障网络正常运作的重要工具。本文将围绕这两个关键词&#xff0c;探讨它…...

python机器人编程——一种3D骨架动画逆解算法的启示(上)

目录 一、前言二、fabrik 算法三、python实现结论PS.扩展阅读ps1.六自由度机器人相关文章资源ps2.四轴机器相关文章资源ps3.移动小车相关文章资源ps3.wifi小车控制相关文章资源 一、前言 我们用blender等3D动画软件时&#xff0c;会用到骨骼的动画&#xff0c;通过逆向IK动力学…...

Flutter开发者必备面试问题与答案02

Flutter开发者必备面试问题与答案02 视频 https://youtu.be/XYSxTb0iA9I https://www.bilibili.com/video/BV1Zk2dYyEBr/ 前言 原文 Flutter 完整面试问题及答案02 本文是 flutter 面试问题的第二讲&#xff0c;高频问答 10 题。 正文 11. PageRoute 是什么&#xff1f; …...

拥抱真实:深度思考之路,行动力的源泉

在纷繁复杂的现代社会&#xff0c;人们往往被表象迷惑&#xff0c;忙碌于各种事务之中&#xff0c;却很少停下来进行深度思考。这种忙碌往往是表面的、无效的&#xff0c;因为它缺乏对自我和目标的深刻理解与追求。提升行动力&#xff0c;避免假勤奋&#xff0c;关键在于深度思…...

【Python爬虫实战】深入理解Python异步编程:从协程基础到高效爬虫实现

#1024程序员节&#xff5c;征文# &#x1f308;个人主页&#xff1a;易辰君-CSDN博客 &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html ​ 目录 前言 一、异步 &#xff08;一&#xff09;核心概念 &#xff08;二&#xff09;…...

OpenCV图像处理方法:腐蚀操作

腐蚀操作 前提 图像数据为二值的&#xff08;黑/白&#xff09; 作用 去掉图片中字上的毛刺 显示图片 读取一个图像文件&#xff0c;并在一个窗口中显示它。用户可以查看这个图像&#xff0c;直到按下任意键&#xff0c;然后程序会关闭显示图像的窗口 # cv2是OpenCV库的P…...

PG数据库之流复制详解

一、流复制的定义 PostgreSQL流复制&#xff08;Streaming Replication&#xff09;是一种数据复制技术&#xff0c;它允许实时传输数据更改&#xff0c;从而在主服务器和一个或多个备用服务器之间保持数据同步。流复制是PostgreSQL数据库管理系统&#xff08;DBMS&#xff09…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...