​在前面事务里面讲过Redis是一个单线程应用程序,当然我们比较有代表性的单线程还有Node.js、Nginx等。

那么既然是单线程的为什么还这么快呢?

Redis的数据都在内存里面,所有的运算都是内存级别,处理数据是非常快速的,所以这里得注意一些复杂度为O(n)的指令,可能会导致服务器卡顿。

那么Redis是一个单线程是如何处理并发客户端的连接呢?

这就是接下来要讲的非阻塞IO多路复用事件轮询API

非阻塞IO

那什么是阻塞IO模型?即在读写数据过程中会发生阻塞现象。

当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除block状态。

####阻塞IO模型,如果数据没有就绪,就会一直阻塞在read方法。data = socket.read();

非阻塞IO

当用户线程发起一个read操作后,并不需要等待,而是马上就得到了一个结果,不管你有没有发送进来,会立即执行下一行代码。如果结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦内核中的数据准备好了,并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程,然后返回。

非阻塞IO有个问题,那就是线程要读数据,结果读了一部分就返回了,那么线程如何知道何时才应该继续读,也就是说,当数据到来时,线程如何得到通知。写也是一样,如果缓冲区满了,写不完,剩下的数据何时才应该继续写,线程也应该得到通知。那么事件轮询API就是解决这个问题。

多路复用(事件轮询)

最简单的事件轮询API是select函数,它是操作系统提供给用户程序的API。输入是读写描述符列表read_fds&write_fds,输出是与之对应的可读可写事件。同时还提供了一个timeout参数,如果没有任何事件到来,那么就最多等待timeout的值的时间,线程处于阻塞状态。一旦期间有任何事件到来,就可以立即返回。时间过了之后还是没有任何事件到来,也会主即返回 。

因为我们通过select系统调用同时处理多个通道描述待的读写事件,因此我们将这类系统调用称为多路复用API。现代操作系统的多路复用API已经不再使用select系统调用,而改用epoll(linux)和kqueue(FreeBSD)和(macosx),因为select系统调用的性能在描述符特别多时会变得非常差。它们使用起来可能在形式上略有差异,但是本质上都是差不多的,都可以使用上面的伪代码逻辑进行理解。

指令队列

Redis会将每个客户端套接字都关联一个指令队列。客户端的指令通过队列来排队进行顺序处理,先到先服务。

响应队列

Redis同样也会为每个客户端套接字关联一个晌应队列。Redis服务器通过响应队列来将指令的返回结果回复给客户端。

如果队列为空,那么意昧着连接暂时处于空闲状态,不需要去获取写事件,也就是可以将当前的客户端描述符从write_fds里面移出来。等到队列有数据了,再将描述符放进去,避免select系统调用立即返回写事件,结果发现没什么数据可以写,出现这种情况的线程会令CPU消耗飘升。

定时任务

服务器除了要响应IO事件外,还要处理其他事情。比如定时任务就是非常重要的一件事。如果线程阻塞在select系统调用上,定时任务将无法得到准时调度。那Redis是如何解决这个问题的呢?
Redis的定时任务会记录在一个被称为“最小堆”的数据结构中。在这个堆中,
最快要执行的任务排在堆的最上方。在每个循环周期里,Redis都会对最小堆里面已经到时间点的任务进行处理。处理完毕后,将最快要执行的任务还需要的时间记录下来,这个时间就是select系统调用的timeout参数。因为Redis知道未来timeout的值的时间内,没有其他定时任务需要处理,所以可以安心睡眠 timeout 的值的时间。

Nginx和Node的事件处理原理和Redis也是类似的。

一名正在抢救的coder

笔名:mangolove

CSDN地址:https://blog.csdn.net/mango_love

GitHub地址:https://github.com/mangoloveYu

