-
2020-05-26 10:03:22
redis为什么可以支持高并发和它内部的工作模式有不可分割的关系:
- 绝大部分请求是纯粹的内存操作(非常快速)
- 采用单线程,避免了不必要的上下文切换和竞争条件
- 非阻塞IO - IO多路复用
Redis客户端对服务端的每次调用都经历了发送命令,执行命令,返回结果三个过程。其中执行命令阶段,由于Redis是单线程来处理命令的,所有到达服务端的命令都不会立刻执行,所有的命令都会进入一个队列中,然后逐个执行,并且多个客户端发送的命令的执行顺序是不确定的,但是可以确定的是不会有两条命令被同时执行,不会产生并发问题,这就是Redis的单线程基本模型。
文件事件处理器结构包含5个部分,其实真正包含为4个部分(不包含socket队列,加上主要方便后面理解):多个socket、IO多路复用程序、socket队列、文件事件分派器、以及事件处理器。如图:
注:如果只是单纯的单线程,那么redis在每一次的IO处理上都会耗费很长的时间,但是redis这里使用了IO多路复用监听多个socket,哪个socket接收完成了请求的IO,就将这个scoket塞入socket队列,这样就大大减少了IO处理的时间。
如图可以看出
- 客户端请求过来,到了IO多路复用
- 监听到接收请求完成的socket,放入队列供文件事件分派器消费(这个过程是单线程的)
- 文件事件分派器在选择对应的事件处理器进行处理
这里只是简单解读了redis的内部工作模式,具体的多路复用原理大家需要了解可以自行了解。
但是这里得说明下redis这里主流程虽然是单线程,但并不代表redis任何时候都是单线程的,比如我们之前讲的redis持久化操作,就会启用一个子线程进行持久化操作,这种操作还存在很多场景,所以redis的单线程指的是redis的主流程单线程,既我们上述所讲的过程。
另外redis6.0好像也要引入上述主流程的多线程操作,因为在面试的时候被问到redis是单线程还是多线程时不能一口咬定就是单线程。
更多相关内容 -
Redis 单线程还是多线程?
2019-09-18 09:51:27Redis 单线程还是多线程 前段时间无意间看到一篇博客,讲述了Redis6即将在年底发布的事情,好奇心驱动下搜索了官网,想看看新版Redis带来了什么新的功能,果然得到证实Redis在年底将发布新的版本:6.0,并且Redis...Redis 单线程还是多线程
前段时间无意间看到一篇博客,讲述了Redis6即将在年底发布的事情,好奇心驱动下搜索了官网,想看看新版Redis带来了什么新的功能,果然得到证实Redis在年底将发布新的版本:6.0,并且Redis创始人兼核心开发者 antirez 在博客也介绍了将在6.0所提供的新功能
ACL用户权限控制功能
RESP3:新的 Redis 通信协议
Cluster 管理工具
SSL 支持
IO多线程支持
新的Module API
新的 Expire 算法等具体可以参考相关资料(http://antirez.com/latest/0)
这里只是大致说一下自身比较感兴趣的功能
IO多线程
刚开始看到Redis支持多线程的时候,其实自身心里挺疑惑的,Redis难道是单线程?为什么单线程响应能够那么快?带着这些疑问翻阅了相关资料。官方FAQ表示,因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案。
那既然是单线程那为什么会那么快呢?原来Redis使用了单线程架构和I/O多路复用模型来实现高性能的内存数据库服务,只所以快可归结一下几点:
1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
4、使用多路I/O复用模型,非阻塞IO;
5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求
以上几点都比较好理解,下边我们针对多路 I/O 复用模型进行简单的探讨:
首先,Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞的,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导致整个进程无法对其它客户提供服务,而 I/O 多路复用就是为了解决这个问题而出现的.
多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量
注意:上面说的都是单线程的优点,但单线程也有其缺点,对于每个命令的执行时间有要求,如果某个命令执行时间过长,会造成其他命令阻塞,对于Redis这种高性能的服务来说是致命的。
既然单线程Redis这么优越,Redis 6.0引入的IO多线程岂不是多余?
答案肯定是非也,目前对于单线程 Redis 来说,性能瓶颈主要在于网络的 IO 消耗,优化主要有两个方向:
1、提高网络 IO 性能,典型的实现像使用 DPDK 来替代内核网络栈的方式
2、使用多线程充分利用多核,典型的实现像 Memcached协议栈优化的这种方式跟 Redis 关系不大,多线程特性在社区也被反复提了很久后, Redis作者antirez终于在 Redis 6 加入多线程(据说多线程 IO 特性的引入对性能提升至少是一倍以上,http://antirez.com/news/126)。因为读写网络的read/write系统调用在Redis执行期间占用了大部分CPU时间,如果把网络读写做成多线程的方式对性能会有很大提升,这里所说的多线程,是通过系统调用写操作,将客户端的输入输出缓冲中的数据通过多线程IO与客户端交互。现在已经实现了第一版,write side即回复客户端这部分已经完成了,并且去掉了主线程和IO线程之间的互斥锁,采用busy loop的形式来等待io线程工作结束,这部分能够有50%的性能提升,架构图如下
但跟 Memcached 这种从 IO 处理到数据访问多线程的实现模式有些差异,Redis 的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程。之所以这么设计是不想因为多线程而变得复杂,需要去控制 key、lua、事务,LPUSH/LPOP 等等的并发问题。整体的设计大体如下:
多线程 IO 的读(请求)和写(响应)在实现流程是一样的,只是执行读还是写操作的差异。同时这些 IO 线程在同一时刻全部是读或者写,不会部分读或部分写的情况,所以下面以读流程作为例子。分析过程中只会覆盖核心逻辑而不是全部细节。如果想完全理解细节,建议看完之后再次看一次源码实现。
加入多线程 IO 之后,整体的读流程如下:
1、主线程负责接收建连请求,读事件到来(收到请求)则放到一个全局等待读处理队列
2、主线程处理完读事件之后,通过 RR(Round Robin) 将这些连接分配给这些 IO 线程,然后主线程忙等待(spinlock 的效果)状态
3、IO 线程将请求数据读取并解析完成(这里只是读数据和解析并不执行)
4、主线程执行所有命令并清空整个请求等待读处理队列(执行部分串行)上面的这个过程是完全无锁的,因为在 IO 线程处理的时主线程会等待全部的 IO 线程完成,所以不会出现data race的场景。
总结
不管单线程还是多少线程,其实对应Redis不同模块而已。对于Redis 6.0 2019 年底发布,其将在性能、协议以及权限控制都会有很大的改进,还是值得期待的。
最后在说一下,Redis 6.0将采用全新协议 RESP3,进而实现 Client side caching(客户端缓存)功能,可以说是在提升Redis作为缓存的读写能力有了质的飞跃,值得期待。有兴趣的可以看看RESP3 的设计稿:
https://github.com/antirez/RESP3/blob/master/spec.md -
redis单线程快的原因和原理
2021-01-21 15:05:48(二)单线程操作,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗; (三)采用了非阻塞I... -
Redis 到底是单线程还是多线程?
2021-11-16 21:18:351 Redis单线程问题 主要是指Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的...1 Redis单线程问题
主要是指Redis的网络IO和键值对读写是由一个线程来完成的,Redis在处理客户端的请求时包括获取 (socket 读)、解析、执行、内容返回 (socket 写) 等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。这也是Redis对外提供键值存储服务的主要流程。
但Redis的其他功能,比如持久化、异步删除、集群数据同步等等,其实是由额外的线程执行的。Redis工作线程是单线程的,但是,整个Redis来说,是多线程的。2 Redis单线程为什么快
(1) 基于内存操作:Redis 的所有数据都存在内存中,因此所有的运算都是内存级别的,所以他的性能比较高;
(2) 数据结构简单:Redis 的数据结构是专门设计的,而这些简单的数据结构的查找和操作的时间大部分复杂度都是 O(1),因此性能比较高;
(3) 多路复用和非阻塞 I/O:Redis使用 I/O多路复用功能来监听多个 socket连接客户端,这样就可以使用一个线程连接来处理多个请求,减少线程切换带来的开销,同时也避免了 I/O 阻塞操作;
(4) 避免上下文切换:因为是单线程模型,因此就避免了不必要的上下文切换和多线程竞争,这就省去了多线程切换带来的时间和性能上的消耗,而且单线程不会导致死锁问题的发生;3 I/O 多路复用
这是IO模型的一种,即经典的Reactor设计模式,
I/O 多路复用,简单来说就是通过监测文件的读写事件再通知线程执行相关操作,保证 Redis 的非阻塞 I/O 能够顺利执行完成的机制。
多路指的是多个socket连接,
复用指的是复用一个线程。多路复用主要有三种技术:select,poll,epoll。
epoll是最新的也是目前最好的多路复用技术。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗),且Redis在内存中操作数据的速度非常快(内存内的操作不会成为这里的性能瓶颈),主要以上两点造就了Redis具有很高的吞吐量。4 Redis 6
在 Redis 6.0 中新增了多线程的功能来提高 I/O 的读写性能,他的主要实现思路是将主线程的 IO 读写任务拆分给一组独立的线程去执行,这样就可以使多个 socket 的读写可以并行化了,采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗),将最耗时的Socket的读取、请求解析、写入单独外包出去,剩下的命令执行仍然由主线程串行执行并和内存的数据交互。
结合上图可知,网络IO操作就变成多线程化了,其他核心部分仍然是线程安全的,是个不错的折中办法。5 Redis6 开启多线程
在Redis6.0中,多线程机制默认是关闭的,如果需要使用多线程功能,需要在redis.conf中完成两个设置。
1 设置io-thread-do-reads配置项为yes,表示启动多线程。
2 设置线程个数。关于线程数的设置,官方的建议是如果为 4 核的 CPU,建议线程数设置为 2 或 3,如果为 8 核 CPU 建议线程数设置为 6,线程数一定要小于机器核数,线程数并不是越大越好。 -
Redis是单线程还是多线程问题
2020-08-08 11:52:471、Redis单线程 在一开始的时候,Redis采用的是单线程模型,因为Redis是一个基于内存的数据库,将所有的数据放入内存,所以使用单线程的操作效率是最高的,多线程会上下文切换消耗大量时间,对于内存系统来说,单...在学习redis的过程中,很多文章都说redis是单线程,但在官方给出的说明中显示,redis6.0已经引入了多线程,对此我找了许多文档,将学习过程整理记录下来。
1、Redis单线程
在一开始的时候,Redis采用的是单线程模型,因为Redis是一个基于内存的数据库,将所有的数据放入内存,所以使用单线程的操作效率是最高的,多线程会上下文切换消耗大量时间,对于内存系统来说,单线程才能产生更高的效率。但是单线程不意味着整个Redis就一个线程,Redis其他模块还有各自的线程。
如下图:
Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。
使用I/O多路复用机制同时监听多个客户端,在单线程模式下,即使网络处理很多,因为存在I/O多路复用,依然可以在高速的内存处理下得到忽略。
2、Redis为什么引入多线程
Redis基于内存操作,CPU并不是性能瓶颈,Redis的瓶颈是根据机器的内存和网络带宽。在6.0的版本中引入了多线程。
这个I/O threads 指的是网络I/O处理方面使用了多线程,如网络数据的读写和协议解析等,这是因为读写网络的read/write在Redis执行期间占用了大部分CPU时间,如果把这部分模块使用多线程方式实现会对性能带来极大地提升。但是Redis执行命令的核心模块还是单线程的。目前最新的6.0版本中,I/O多线程处理模式需要在配置文件中开启。
-
为什么说Redis是单线程的以及Redis为什么这么快!
2021-01-07 09:15:34简单解释下第二条:上下文切换就是cpu在多线程之间进行轮流执行(枪战cpu资源),而redis单线程的,因此避免了繁琐的多线程上下文切换。 重点解释下多路复用: 多路-指的是多个socket连接,复用-指的是复用一个线程... -
redis单线程还是多线程
2020-05-29 13:58:48Redis 的单线程 Redis 是单线程模型,指的是执行 Redis 命令的核心模块是单线程的,而不是整个 Redis 实例就一个线程,Redis 其他模块还有各自模块的线程的。 Redis基于Reactor模式开发了网络事件处理器,这个... -
redis单线程和多线程
2022-02-14 09:13:40普遍说redis是单线程的,指的是redis处理请求、解析、执行命令是单线程完成的,但像清理过期数据等操作仍然是多线程完成的 6.0版本之前 整个流程都是单线程完成的 6.0版本之后 默认不开启 主线程接收到请求后,将... -
Redis是单线程还是多线程?为何速度快?
2021-03-06 12:35:47速度快的原因Redis单线程模型是怎样的? 单线程还是多线程? Redis是单线程操作,采用非阻塞IO多路复用单线程,长期持有IO连接,减少了网络IO的时间。 速度快的原因 1.基于纯内存操作,速度快; 2.数据结构简单; 3.... -
redis是单线程还是多线程?
2022-02-07 14:36:16Redis 是单线程,主要是指 Redis 对外提供键值存储服务的主要流程,即网络 IO 和键值对读写是由⼀个线程来完成的。除此外 Redis 的其他功能,比如持久化、 异步删除、集群数据同步等,是由额外的线程执⾏的。在这... -
Redis面试题(一): Redis到底是多线程还是单线程?
2018-04-02 18:18:360.redis单线程问题单线程指的是网络请求模块使用了一个线程(所以不需考虑并发安全性),即一个线程处理所有网络请求,其他模块仍用了多个线程。1.为什么说redis能够快速执行(1) 绝大部分请求是纯粹的内存操作(非常... -
Redis单线程模型详解
2022-01-16 16:28:42为什么Redis单线程模型也能效率这么高? Redis 单线程模型简介 Redis 内部使用文件事件处理器 file event handler ,这个文件事件处理器是单线程的,所以 Redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听... -
大厂面试题:Redis到底是单线程还是多线程?
2021-07-14 00:11:10马上就要金九银十了,有不少同学都想趁此机会跳槽涨薪进大厂,不过想要入职大厂可谓是千军万马过独木桥,竞争非常激烈啊!如何能够在面试官眼中脱颖而出显得尤为重要。想要跳槽涨薪,Redis是你一定... -
Redis是单线程还是多线程
2022-01-14 11:10:00我们平时看到介绍 Redis 的文章,都会说 Redis 是单线程的。但是我们学习的时候,比如 Redis 的 bgsave 命令,它的作用是在后台异步保存当前数据库的数据到磁盘,那既然是异步了,肯定是由别的线程去完成的,这怎么... -
Redis是单线程还是多线程的
2021-06-03 22:29:55Redis是单线程还是多线程的 1、Redis单线程指的是什么? Redis单线程模型,指的是执行 Redis 命令的核心模块是单线程的,而不是整个 Redis 实例就一个线程。 Redis基于Reactor模式开发了网络事件处理器,这个... -
20_来聊聊redis的线程模型吧?为啥单线程还能有很高的效率?.zip
2020-11-13 22:57:00https://mp.csdn.net/console/uploadResources?spm=1011.2124.3001.4171 -
redis单线程模式
2021-12-06 16:47:261、redis单线程指的是:Redis 的网络 IO 和键值对读写是由一个线程来完成的,这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的... -
Redis到底是单线程还是多线程?
2020-05-18 15:28:54Redis采用的是基于内存的采用的是单进程单线程模型的 KV 数据库,由C语言编写,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。这个数据不比采用单进程多线程的同样基于内存的 KV 数据库 Memcached 差!... -
redis单线程和优劣势
2021-09-28 08:51:12为什么Redis是单线程的 因为Redis是基于内存的...Redis单线程的优劣势 1)单进程单线程优势 代码更清晰,处理逻辑更简单 2)单进程单线程弊端 无法发挥多核CPU性能,不过可以通过在单机开多个Redis实例来完善。 ... -
redis单线程&IO多路复用
2020-10-19 11:31:44redis单线程: redis是以socket方式通信,socket服务端可同时接受多个客户端请求连接,也就是说,redis服务同时面对多个redis客户端连接请求,而redis服务本身是单线程运行。 假设,现在有A,B,C,D,E五个客户端... -
Redis(二) 单线程与io多路复用 redis6多线程
2022-03-12 14:23:29redis多线程,io多路复用技术,删除清理操作异步线程,网络io读写多线程 -
Redis单线程为何这么快
2022-02-08 10:03:48因为redis是基于Reactor模式开发了网络事件处理器和文件事件处理器,它是单线程的,所以redis才叫单线程模型。 Redis的单线程模型 文件处理器的结构包含:多个socket、IO多路复用程序、文件事件分派器和事件处理器... -
redis基础和使用(三)--单线程与IO多路复用
2021-11-12 10:29:53文章目录1 Redis为什么是单线程的1.1 官方解释1.2 Redis单线程优势1.3 Redis 不仅仅是单线程1.4 Redis的性能瓶颈2 IO多路复用2.1 文件描述符和文件句柄2.2 什么是IO多路复用?2.3 Redis的IO多路复用3 多线程IO多路... -
Redis 多线程
2021-12-28 19:11:57在Redis 6.0中,非常受关注的第一个新特性就是多线程。这是因为,Redis一直被大家熟知的就是它的单线程架构,虽然有些命令操作可以用后台线程或子进程执行(比如数据删除、快照生成、AOF重写)。但是,从网络IO处理... -
Redis单线程模型
2019-09-18 21:58:161.Redis单线程模型 1.1.文件事件处理器 1>.Redis基于Reactor模式开发了网络事件处理器,这个处理器就叫做文件事件处理器(file event handler).这个文件事件处理器是单线程的,所以Redis才叫做单线程的模型,文件事件... -
详解redis单线程模型
2021-03-31 16:57:01背景:但凡你用redis都知道redis的一大特点就是单线程,那么在如今服务器普遍多核的时代下,为什么redis要采用单线程模型?单线程模型好在哪里?不用单线程模型redis是不是可以更快?带着这些问题我们一起来回顾一下... -
Redis单线程模型和IO多路复用
2020-07-09 15:06:33Redis使用单线程,可以避免上下文切换,效率最高。避免了线程切换、加锁等资源消耗 IO多路复用指多个channel或者网络IO,共用一个或者少量线程来处理。 为什么使用多路复用,是因为与用户网络传输是需要等待的,IO...