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

一.redis为什么要使用单线程

在多线程并发大行其道的今天,为什么redis要另辟蹊径选择单线程,要理解这一点我们就要先了解多线程的开销。

首先我们先明确两个概念,并行与并发:

并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。
并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。所以无论从微观还是从宏观来看,二者都是一起执行的。

可以看到对于并发场景来说在同一时刻只能有一条指令被执行,只不过处理器的处理速度极快,处理器在不同的线程来回中切换,给我们造成了一种所有指令同时运行的假象,这也就是为什么我们能够在电脑中同时运行超过我们CPU核心数的进程。注意到我们前面说的线程的切换,实际上这个操作是需要花费很多时间的。

CPU分配给每个线程的执行时间,我们一把称作时间片。时间片一般为几十毫秒。CPU通过时间片分配算法来循环执行任务,当前任务执行一个时间片后切换到下一个任务。但是我们思考一个这样的问题,时间片是一定的,但是任务所需时间是不一定的,也就是在时间片结束前,任务可能不能完全完成,那么我们就需要保存上一次任务的状态,以便下一次的再处理。所以任务从保存到再加载的过程就是我们常说的线程的上下文切换。对于redis这种应用于经常要处理海量数据的数据库来说,这个消耗成本是不可接受的。另外多线程编程模式下,还会面临对共享资源的并发访问的控制问题。

二.单线程的redis为什么快

通常来说,单线程的处理能力要比多线程差很多,但是 Redis 却能使用单线程模型达到每秒数十万级别的处理能力,这是为什么呢?其实,这是 Redis 多方面设计选择的一个综合结果。

一方面,Redis 的大部分操作在内存上完成,再加上它采用了高效的数据结构,例如哈希表和跳表,这是它实现高性能的一个重要原因。另一方面,就是 Redis 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率。

下面我们深入的探讨一下网络中的基本IO模型,和多路复用机制的优点。

三.redis用的多路复用机制好在哪?

在这里我们主要介绍:阻塞式IO、非阻塞式IO和多路复用。

(1)阻塞式IO

         如上图所示,首先解释用户程序空间和内核空间:在java中用read方法从网络上读取数据,需要由操作系统来做这个事情,这里就涉及到用户空间和内核空间的切换,操作系统中有一个read方法来真正完成数据读取。而真正读取数据又分为两个阶段,等待数据和复制数据(从网卡读到内存),等复制结束了再从操作系统内核空间将数据传输到用户程序空间。所谓阻塞式IO模式就是在读取数据期间,内核空间等待数据和复制数据的过程中,用户线程啥活都做不了。

(2)非阻塞式IO

如上图所示,非阻塞IO在等待数据阶段没有读取到数据会直接返回,然后不断地重复这个过程,用户线程始终是运行状态。不过,真正在复制数据的阶段用户线程依然是阻塞住的。

(3)多路复用

可以看到,阻塞式IO会一直阻塞住等待内核的返回结果,这一等不仅可能会等到海枯石烂,而且还干不了其他活啊,于是出现了非阻塞式IO,我不能傻傻的等着啊,于是乎,在非阻塞的情况下,我们需要在一个循环中不断地查询内核,“哥,数据准备好没有啊?”,如果没有准备好,内核会返回给我们一个EWOULDBLOCK的错误,相比于阻塞式IO呆呆地等在原地啥也不干,非阻塞显然可以在循环中处理一些其他事情,当然,频繁的进行系统调用,这是会耗费大量的CPU资源的。那么,阻塞式IO和非阻塞式IO都存在相应的问题,不过我们细细分析一下可以发现,不对啊,为啥要我一直来问内核呢,内核你数据准备好通知我一声不就好了嘛。

没错,这就是IO多路复用的设计初衷,我们熟悉的select/poll/epoll就是为了实现这种想法,同时能够支持多个套接字的网络事件,具体差别不展开讲了。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字。内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。看到没,redis使用单线程+多路复用的机制实现了并发处理海量数据的目的。redis并不会阻塞在某一个特定客户端请求处理上,也不会像非阻塞式IO一样不断轮询看是否有请求发生,而是不断地去对内核通知的请求进行处理。

四.启示

最后提醒一点,我们通常说,Redis 是单线程,主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的。

这给我们带来什么启示?在生活中难免遇到各种各样的琐事,我们应该像redis一样,理清楚主要矛盾,将主要精力集中在你最想做的事情上,而不是什么事情都耗费很大的精力,这样才能做出成绩,加油吧。

