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

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

Redis Server:

redis实现了一套事件触发模型,主要处理两种事件:I/O事件(文件事件)和定时事件。而处理它们的就靠一个EventLoop线程。同时redis还提供了丰富的数据结构,今天我们要分析的主要是List数据结构中的阻塞命令。

先来看看BLPOP的源码(做了精简,只看主要的部分,详细的可以看文尾提供的参考链接):

t_list.c

t_list.c_1.png

t_list.c_2.png

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

既然是list数据结构,当然有push数据的操作:

同样是t_list.c

t_list.c_3.png

t_list.c_4.png

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

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

redis.c

redis.c_1.png

t_list.c_5.png

t_list.c_6.png

上面代码表明:每次处理完客户端命令后都会遍历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

BinaryJedis.java.png

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

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

NIO的实现就稍微复杂一些,这里分两种情况(以netty为例):

不带RquestID的实现方式

伪代码如下:

不带RquestID.png

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

带RequestID的实现方式

伪代码如下:

带RequestID.png

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

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

redis阻塞队列 java_Redis阻塞操作实现原理相关推荐

  1. Java阻塞队列ArrayBlockingQueue和LinkedBlockingQueue实现原理分析

    转载自  Java阻塞队列ArrayBlockingQueue和LinkedBlockingQueue实现原理分析 Java中的阻塞队列接口BlockingQueue继承自Queue接口. Block ...

  2. java 多线程阻塞队列 与 阻塞方法与和非阻塞方法

    Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...

  3. java 中 阻塞队列 非阻塞队列 和普通队列的区别

    转载自 https://blog.csdn.net/u012881904/article/details/51491736 阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻 ...

  4. Java阻塞队列-BlockingQueue介绍及实现原理

    阻塞队列是对普通队列的一种扩展,在普通队列功能上增加了一些额外功能. 普通队列的功能可以参照java的Queue接口 public interface Queue<E> extends C ...

  5. 什么是阻塞队列?阻塞队列的实现原理是什么?如何使用阻塞队列来实现生产者-消费者模型?

    阻塞队列(BlockingQueue)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...

  6. 【redis】redis实现队列的阻塞、延时、发布和订阅

    Redis不仅可作为缓存服务器,还可以用作消息队列.它的列表类型天生支持用作消息队列.如下图所示: 由于Redis的列表是使用双向链表实现的,保存了头节点和尾节点,所以在列表的头部和尾部两边插入或获取 ...

  7. LinkedBlockingQueue 链式阻塞队列的使用方法和原理

    目录 目录 概览 使用方法 1. add | remove | element 2. offer | poll | peek 3. put | take 4. offer | poll (timeou ...

  8. java 手写阻塞队列_Java阻塞队列的实现

    阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞.试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列 ...

  9. Java线程详解(15)-阻塞队列和阻塞栈

    Java线程:新特征-阻塞队列 阻塞队列是Java5线程新特征中的内容,Java定义了阻塞队列的接口java.util.concurrent.BlockingQueue,阻塞队列的概念是,一个指定长度 ...

最新文章

  1. jq 读取office插件_800+页麦肯锡经典图示发送!让你不用插件,轻松搞定逻辑图...
  2. [文摘20070913]最好的消息
  3. vs编译obj给delphi用
  4. 友声电子秤设置软件_友声电子秤说明书/操作指南?(一)
  5. java中start与loop_java for-loop问题
  6. 使用Nsight查找CE3的渲染bug
  7. error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
  8. python k线顶分型_顶分型底分型代码
  9. 格力空调通讯协议_格力空调485通讯协议格式 485总线上modbus通信协议?
  10. 监控行业常见视频格式
  11. U产品快报 | UK8S支持K8S 1.18版本、URTC新版Webdemo上线等重要更新
  12. Linux如何创建用户及设置权限
  13. latex怎么打区间_latex 函数中间点
  14. Akamai阿卡迈_abck逆向sensor_data(一)
  15. SDRAM芯片中的DQM信号的理解
  16. 1 基于搜索的路径规划 —— Dijkstra算法(python)
  17. 第四篇:coalesce 和repartition 在shuffle 和并行度之间的选择(spark2.3持续更新中...........)
  18. 计算机Excel删除和清除,电脑EXCEL表格一次删除所有空行的两种方法
  19. Axure的交互事件
  20. 全球与中国四乙基氢氧化铵市场竞争趋势与企业竞争策略研究报告2022-2028年版

热门文章

  1. pthread_create创建线程
  2. 树链剖分——轻重链剖分
  3. 更换电脑时,如何将原OutLook中邮件全部导出呢
  4. 「镁客·请讲」速腾聚创邱纯鑫:要做配有软件算法的高性价比激光雷达
  5. linux文件夹重命名
  6. 还在看美女直播跳舞,过时啦老夫反手就是一波用jmeter对直播间做压测
  7. android 蓝牙连接图标不见了,Android P系统默认蓝牙状态栏不显示图标
  8. adobe reader java_PDF显示福昕阅读器中的签名,但不显示Adobe Reader
  9. tomcat idea项目访问、下载web项目外的静态资源(图片、文件),js下载项目外的文件,server.xml设置对idea中的项目不生效
  10. 前端优化之if...else判断