Redis多线程原理详解

从上图中可以看出只有以下3个地方用的是多线程,其他地方都是单线程:

1:接收请求参数

2:解析请求参数

3:请求响应,即将结果返回给client

很明显以上3点各个请求都是互相独立互不影响的,很适合用多线程,特别是请求体/响应体很大的时候,更能体现多线程的威力。而操作数据库是请求之间共享的,如果使用多线程的话适合读写锁。而操作数据库本身是很快的(就是对map的增删改查),单线程不一定就比多线程慢,当然也有可能是作者偷懒,懒得实现罢了,但这次的多线程模型还是值得我们学习一下的。

2:redis多线程是怎么实现的?

先大致说一下多线程的流程:

2:服务器收到的每个请求都会放入全局读队列clients_pending_read,同时将队列中的元素分发到每个线程对应的队列io_threads_list中,这些工作都是在主线程中执行的。

3:每个线程(包括主线程和子线程)接收请求参数并做解析,完事后在client中设置一个标记CLIENT_PENDING_READ,标识参数解析完成,可以操作数据库了。(主线程和子线程都会执行这个步骤)

4:主线程遍历队列clients_pending_read,发现设有CLIENT_PENDING_READ标记的,就操作数据库

5:操作完数据库就是响应client了,响应是一组函数addReplyXXX,在client中设置标记CLIENT_PENDING_WRITE,同时将client加入全局写队列clients_pending_write

6:主线程将全局队列clients_pending_write以轮训的方式将任务分发到每个线程对应的队列io_threads_list

7:所有线程将遍历自己的队列io_threads_list,将结果发送给client

3:redis多线程是怎么做到无锁的?

上面说了多线程的地方都是互相独立互不影响的。但是每个线程的队列就存在两个两个线程访问的情况:主线程向队列中写数据,子线程消费,redis的实现有点反直觉。按正常思路来说,主线程在往队列中写数据的时候加锁;子线程复制队列&并将队列清空,这个两个动作是加锁的,子线程消费复制后的队列,这个过程是不需要加锁的,按理来说主线程和子线程的加锁动作都是非常快的。但是redis并没有这么实现,那么他是怎么实现的呢?

redis多线程的模型是主线程负责搜集任务,放入全局读队列clients_pending_read和全局写队列clients_pending_write,主线程在将队列中的任务以轮训的方式分发到每个线程对应的队列(list *io_threads_list[128])

1:一开始子线程的队列都是空,主线程将全对队列中的任务分发到每个线程的队列,并设置一个队列有数据的标记(_Atomic unsigned long io_threads_pending[128]),io_threads_pending[1]=5表示第一个线程的队列中有5个元素

2:子线程死循环轮训检查io_threads_pending[index] > 0,有数据就开始处理,处理完成之后将io_threads_pending[index] = 0,没数据继续检查

3:主线程将任务分发到子线程的队列中,自己处理自己队列中的任务,处理完成后,等待所有子线程处理完所有任务,继续收集任务到全局队列,在将任务分发给子线程,这样就避免了主线程和子线程同时访问队列的情况,主线程向队列写的时候子线程还没开始消费,子线程在消费的时候主线程在等待子线程消费完,子线程消费完后主线程才会往队列中继续写,就不用加锁了。因为任务是平均分配到每个队列的,所以每个队列的处理时间是接近的,等待的时间会很短。

4:源码执行流程

为了方便你看源码,这里加上一些代码的执行流程

启动socket监听,注册连接处理函数,连接成功后创建连接对象connection,创建client对象,通过aeCreateFileEvent注册client的读事件