一篇文章带你搞透redis高性能IO模型相关推荐

  1. 一篇文章带你搞懂Redis(超级无敌最最最详细版本)(命令大全)(真·收藏必备)

    (本文近两万字,阅读时间可能较久,建议收藏以便查询使用) 目录 Redis诞生背景功能简介 Redis的下载与安装 Redis键的基本操作 Redis键名查询 Redis键的类型查询 Redis键的重 ...

  2. java 不重启部署_一篇文章带你搞定SpringBoot不重启项目实现修改静态资源

    一.通过配置文件控制静态资源的热部署 在配置文件 application.properties 中添加: #表示从这个默认不触发重启的目录中除去static目录 spring.devtools.res ...

  3. 一篇文章带你搞定 MongoDB 实现 REST

    文章目录 一.前期准备 二.SpringBoot 实现 MongoDB 的 REST 三.使用 Postman 测试使用 一.前期准备 首先使用 docker 搭建好 MongoDB:一篇文章带你搞定 ...

  4. 一篇文章带你搞定19年数学建模机场出租车优化问题示例讲解含代码

    文章目录 一.问题分析 二.数据介绍 三.模型的求解 四.结果分析 一.问题分析 收集国内某一机场及其所在城市出租车的相关数据,给出该机场出租车司机的选择方案,并分析模型的合理性和对相关因素的依赖性. ...

  5. 借重新装系统之际,一篇文章带你玩透Windows 10从系统安装到软件选择

    系统安装所需软件 Rufus 一个制作USB-ISO的免费软件,比微软官方工具好的地方在于除了可以制作windows 系统U盘,还可以制作linux 以及安卓X86的系统安装光盘. 借重新装系统之际, ...

  6. 一篇文章带你搞懂网络层(网际层)-- 地址篇

    网络层(Network Layer)是OSI模型中的第三层(TCP/IP模型中的网际层),提供路由和寻址的功能,使两终端系统能够互连且决定最佳路径,并具有一定的拥塞控制和流量控制的能力.相当于发送邮件 ...

  7. 如何使用RSA 对数据加解密和签名验签?一篇文章带你搞定

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 三分割据纡筹策,万古云霄一羽毛. ...

  8. 一篇文章带你搞懂微信小程序的开发过程

    点击上方"前端进阶学习交流",进行关注 回复"前端"即可获赠前端相关学习资料 今 日 鸡 汤 只解沙场为国死,何须马革裹尸还. 大家好,我进阶学习者. 前言 小 ...

  9. 一篇文章带你搞定二维插值的 MATLAB 计算

    前面已经学习了二维插值的基本概念:一篇文章带你认识数学建模中的二维插值 本篇文章主要实现使用MATLAB进行二维插值计算 文章目录 一.网格节点的插值计算 二.散点数据的插值计算 1. 示例 1 2. ...

最新文章

  1. 如何为网站增加索引,促进网站SEO优化?
  2. SQL 交集 差集 并集 笛卡尔积 应用实例
  3. cimage和gdi绘图效率比较_GDI+和GDI绘图性能对比实验
  4. IIS7 + Tomcat7 整合共用80端口
  5. body curl 设置post_深入说说postman发送post请求
  6. shell bash判断文件或文件夹是否存在
  7. pyqt5实现注册界面并获得文本框内容
  8. 显卡风扇不转电脑黑屏_笔记本电脑开不了机是什么原因及常见解决办法
  9. java session时间_java设置session过期时间的实现方法
  10. EDG 官宣 Clearlove(明凯)正式退役成为教练,你有什么想说的?
  11. 【论文翻译和解释(2)】LOF:Identifying Density-Based Local Outliers论文精读
  12. oracle sql中( ),Oracle SQL中的函数
  13. 计算机基础知识对程序员来说有多重要?
  14. 公式宝典之颜色混合模式公式
  15. 《FORTRAN语法:章节篇》第1章 数据类型
  16. 电信android智能机定位问题
  17. 学习英音的电影和电视剧
  18. 测试开发面试题目(三)——测试用例、安卓苹果系统区别、小程序与app的区别
  19. jquery对json的遍历
  20. error: failed linking references

热门文章

  1. 7.PCIE配置空间读写软件
  2. Excel笔记(4)常用函数21-34
  3. MySQL-7 DDL约束 标识列 TCL事务控制语言 视图view
  4. 世界电信日| 谈谈电信行业缘何牵线云计算?
  5. python中有没有switch_为什么python没有switch/case
  6. 虚函数 虚继承 抽象类
  7. 2.郝斌C语言课程大纲
  8. 视觉享受,兼顾人文观感和几何特征的字体「GitHub 热点速览 v.22.46」
  9. java http range_断点续传 HTTP range requests
  10. IIR无限冲激响应和FIR有限冲激响应数字滤波器有什么区别?