Redis线程IO模型的秘密知多少相关推荐

  1. Redis高效性探索--线程IO模型,通信协议

    Redis线程IO模型 Redis是单线程,这个毋庸置疑 Redis单线程能做到这么高的效率?不用怀疑,还有很多其他的服务都是单线程但是也有超高的效率,比如Node.js,Nginx也是单线程. Re ...

  2. 打卡学习 | Redis原理应用-线程IO模型

    这是小小国庆节更新的第一篇,小小本篇将会更新Redis原理应用,线程IO模型.我是小小,我们这期见面了. 送书反馈 小小送的书到啦,一共三本书,晒图如下. 小小开始今天的文章,跟我学Redis系列之, ...

  3. 一篇文章带你搞透redis高性能IO模型

    Redis作为K-V数据库,应用非常广泛,在各大厂的面试中,redis也是绕不开的一个话题.我们说redis快,常规的解释是redis是基于内存实现的以及它的高效的数据结构,其实redis快的原因还有 ...

  4. 03 Redis 网络IO模型简介

    1 Redis中的单线程模型 提起Redis,我们经常会说其底层是一个单线程模型,但这是不严谨的.Redis 单线程指的是网络请求模块使用了一个线程,即一个线程处理所有网络请求,其他模块该使用多线程, ...

  5. Redis的IO模型以及客户端与服务端设计

    文章目录 IO模型--事件驱动 文件事件(通常是与客户端的交互) 文件事件的处理器 时间事件(服务器的自身触发的一些维护操作) 分类 底层实现 时间事件应用实例:serverCron函数 事件的调度与 ...

  6. Redis线程模型的前世今生

    作者:vivo互联网服务器团队-Wang Shaodong 一.概述 众所周知,Redis是一个高性能的数据存储框架,在高并发的系统设计中,Redis也是一个比较关键的组件,是我们提升系统性能的一大利 ...

  7. IO模型、IO多路复用

    IO多路复用 基础概述 用户空间和内核空间 PIO与DMA 缓存IO和直接IO 缓存IO 优点 缺点 直接IO IO访问方式 磁盘IO 网络IO 磁盘IO和网络IO对比 Socket网络编程 客户端 ...

  8. python(40)- 进程、线程、协程及IO模型

    一.操作系统概念 操作系统位于底层硬件与应用软件之间的一层.工作方式:向下管理硬件,向上提供接口. 操作系统进行进程切换:1.出现IO操作:2.固定时间. 固定时间很短,人感受不到.每一个应用层运行起 ...

  9. 02 | 高性能 IO 模型:为什么单线程 Redis 能那么快?

    我们通常说,Redis 是单线程,主要是指Redis 的网络 IO和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程.但 Redis 的其他功能,比如持久化.异步删除 ...

最新文章

  1. RHEL/CentOS/OEL5/6.x高危漏洞修补
  2. python2与python3之间的主要区别
  3. 网络:浏览器静态资源缓存机制
  4. Java IO: File
  5. Halcon算子学习:xyz_to_object_model_3d
  6. C++ STL min_element和max_element的使用方法
  7. linux确定字符行,linux小计,统计文件中包含指定字符串的行数
  8. Android pk8/x509生成keystore
  9. beyond compare 代码对比工具使用方法
  10. java 内置中介模式_详解Java设计模式编程中的中介者模式
  11. 解决DNS解析故障的几种方法
  12. 方正书版PS文件转换PDF文件PHP源程序 发布说明
  13. 【NVMe2.0b 10】Controller Shutdown 与 NVM Subsystem Shutdown
  14. ethereum扫描区块,获取区块内的交易记录
  15. 蓝牙耳机哪个品牌比较好?盘点四款好用的蓝牙耳机
  16. CoBot 库博源代码缺陷检测工具
  17. c语言 符号自动换行,单片机串口发送字符为什么会自动换行?
  18. java8 —— Stream( 流 )
  19. 北京交通大学官网页面模仿
  20. WhatsApp受众画像概述

热门文章

  1. (软件工程复习核心重点)第一章软件工程概论-第二节:软件工程
  2. (王道408考研数据结构)第七章查找-第一节:查找的基本概念、平均查找长度
  3. Linux系统编程18:超详解进程程序替换exec函数的一些用法
  4. Socket选项之SO_RCVTIMEO 和SO_SNDTIMEO
  5. LeetCode 138 复制带随机指针的链表
  6. Python 动态获取对象的属性和方法(内含inspect)
  7. 05 Python字符串的通用操作
  8. 鼠标按下改变RelativeLayout背景颜色,松开变回
  9. spring事务介绍 1
  10. 题解 UVA10587 【Mayor's posters】