面试时说Redis是单线程的,被喷惨了!
Redis是单线程的,这话搁以前,是横着走的,谁都知道的真理。现在不一样,Redis 变了。再说这句话,多少得有质疑的语气来跟你辩驳一番。意志不坚定的,可能就缴械投降,顺着别人走了。
到底是什么样的,各位看官请跟我一起往下看:
- 思维导图 -
Reactor模式
反应器模式,你可能不太认识,如果看过上篇文章的话应该会有点印象。涉及到 Redis 线程它是一个绕不过去的话题。
1、传统阻塞IO模型
在讲反应器模式前,这里有必要提一下传统阻塞IO模型的处理方式。
在传统阻塞IO模型中,由一个独立的 Acceptor 线程来监听客户端的连接,每当有客户端请求过来时,它就会为客户端分配一个新的线程来进行处理。当同时有多个请求过来,服务端对应的就会分配相应数量的线程。这就会导致CPU频繁切换,浪费资源。
有的连接请求过来不做任何事情,但服务端还会分配对应的线程,这样就会造成不必要的线程开销。这就好比你去餐厅吃饭,你拿着菜单看了半天发现真他娘的贵,然后你就走人了。这段时间等你点菜的服务员就相当于一个对应的线程,你要点菜可以看作一个连接请求。
同时,每次建立连接后,当线程调用读写方法时,线程会被阻塞,直到有数据可读可写, 在此期间线程不能做其它事情。还是上边餐厅吃饭的例子,你出去转了一圈发现还是这家性价比最高。回到这家餐厅又拿着菜单看了半天,服务员也在旁边等你点完菜为止。这个过程中服务员什么也不能做,只能这么干等着,这个过程相当于阻塞。
你看这样的方式,每来一个请求就要分配一个线程,并且还得阻塞地等线程处理完。有的请求还只是过来连接下,什么操作也不干,还得为它分配一个线程,对服务器资源要求那得多高啊。遇到高并发场景,不敢想象。对于连接数目比较小的的固定架构倒是可以考虑。
2、伪异步IO模型
你可能了解过一种通过线程池优化的解决方案,采用线程池和任务队列的方式。这种被称作伪异步IO模型。
当有客户端接入时,将客户端的请求封装成一个 task 投递到后端线程池中来处理。线程池维护一个消息队列和多个活跃线程,对消息队列中的任务进行处理。
这种解决方案,避免了为每个请求创建一个线程导致的线程资源耗尽问题。但是底层仍然是同步阻塞模型。如果线程池内的所有线程都阻塞了,那么对于更多请求就无法响应了。因此这种模式会限制最大连接数,并不能从根本上解决问题。
我们继续用上边的餐厅来举例,餐厅老板在经营了一段时间后,顾客多了起来,原本店里的5个服务员一对一服务的话根本对付不过来。于是老板采用5个人线程池的方式。服务员服务完一个客人后立刻去服务另一个。
这时问题出现了,有的客人点菜特别慢,服务员就得等待很长时间,直到客人点完为止。如果5个客人都点的特别慢的话,这5个服务员就得一直等下去,就会导致其余的顾客没有人服务的状态。这就是我们上边所说的线程池所有线程都被阻塞的情况。
那么这种问题该如何解决呢?别急, Reactor 模式就要出场了。
3、Reactor设计模式
Reactor 模式的基本设计思想是基于I/O复用模型来实现的。
这里说下I/O复用模型。和传统IO多线程阻塞不同,I/O复用模型中多个连接共用一个阻塞对象,应用程序只需要在一个阻塞对象等待。当某个连接有新的数据可以处理时,操作系统通知应用程序,线程从阻塞状态返回,开始进行业务处理。
什么意思呢?餐厅老板也发现了顾客点餐慢的问题,于是他采用了一种大胆的方式,只留了一个服务员。当客人点餐的时候,这个服务员就去招待别的客人,客人点好餐后直接喊服务员来进行服务。这里的顾客和服务员可以分别看作多个连接和一个线程。服务员阻塞在一个顾客那里,当有别的顾客点好餐后,她就立刻去服务其他的顾客。
了解了 reactor 的设计思想后,我们再来看下今天的主角单 reactor 单线程的实现方案:
Reactor 通过 I/O复用程序监控客户端请求事件,收到事件后通过任务分派器进行分发。
针对建立连接请求事件,通过 Acceptor 处理,并建立对应的 handler 负责后续业务处理。
针对非连接事件,Reactor 会调用对应的 handler 完成 read->业务处理->write 处理流程,并将结果返回给客户端。
整个过程都在一个线程里完成。
单线程时代
了解了 Reactor 模式后,你可能会有一个疑问,这个和我们今天的主题有什么关系呢。可能你不知道的是,Redis 是基于 Reactor 单线程模式来实现的。
IO多路复用程序接收到用户的请求后,全部推送到一个队列里,交给文件分派器。对于后续的操作,和在 reactor 单线程实现方案里看到的一样,整个过程都在一个线程里完成,因此 Redis 被称为是单线程的操作。
对于单线程的 Redis 来说,基于内存,且命令操作时间复杂度低,因此读写速率是非常快的。
多线程时代
Redis6 版本中引入了多线程。上边已经提到过 Redis 单线程处理有着很快的速度,那为什么还要引入多线程呢?单线程的瓶颈在什么地方?
我们先来看第二个问题,在 Redis 中,单线程的性能瓶颈主要在网络IO操作上。也就是在读写网络 read/write 系统调用执行期间会占用大部分 CPU 时间。如果你要对一些大的键值对进行删除操作的话,在短时间内是删不完的,那么对于单线程来说就会阻塞后边的操作。
回想下上边讲得 Reactor 模式中单线程的处理方式。针对非连接事件,Reactor 会调用对应的 handler 完成 read->业务处理->write 处理流程,也就是说这一步会造成性能上的瓶颈。
Redis 在设计上采用将网络数据读写和协议解析通过多线程的方式来处理,对于命令执行来说,仍然使用单线程操作。
总结
Reactor模式
传统阻塞IO模型客户端与服务端线程1:1分配,不利于进行扩展。
伪异步IO模型采用线程池方式,但是底层仍然使用同步阻塞方式,限制了最大连接数。
Reactor 通过 I/O复用程序监控客户端请求事件,通过任务分派器进行分发。
单线程时代
基于 Reactor 单线程模式实现,通过IO多路复用程序接收到用户的请求后,全部推送到一个队列里,交给文件分派器进行处理。
多线程时代
单线程性能瓶颈主要在网络IO上。
将网络数据读写和协议解析通过多线程的方式来处理 ,对于命令执行来说,仍然使用单线程操作。
有道无术,术可成;有术无道,止于术
欢迎大家关注Java之道公众号
好文章,我在看❤️
面试时说Redis是单线程的,被喷惨了!相关推荐
- 单线程为什么cpu慢_面试时说Redis是单线程的,被喷惨了!
Redis是单线程的,这话搁以前,是横着走的,谁都知道的真理.现在不一样,Redis 变了.再说这句话,多少得有质疑的语气来跟你辩驳一番.意志不坚定的,可能就缴械投降,顺着别人走了. 到底是什么样的, ...
- 面试:为什么redis是单线程的,性能却很高?
面试:为什么redis是单线程的,性能却很高? 1.数据全部存在内存中,在内存中读数据比磁盘中快的多 2.采用了非阻塞io,io多路复用技术 3.避免了线程切换的资源消耗
- redis为什么是单线程_面试官:Redis单线程为什么执行效率这么高?
点击上方☝Java编程技术乐园,轻松关注!及时获取有趣有料的技术文章 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇回顾: 面试官:Redis为什么设计成单线程的 ...
- redis主从复制如何保证数据一致性_面试官:Redis 主从复制时网络开小差了怎么整?...
上周因为实在太忙就认认真真写了一篇水文,吹了一下自己过去的经历,反响竟然超出了我的预期,并且后台还有读者留言表示想看续集的.哈哈,果然大家还是对水文更有热情. 这期我们继续回到之前的 Redis 话题 ...
- 高频面试考点:Redis中有几百万数据量,如何进行高效访问?
作者:老顾 https://dwz.cn/pm3pI6MZ 一.前言 有时候我们需要知道线上Redis使用情况,尤其需要知道一些前缀的key值,那我们怎么去查看呢?而且通常情况下Redis里的数据都是 ...
- Redis 属于单线程还是多线程?不同的版本有什么区别?
Redis 是普及率最高的技术之一,同时也是面试中必问的一个技术模块,所以从今天开始我们将从最热门的 Redis 面试题入手,更加深入的学习和了解一下 Redis. 我们本文的面试题是 Redis 属 ...
- 面试中关于Redis的问题看这篇就够了
昨天写了一篇自己搭建redis集群并在自己项目中使用的文章,今天早上看别人写的面经发现redis在面试中还是比较常问的(笔主主Java方向).所以查阅官方文档以及他人造好的轮子,总结了一些redis面 ...
- 吊打面试官!Redis 常见面试题请收好 | 原力计划
作者 | 敖丶丙 责编 | Elle 出品 | CSDN 博客 你知道的越多,你不知道的越多 GitHub地址 https://github.com/AobingJava/JavaFamily 已经开 ...
- Redis是单线程的以及Redis为什么这么快
2019独角兽企业重金招聘Python工程师标准>>> 一.前言 近乎所有与Java相关的面试都会问到缓存的问题,基础一点的会问到什么是"二八定律".什么是&qu ...
最新文章
- PDGAN: A Novel Poisoning Defense Method in Federated Learning Using Generative Adversarial Network笔记
- 进程与线程的区别(面试题)
- 高等数学一使用python实现极限后有代码
- oracle的基本命令,Oracle基本命令
- python做副业_学习Python可以做哪些副业,你是不是感觉自己错过了一个亿?
- swift中高阶函数map、flatMap、filter、reduce
- 软件基本功:不要给代码加系数
- 利用U盘装CentOS6.4和将CentOS6.4安装到U盘
- 解读核磁共振射频系统架构、模块结构及功能介绍
- 没有USB 如何通过adb连接手机设备
- word中替换向下箭头
- 正则验证邮箱格式是不是正确
- HostMonitor监控软件
- Kaggle鱼品种识别
- 硬盘分区整数G计算小公式
- 网络问题“56”的解决
- 【CSS】css变量
- 家里计算机网络布局图,装修新房WiFi如何布置 家庭网络系统布置方法【详解】...
- 突然觉得。。。好累!!!
- 【python】request HTTPS代理
热门文章
- vue中webpack默认配置_webpack中Entry与Output的基础配置
- ActivityManager kill reason
- android 调用系统方法,android 调用系统功窗口方法
- 三,位操作类指令:包括逻辑运算指令,测试指令和移位指令
- 【C语言重点难点精讲】C语言指针
- 全排列的递归与非递归形式
- JS 常用函数二(改变HTML样式)
- Java 获取命令行输入数据(命令行输入,Scanner类)
- C++ 常用设计模式
- Red Hat Enterprise Linux (RHEL) 6.4 DVD ISO 迅雷下载地址