Redis阻塞操作实现原理(转)

原文:https://www.jianshu.com/p/xsMzfn

作者:Haiger

最近一位朋友问到:既然Redis是单线程的工作模式,那像 _BLPOP_这样的阻塞操作又是然后实现的呢?

接下来分别从服务端和客户端来阐述这一逻辑的实现原理。

Redis Server:
redis实现了一套事件触发模型,主要处理两种事件:I/O事件(文件事件)和定时事件。而处理它们的就靠一个EventLoop线程。同时redis还提供了丰富的数据结构,今天我们要分析的主要是List数据结构中的阻塞命令。
先来看看BLPOP的源码(做了精简,只看主要的部分,详细的可以看文尾提供的参考链接):
t_list.c

Redis阻塞操作实现原理(转)

Redis阻塞操作实现原理(转)

上面代码表明:如果客户端发来一个blpop key命令,redis先找到对应的key的list,如果list不为空则pop一个数据返回给客户端;如果对应的list不存在或者里面没有数据,就将该key添加到一个blockling_keys的字典中,value就是想订阅该key的client链表。此时对应的client的为block状态,且i/o channel里面没有写入数据。

既然是list数据结构,当然有push数据的操作:
同样是 t_list.c

Redis阻塞操作实现原理(转)

Redis阻塞操作实现原理(转)

上面代码表明:如果客户端发来一个rpush key value命令,先从blocking_keys中查找是否存在对应的key,如果存在就往ready_keys这个链表中添加该key;同时将value插入到对应的list中,并响应客户端。

从上面的分析来看,主要是blocking_keys和ready_keys的作用,那何时才会处理它们呢? 我们知道redis全靠EventLoop来处理所以的I/O事件,我们来看看所以命令的处理入口:
redis.c

Redis阻塞操作实现原理(转)

Redis阻塞操作实现原理(转)

上面代码表明:每次处理完客户端命令后都会遍历ready_keys,并通过blocking_keys找到对应的client,依次将对应list的数据pop出来并响应对应的client;同时检查是否需要再次block。

这样一来整个流程就清晰了。redis就是通过blocking_keys和ready_keys两个数据结构来实现的阻塞操作。但整个阻塞并没有阻塞EventLoop本身,从而实现命令的快速响应。算是一个典型的空间换时间的设计思路。

接下来再看看客户端如何实现一个阻塞的I/O请求。
Client:
这里我们分两种I/O模型来阐述:阻塞I/O(BIO)和非阻塞I/O(NIO)。
BIO,以Jedis为例。
BinaryJedis.java

Redis阻塞操作实现原理(转)

可以看出一个blpop请求会向redis发起两次I/O请求,一次向redis发送BLPOP key命令,一次从对应的链接管道(channel)中读取数据。由于BIO的特性当channel中没有数据时会一直阻塞,直到有新数据为止。这样就实现了客户端的阻塞效果。

注意:

这里的链接是被独享的,不然会有数据干扰。

NIO的实现就稍微复杂一些,这里分两种情况(以netty为例):
不带RquestID的实现方式
伪代码如下:

Redis阻塞操作实现原理(转)

由于NIO的特性read和write是两个I/O事件,要分别等待selector来触发,所以不能像BIO那样连续发起两次I/O操作。再加上没有requesID,当read到数据时无法找到之前对应的发起者,所以这里的链接也必须是独享的,同时由一个只能包含一个元素的阻塞队列LinkedBlockingQueue来实现阻塞的效果。

带RequestID的实现方式
伪代码如下:

Redis阻塞操作实现原理(转)

这里因为reqeust和response数据结构里都有带上了requestId,并且在链接对象上缓存了requestId和响应future的对应关系,因此链接可以不用独享。

到处,整个阻塞的实现原理分析完毕。

参考链接:
带注解的redis源码:
https://github.com/huangz1990/annotated_redis_source/blob/unstable/src/t_list.c https://github.com/huangz1990/annotated_redis_source/blob/unstable/src/redis.c
IO – 同步,异步,阻塞,非阻塞 (亡羊补牢篇)
http://blog.csdn.net/historyasamirror/article/details/5778378

Original: https://www.cnblogs.com/ajianbeyourself/p/15650518.html
Author: 奋斗终生
Title: Redis阻塞操作实现原理(转)

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

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

(0)

