redis阻塞队列 java_Redis阻塞操作实现原理
最近一位朋友问到:既然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阻塞操作实现原理相关推荐
- Java阻塞队列ArrayBlockingQueue和LinkedBlockingQueue实现原理分析
转载自 Java阻塞队列ArrayBlockingQueue和LinkedBlockingQueue实现原理分析 Java中的阻塞队列接口BlockingQueue继承自Queue接口. Block ...
- java 多线程阻塞队列 与 阻塞方法与和非阻塞方法
Queue是什么 队列,是一种数据结构.除了优先级队列和LIFO队列外,队列都是以FIFO(先进先出)的方式对各个元素进行排序的.无论使用哪种排序方式,队列的头都是调用remove()或poll()移 ...
- java 中 阻塞队列 非阻塞队列 和普通队列的区别
转载自 https://blog.csdn.net/u012881904/article/details/51491736 阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻 ...
- Java阻塞队列-BlockingQueue介绍及实现原理
阻塞队列是对普通队列的一种扩展,在普通队列功能上增加了一些额外功能. 普通队列的功能可以参照java的Queue接口 public interface Queue<E> extends C ...
- 什么是阻塞队列?阻塞队列的实现原理是什么?如何使用阻塞队列来实现生产者-消费者模型?
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...
- 【redis】redis实现队列的阻塞、延时、发布和订阅
Redis不仅可作为缓存服务器,还可以用作消息队列.它的列表类型天生支持用作消息队列.如下图所示: 由于Redis的列表是使用双向链表实现的,保存了头节点和尾节点,所以在列表的头部和尾部两边插入或获取 ...
- LinkedBlockingQueue 链式阻塞队列的使用方法和原理
目录 目录 概览 使用方法 1. add | remove | element 2. offer | poll | peek 3. put | take 4. offer | poll (timeou ...
- java 手写阻塞队列_Java阻塞队列的实现
阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞.试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列 ...
- Java线程详解(15)-阻塞队列和阻塞栈
Java线程:新特征-阻塞队列 阻塞队列是Java5线程新特征中的内容,Java定义了阻塞队列的接口java.util.concurrent.BlockingQueue,阻塞队列的概念是,一个指定长度 ...
最新文章
- jq 读取office插件_800+页麦肯锡经典图示发送!让你不用插件,轻松搞定逻辑图...
- [文摘20070913]最好的消息
- vs编译obj给delphi用
- 友声电子秤设置软件_友声电子秤说明书/操作指南?(一)
- java中start与loop_java for-loop问题
- 使用Nsight查找CE3的渲染bug
- error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
- python k线顶分型_顶分型底分型代码
- 格力空调通讯协议_格力空调485通讯协议格式 485总线上modbus通信协议?
- 监控行业常见视频格式
- U产品快报 | UK8S支持K8S 1.18版本、URTC新版Webdemo上线等重要更新
- Linux如何创建用户及设置权限
- latex怎么打区间_latex 函数中间点
- Akamai阿卡迈_abck逆向sensor_data(一)
- SDRAM芯片中的DQM信号的理解
- 1 基于搜索的路径规划 —— Dijkstra算法(python)
- 第四篇:coalesce 和repartition 在shuffle 和并行度之间的选择(spark2.3持续更新中...........)
- 计算机Excel删除和清除,电脑EXCEL表格一次删除所有空行的两种方法
- Axure的交互事件
- 全球与中国四乙基氢氧化铵市场竞争趋势与企业竞争策略研究报告2022-2028年版
热门文章
- pthread_create创建线程
- 树链剖分——轻重链剖分
- 更换电脑时,如何将原OutLook中邮件全部导出呢
- 「镁客·请讲」速腾聚创邱纯鑫:要做配有软件算法的高性价比激光雷达
- linux文件夹重命名
- 还在看美女直播跳舞,过时啦老夫反手就是一波用jmeter对直播间做压测
- android 蓝牙连接图标不见了,Android P系统默认蓝牙状态栏不显示图标
- adobe reader java_PDF显示福昕阅读器中的签名,但不显示Adobe Reader
- tomcat idea项目访问、下载web项目外的静态资源(图片、文件),js下载项目外的文件,server.xml设置对idea中的项目不生效
- 前端优化之if...else判断