redis线程模型(三)

速度

根据官方的 benchmark,通常来说,在一台普通硬件配置的 Linux 机器上跑单个 Redis 实例,处理简单命令(时间复杂度 O(N) 或者 O(log(N))),QPS 可以达到 8w+

速度快的原因

  • 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。
  • 数据结构简单,对数据操作也简单,如哈希表、跳表都有很高的性能。
  • 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑同步情况下的锁问题
  • 使用I/O多路复用模型

为什么要设计成单线程

在讨论这个问题之前,我们要先明确『单线程』这个概念的边界:它的覆盖范围是核心网络模型。

因此,当我们讨论 Redis 的多线程之时,有必要对 Redis 的版本划出两个重要的节点:

  1. Redis v4.0(引入多线程处理异步任务)
  2. Redis v6.0(正式在网络模型中实现 I/O 多线程)

Redis基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器。它的组成结构为4部分:多个套接字、IO多路复用程序、文件事件分派器、事件处理器。因为文件事件分派器队列的消费是单线程的,所以Redis才叫单线程模型。

简单版本:

使用了单线程后,可维护性高。多线程模型虽然在某些方面表现优异,但是它却引入了程序执行顺序的不确定性,带来了并发读写的一系列问题,增加了系统复杂度、同时可能存在线程切换、甚至加锁解锁、死锁造成的性能损耗。

Redis 通过 AE 事件模型以及 IO 多路复用等技术,处理性能非常高,因此没有必要使用多线程。单线程机制使得 Redis 内部实现的复杂度大大降低.

Redis中只有网络请求模块和数据操作模块是单线程的(指的是文件事件处理器中的文件事件分派器使用一个线程来处理,即一个线程处理所有网络请求)。而其他的如持久化存储模块、集群支撑模块等是多线程的。redis从4.0版本开始其实就引入了多线程。

理解版本:

官方表示,Redis是基于内存操作,CPU不是Redis的性能瓶颈,Redis的性能瓶颈是机器的内存(可通过加大内存来解决,或者优化数据结构)和网络带宽(io多路复用)。大多数请求不会是 CPU 密集型的,而是 I/O 密集型。

一个计算机程序在执行的过程中,主要需要进行两种操作分别是读写操作和计算操作。其中读写操作主要是涉及到的就是I/O操作,其中包括网络I/O和磁盘I/O。计算操作主要涉及到CPU。

而多线程的目的,就是通过并发的方式来提升I/O的利用率和CPU的利用率。那么,Redis需不需要通过多线程的方式来提升提升I/O的利用率和CPU的利用率呢?

首先,我们可以肯定的说,Redis不需要提升CPU利用率,因为Redis的操作基本都是基于内存的,CPU资源根本就不是Redis的性能瓶颈。所以,通过多线程技术来提升Redis的CPU利用率这一点是完全没必要的。

那么,使用多线程技术来提升Redis的I/O利用率呢?是不是有必要呢?

Redis确实是一个I/O操作密集的框架,他的数据操作过程中,会有大量的网络I/O和磁盘I/O的发生。要想提升Redis的性能,是一定要提升Redis的I/O利用率的,这一点毋庸置疑。

但是,提升I/O利用率,并不是只有采用多线程技术这一条路可以走!

虽然采用多线程可以帮助我们提升CPU和I/O的利用率,但是多线程带来的并发问题(多线程编程模式带来的共享资源的并发控制问题)也给这些语言和框架带来了更多的复杂性。而且,多线程模型中,多个线程的互相切换也会带来一定的性能开销。

所以,在提升I/O利用率这个方面上,Redis并没有采用多线程技术,而是选择了多路复用 I/O技术。

io多路复用模型

基于单线程Reactor模型。这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个客户端的网络IO连接请求(尽量减少网络 IO 的时间消耗)。他采用IO多路复用机制同时监听多个Socket,根据Socket上的事件来选择对应的事件处理器进行处理。文件事件处理器的结构包含4个部分:

•    多个Socket
•    IO多路复用程序
•    文件事件分派器
•    事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

多个Socket可能会产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序会监听多个Socket,会将Socket产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。

redis6.0版本增加了多线程处理

Redis 6.0的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行。6.0没有默认开启多线程,需要在配置文件中开启。

https://zhuanlan.zhihu.com/p/356059845

https://zhuanlan.zhihu.com/p/357343339

https://developer.aliyun.com/article/760847

https://blog.csdn.net/a745233700/article/details/113488673

https://xie.infoq.cn/article/b6733865dbf95ddcf9968156a

https://segmentfault.com/a/1190000037434936

猜你喜欢

转载自blog.csdn.net/weixin_46217160/article/details/115691314
今日推荐