大家都在看

  • 在linux里部署OA项目环境

    1.首先要实现linux可以从windows系统里把文件拖到linux里 ①挂载光盘 [root@localhost ~]# mkdir /mnt/cdrom //创建挂载点 [r…

    Linux 2023年6月13日
    0145
  • USB转双串口产品设计-RS232串口

    基于USB转2路串口芯片CH342,可以为各类主机扩展出2个独立的串口。CH342芯片支持使用操作系统内置的CDC串口驱动,也支持使用厂商提供的VCP串口驱动程序,可支持Windo…

    Linux 2023年6月7日
    0113
  • tcpreplay重放报文,tcpdump能抓到包,应用程序收不到包

    现象: 生产环境中有两台服务器A、B,A服务器实时有报文发往B服务器。为了在测试环境测试新功能,故在现网A服务器上tcpdump抓取发往B服务器的报文,然后在测试环境tcprewr…

    Linux 2023年5月27日
    0172
  • redis中key和value的存储大小限制

    String类型:一个String类型的value最大可以存储512M List类型:list的元素个数最多为2^32-1个,也就是4294967295个。 Set类型:元素个数最…

    Linux 2023年5月28日
    0150
  • Redis高可用架构Sentinel

    1 简介 哨兵是用来解决redis高可用性的,可以监控集群中主从的变化,然后进行故障转移。一套合理的监控机制是Sentinel节点判定节点不可达的重要保证,Redis Sentin…

    Linux 2023年6月13日
    0113
  • ELK收集日志之logstash使用

    一、logstash使用 1.logstah收集文件日志 不难理解,我们的日志通常都是在日志文件中存储的,所以,当我们在使用INPUT插件时,收集日志,需要使用file模块,从文件…

    Linux 2023年5月27日
    0108
  • PYTORCH: 60分钟 | TENSORS

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

    Linux 2023年6月16日
    0197
  • 统计算法_数值/线性关系度量

    继续统计算法,这次也没什么特别的,还没到那么深入,也是比较基础的1、方差-样本2、协方差(标准差)-样本3、变异系数4、相关系数 依然是先造个list,这次把这个功能写个函数,方便…

    Linux 2023年6月6日
    0170
  • 重磅硬核 | 一文聊透对象在 JVM 中的内存布局,以及内存对齐和压缩指针的原理及应用

    欢迎关注公众号:bin的技术小屋,大家如果看到图片显示不了的话,可以查看公众号原文 大家好,我是bin,又到了每周我们见面的时刻了,我的公众号在1月10号那天发布了第一篇文章《从内…

    Linux 2023年6月6日
    0166
  • Linux上安装tomcat

    参考https://www.digitalocean.com/community/tutorials/how-to-install-apache-tomcat-8-on-cento…

    Linux 2023年6月6日
    0110
  • 翻车!误删/usr/lib/引发的血案,从棺材边成功抢救的过程分享。

    写在开篇 血案:本地开发机是CentOS 7,本想删除在/usr/lib/下的一个软链,如:/usr/lib/xxx。当正想删除时,突然被别的事情打扰了一下,回过神之后莫名奇妙的执…

    Linux 2023年6月7日
    0121
  • linux版的查毒工具 ClamAv 安装脚本

    /bin/bash 安装linux版的查毒工具 clamav 用root执行 保证服务器能访问外网 yum源最好是最新的 创建用户和组 groupadd clamavuseradd…

    Linux 2023年6月13日
    0116
  • Linux快速入门(七)效率工具(Vim)

    Vim编辑器 所有的 Linux系统都会内建一个 Vi文本编辑器,而 Vim是从 Vi发展出来的一个高度可配置的文本编辑器,旨在高效的创建和更改任何类型的文本,它还可以根据文件的扩…

    Linux 2023年6月6日
    0112
  • Linux系统Yum中的$releasever和$basearch变量

    Yum的配置文件中包含大量的$releasever和$basearch变量,那么他们的取值是什么呢? 为什么要折腾这个玩意呢?有点地方的网络是私有化网络,内部有大量的Linux服务…

    Linux 2023年6月8日
    0105
  • 【抄】Shell正则表达式

    shell 正则语法基础 copy from: https://man.linuxde.net/docs/shell_regex.html 正则表达式的分类 基本的正则表达式(Ba…

    Linux 2023年5月28日
    0129
  • NJU软件分析笔记(1)

    课程链接本次课程主要内容 Compilers and Static Analyzers AST vs. IR IR: Three-Address Code (3AC) 3AC in…

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