(三)Redis 线程与IO模型
1、Redis 单线程
通常说 Redis 是单线程,主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,其他功能,比如持久化、异步删除、集群数据同步等,是由额外的线程执行的,所以严格来说,Redis 并不是单线程。
多线程开发会不可避免的带来并发控制和资源开销的问题,如果没有良好的系统设计往往会适得其反,为了避免这些问题,Redis 直接采用了单线程模式。
Redis 单线程模型能达到每秒数十万级别的处理能力,一方面是大部分操作在内存上完成 + 高效的数据结构,例如哈希表和跳表。另一方面,就是采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率。
在了解多路复用之前,要先明白网络操作的基本 IO 模型和潜在的阻塞点。如果单线程被阻塞了,就无法进行多路复用了。以 Get 请求为例如下图,bind/listen、accept、recv、parse 和 send 属于网络 IO 处理,get 属于键值数据操作。
这里的网络 IO 操作中,潜在的阻塞点分别是 accept() 和 recv()。当 Redis 监听到一个客户端有连接请求,但一直未能成功建立起连接时,会阻塞在 accept() 函数这里,导致其他客户端无法和 Redis 建立连接。类似的,当 Redis 通过 recv() 从一个客户端读取数据时,如果数据一直没有到达,Redis 也会一直阻塞在 recv(),这就导致 Redis 整个线程阻塞,无法处理其他客户端请求,效率很低。不过,Socket 网络模型可以设置非阻塞模式,基于此 Linux 中的 IO 多路复用机制就要登场了。
2、多路复用机制
Linux 中的 IO 多路复用机制是指一个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制。简单来说,在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字。内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 IO 流的效果。
图中的多个 FD 就是指多个套接字,Redis 网络框架调用 epoll 机制,让内核监听这些套接字。此时,Redis 线程不会阻塞在某一个特定的监听或已连接套接字上,所以,Redis 可以同时和多个客户端连接并处理请求,从而提升并发性。
为了在请求到达时能通知到 Redis 线程,select/epoll 提供了基于事件的回调机制,即针对不同事件的发生,调用相应的处理函数,select/epoll 一旦监测到 FD 上有请求到达时,就会触发相应的事件。这些事件会被放进一个事件队列,Redis 单线程对该事件队列不断进行处理。这样一来,Redis 无需一直轮询是否有请求实际发生,这就可以避免造成 CPU 资源浪费。同时,Redis 在对事件队列中的事件进行处理时,会调用相应的处理函数,这就实现了基于事件的回调。因为 Redis 一直在对事件队列进行处理,所以能及时响应客户端请求,提升 Redis 的响应性能。
3、Redis 6.0 多线程特性
Redis 6.0 之前,虽然有些命令操作可以用后台线程或子进程执行(比如数据删除、快照生成、AOF 重写),但是,从网络 IO 处理到实际的读写命令处理,都是由单个线程完成的,有时会成为 Redis 的性能瓶颈。Redis 6.0 之后采用多个 IO 线程来处理网络请求,提高网络请求处理的并行度,对于读写命令,仍然使用单线程来处理。
具体流程:
(1)主线程接收到客户端连接请求后创建连接,将 Socket 放入全局等待队列中,通过轮询分配给 IO 线程。
(2)分配后主线程就会进入阻塞状态,等待 IO 线程完成客户端请求读取和解析,多个 IO 线程在并行处理,嗖嗖嗖。
(3)IO 线程解析完请求,主线程还是会以单线程的方式执行这些命令操作。
(4)主线程执行完请求操作后,把返回结果写入缓冲区,主线程阻塞等待 IO 线程把这些结果回写到 Socket 中,并返回给客户端。
和 IO 线程读取和解析请求一样,IO 线程回写 Socket 时,也是有多个线程在并发执行,所以回写 Socket 的速度也很快。等到 IO 线程回写 Socket 完毕,主线程会清空全局队列,等待客户端的后续请求。
4、IO 多线程配置
在实际应用中,如果 Redis 实例的 CPU 开销不大,吞吐量却没有提升,可以考虑使用多线程机制提升吞吐量,redis.conf 中设置:
1. 设置 io-thread-do-reads 配置项为 yes,表示启用多线程
io-threads-do-reads yes
2. 设置线程个数要小于 Redis 实例所在机器的 CPU 核个数,例如,对于一个 8 核的机器来说,Redis 官方建议配置 6 个 IO 线程
io-threads 6
(三)Redis 线程与IO模型的更多相关文章
- Replication基础(六) 复制中的三个线程(IO/SQL/Dump)
Reference: https://blog.csdn.net/sun_ashe/article/details/82181811?utm_source=blogxgwz1 简介在MySQL复制技 ...
- {python之IO多路复用} IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) IO模型比较分析 selectors模块
python之IO多路复用 阅读目录 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 ...
- 15 并发编程-(IO模型)
一.IO模型介绍 1.阻塞与非阻塞指的是程序的两种运行状态 阻塞:遇到IO就发生阻塞,程序一旦遇到阻塞操作就会停在原地,并且立刻释放CPU资源 非阻塞(就绪态或运行态):没有遇到IO操作,或者通过某种 ...
- 通过实例理解Java网络IO模型
网络IO模型及分类 网络IO模型是一个经常被提到的问题,不同的书或者博客说法可能都不一样,所以没必要死抠字眼,关键在于理解. Socket连接 不管是什么模型,所使用的socket连接都是一样的. 以 ...
- Reids原理之IO模型
众所周知Redis是单进程单线程的应用,在如今多核横行的时代,我们不免有疑问,单线程的redis怎么就成了高性能的代表 当有多个线程同时调用redis的时候,那么单线程的redis是怎么处理的呢,这里 ...
- python(40)- 进程、线程、协程及IO模型
一.操作系统概念 操作系统位于底层硬件与应用软件之间的一层.工作方式:向下管理硬件,向上提供接口. 操作系统进行进程切换:1.出现IO操作:2.固定时间. 固定时间很短,人感受不到.每一个应用层运行起 ...
- 03 高性能IO模型:采用多路复用机制的“单线程”Redis
本篇重点 三个问题: "Redis真的只有单线程吗?""为什么用单线程?""单线程为什么这么快?" "Redis真的只有单线程吗? ...
- Redis线程模型的前世今生
一.概述 众所周知,Redis是一个高性能的数据存储框架,在高并发的系统设计中,Redis也是一个比较关键的组件,是我们提升系统性能的一大利器.深入去理解Redis高性能的原理显得越发重要,当然Red ...
- 详解redis网络IO模型
前言 "redis是单线程的" 这句话我们耳熟能详.但它有一定的前提,redis整个服务不可能只用到一个线程完成所有工作,它还有持久化.key过期删除.集群管理等其它模块,redi ...
- Reactor三种线程模型与Netty线程模型
文中所讲基本都是以非阻塞IO.异步IO为基础.对于阻塞式IO,下面的编程模型几乎都不适用 Reactor三种线程模型 单线程模型 单个线程以非阻塞IO或事件IO处理所有IO事件,包括连接.读.写.异常 ...
随机推荐
- WPF随笔收录-实时绘制心率曲线
一.前言 在自己的项目中,涉及到实时心率曲线的绘制,项目上的曲线绘制,一般很难找到能直接用的第三方库,而且有些还是定制化的功能,所以还是自己绘制比较方便.很多人一听到自己画就害怕,感觉很难,今天就分享 ...
- SpringCloud 应用在 Kubernetes 上的最佳实践 — 线上发布(可监控)
简介: 本篇是"SpringCloud 应用在 Kubernetes 上的最佳实践"系列文章的第六篇,主要介绍了如何保障生产环境服务稳定,做到随时发布,从而加快业务的迭代和上线速度 ...
- 阿里云RemoteShuffleService新功能:AQE和流控
简介:阿里云EMR自2020年推出Remote Shuffle Service(RSS)以来,帮助了诸多客户解决Spark作业的性能.稳定性问题,并使得存算分离架构得以实施.为了更方便大家使用和扩展 ...
- Apsara Stack 技术百科 | 数字化业务系统安全工程
简介:数字化平台已经与我们生活紧密结合,其用户规模庞大,一旦系统出现故障,势必会造成一定生活的不便.比如疫情时代,健康码已经成为人们出门必备的条件,一旦提供健康码服务平台出现故障,出行将变得寸步难行 ...
- WPF 从零自己实现从 RealTimeStylus 获取触摸信息
本文将告诉大家什么是 RealTimeStylus 以及如何从零开始不使用 WPF 框架提供的功能从 RealTimeStylus 获取到触摸信息 开始之前先复习一下 Windows 的触摸演进.在上 ...
- WPF 通过 RawInput 获取触摸消息
触摸在 Windows 下属于比较特殊的输入,不同于键盘和鼠标,键盘和鼠标可以通过全局 Hook 的方式获取到鼠标和键盘的输入消息.而触摸则没有直接的 Hook 的方法.如果期望自己的应用,可以在没有 ...
- dotnet 6 数组拷贝性能对比
本文来对比多个不同的方法进行数组拷贝,和测试其性能 测试性能必须采用基准(标准)性能测试方法,否则测试结果不可信.在 dotnet 里面,可以采用 BenchmarkDotNet 进行性能测试.详细请 ...
- js实现打字机效果(完整实例)
在上篇css高斯模糊的效果基础上用js实现一个打字机效果: 上图: 代码: <!DOCTYPE HTML> <html lang="en-US"> < ...
- 表和数据连接,而不是和表连接(JOIN)
1.连接数据,但是顺序会受影响 在使用JOIN连接临时表或子查询时,无法保证结果的顺序与特定值的顺序完全一致.这是因为在查询过程中,数据库优化器可能会选择不同的执行计划,导致结果的顺序发生变化. SE ...
- .NET开源、功能强大、跨平台的图表库 - LiveCharts2
前言 今天大姚给大家分享一个.NET开源(MIT License).功能强大.简单.灵活.跨平台的图表.地图和仪表库:LiveCharts2. 项目介绍 LiveCharts2是一个.NET开源. ...