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模型的更多相关文章

  1. Replication基础(六) 复制中的三个线程(IO/SQL/Dump)

    Reference:  https://blog.csdn.net/sun_ashe/article/details/82181811?utm_source=blogxgwz1 简介在MySQL复制技 ...

  2. {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) 五 ...

  3. 15 并发编程-(IO模型)

    一.IO模型介绍 1.阻塞与非阻塞指的是程序的两种运行状态 阻塞:遇到IO就发生阻塞,程序一旦遇到阻塞操作就会停在原地,并且立刻释放CPU资源 非阻塞(就绪态或运行态):没有遇到IO操作,或者通过某种 ...

  4. 通过实例理解Java网络IO模型

    网络IO模型及分类 网络IO模型是一个经常被提到的问题,不同的书或者博客说法可能都不一样,所以没必要死抠字眼,关键在于理解. Socket连接 不管是什么模型,所使用的socket连接都是一样的. 以 ...

  5. Reids原理之IO模型

    众所周知Redis是单进程单线程的应用,在如今多核横行的时代,我们不免有疑问,单线程的redis怎么就成了高性能的代表 当有多个线程同时调用redis的时候,那么单线程的redis是怎么处理的呢,这里 ...

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

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

  7. 03 高性能IO模型:采用多路复用机制的“单线程”Redis

    本篇重点 三个问题: "Redis真的只有单线程吗?""为什么用单线程?""单线程为什么这么快?" "Redis真的只有单线程吗? ...

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

    一.概述 众所周知,Redis是一个高性能的数据存储框架,在高并发的系统设计中,Redis也是一个比较关键的组件,是我们提升系统性能的一大利器.深入去理解Redis高性能的原理显得越发重要,当然Red ...

  9. 详解redis网络IO模型

    前言 "redis是单线程的" 这句话我们耳熟能详.但它有一定的前提,redis整个服务不可能只用到一个线程完成所有工作,它还有持久化.key过期删除.集群管理等其它模块,redi ...

  10. Reactor三种线程模型与Netty线程模型

    文中所讲基本都是以非阻塞IO.异步IO为基础.对于阻塞式IO,下面的编程模型几乎都不适用 Reactor三种线程模型 单线程模型 单个线程以非阻塞IO或事件IO处理所有IO事件,包括连接.读.写.异常 ...

随机推荐

  1. WPF随笔收录-实时绘制心率曲线

    一.前言 在自己的项目中,涉及到实时心率曲线的绘制,项目上的曲线绘制,一般很难找到能直接用的第三方库,而且有些还是定制化的功能,所以还是自己绘制比较方便.很多人一听到自己画就害怕,感觉很难,今天就分享 ...

  2. SpringCloud 应用在 Kubernetes 上的最佳实践 — 线上发布(可监控)

    简介: 本篇是"SpringCloud 应用在 Kubernetes 上的最佳实践"系列文章的第六篇,主要介绍了如何保障生产环境服务稳定,做到随时发布,从而加快业务的迭代和上线速度 ...

  3. 阿里云RemoteShuffleService新功能:AQE和流控

    ​简介:阿里云EMR自2020年推出Remote Shuffle Service(RSS)以来,帮助了诸多客户解决Spark作业的性能.稳定性问题,并使得存算分离架构得以实施.为了更方便大家使用和扩展 ...

  4. Apsara Stack 技术百科 | 数字化业务系统安全工程

    ​简介:数字化平台已经与我们生活紧密结合,其用户规模庞大,一旦系统出现故障,势必会造成一定生活的不便.比如疫情时代,健康码已经成为人们出门必备的条件,一旦提供健康码服务平台出现故障,出行将变得寸步难行 ...

  5. WPF 从零自己实现从 RealTimeStylus 获取触摸信息

    本文将告诉大家什么是 RealTimeStylus 以及如何从零开始不使用 WPF 框架提供的功能从 RealTimeStylus 获取到触摸信息 开始之前先复习一下 Windows 的触摸演进.在上 ...

  6. WPF 通过 RawInput 获取触摸消息

    触摸在 Windows 下属于比较特殊的输入,不同于键盘和鼠标,键盘和鼠标可以通过全局 Hook 的方式获取到鼠标和键盘的输入消息.而触摸则没有直接的 Hook 的方法.如果期望自己的应用,可以在没有 ...

  7. dotnet 6 数组拷贝性能对比

    本文来对比多个不同的方法进行数组拷贝,和测试其性能 测试性能必须采用基准(标准)性能测试方法,否则测试结果不可信.在 dotnet 里面,可以采用 BenchmarkDotNet 进行性能测试.详细请 ...

  8. js实现打字机效果(完整实例)

    在上篇css高斯模糊的效果基础上用js实现一个打字机效果: 上图: 代码: <!DOCTYPE HTML> <html lang="en-US"> < ...

  9. 表和数据连接,而不是和表连接(JOIN)

    1.连接数据,但是顺序会受影响 在使用JOIN连接临时表或子查询时,无法保证结果的顺序与特定值的顺序完全一致.这是因为在查询过程中,数据库优化器可能会选择不同的执行计划,导致结果的顺序发生变化. SE ...

  10. .NET开源、功能强大、跨平台的图表库 - LiveCharts2

    前言 今天大姚给大家分享一个.NET开源(MIT License).功能强大.简单.灵活.跨平台的图表.地图和仪表库:LiveCharts2.   项目介绍 LiveCharts2是一个.NET开源. ...