Original: https://www.cnblogs.com/hlxs/p/14037919.html
Author: 啊汉
Title: Redis多线程原理详解

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/529416/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Java语言高级(第六部分)函数式接口 Stream流、方法引用 ->(个人学习记录笔记)

    第一章 函数式接口 1.1 概念 函数式接口在Java中是指: 有且仅有一个抽象方法的接口。 函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda…

    Linux 2023年6月8日
    089
  • 【计算题】考研数据结构计算题型整理

    题型1:递归程序,一般使用公式进行递推 int fact(int n){ if(n 本题是求阶乘的递归代码,即n * (n-1) * …. * 1。每次递归调用 fac…

    Linux 2023年6月13日
    0114
  • 世界上最流行的操作系统不是Windows?

    前言 打住,我知道列位是被标题骗进来的,但是这个论题并不是我瞎吹牛,世界上最流行的操作系统还真不是Windows。 提及操作系统,我们印象中比较深刻的无非就是Windows,Lin…

    Linux 2023年6月13日
    0119
  • LeetCode-459. 重复的子字符串

    题目来源 题目详情 给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。 示例 1: 输入: s = “abab”输出: true解释:…

    Linux 2023年6月7日
    0126
  • Mysql数据库语言学习的路线

    对于我们数据库的学习,不管是测试人员还是开发人员以及我们的DBA来说重点都是SQL;但是我们的SQL可以分多少类型,学习重点又是在哪里呢,本文仅仅针对测试人员来展开说明: SQL:…

    Linux 2023年6月14日
    090
  • linux系统编码修改

    查看当前系统默认采用的字符集locale 查看系统当前编码echo $LANG如果输出为:en_US.UTF-8 英文zh_CN.UTF-8 中文 查看系统是否安装中文字符集loc…

    Linux 2023年6月6日
    0102
  • 高等代数:5 矩阵的相抵与相似

    5 矩阵的相抵与相似 1、设S,M是两个集合,则集合 ({(a,b)|a \in S,b \in W}) 称为S与M的 笛卡儿积,记作:(S \times M)。 2、定义1:设S…

    Linux 2023年6月8日
    0123
  • 【Example】C++ 标准库多线程同步及数据共享 (std::future 与 std::promise)

    否则你会像听天书一样懵。(…) ==================================== 在任何语言的多线程编程当中,必然涉及线程的同步及数据的共享,方…

    Linux 2023年6月13日
    0119
  • CentOS7安装MYSQL8.X详细教程

    1-首先查看系统是否存在mysql,无则不返回 rpm -qa|grep mysql 2-安装wget yum -y install wget 3-抓取mariadb并删除包,无则…

    Linux 2023年5月27日
    092
  • 【深度学习】ml_collections报错

    在一些源码中,看见了一个导入: import ml_collections 此时会报错,这个包并不是PyTorch的包,同时也非源码中模块 解决办法: pip install ml…

    Linux 2023年6月13日
    086
  • Redis 内存淘汰策略

    实际上redis定义了【八种内存淘汰策略】来处理redis内存满的情况 noeviction:直接返回错误,不淘汰任何已经存在的redis键 allkeys-lru:所有的键使用l…

    Linux 2023年5月28日
    0106
  • PyTorch 介绍 | TENSORS

    Tensor是一种特殊的数据结构,非常类似于数组和矩阵。在PyTorch中,我们使用tensor编码模型的输入和输出,以及模型的参数。 Tensor类似于Numpy的ndarray…

    Linux 2023年6月16日
    0170
  • npm 和 maven 使用 Nexus3 私服 | 前后端一起学

    前文《Docker 搭建 Nexus3 私服 》介绍了在 docker 环境下安装 nexus3 以及 nexus3 的基本操作和管理,本文分别介绍 npm(前端)和 maven(…

    Linux 2023年6月7日
    074
  • 在Ubuntu机器上使用war包安装Jenkins

    因为一些需求需要迁移之前使用的Jenkins,原来是按照官方文档使用apt方式安装的,这次搬迁后的机器由于默认不通外网(可以通过代理走外网),因此趁此机会,尝试改用war包方式安装…

    Linux 2023年6月6日
    0118
  • Linux lsof命令的使用示例

    Linux命令中,lsof代表 Li St Open Files,用于查看所有被打开的文件,同时显示打开文件相对应的进程。Linux/Unix把一切都看做文件(pipes,sock…

    Linux 2023年6月13日
    091
  • ip、ifconfig 和 route命令介绍与网络配置

    linux的ip命令和ifconfig类似,但前者功能更强大,并旨在取代后者。使用ip命令,只需一个命令,你就能很轻松地执行一些网络管理任务。ifconfig是net-tools中…

    Linux 2023年6月6日
    097
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球