为什么说 Redis 是单线程的?——Java全栈知识(25)

为什么说 Redis 是单线程的?

我们常说的 Redis 是单线程的,但是我前面在讲持久化机制的时候又说 RDB 的持久化是通过主进程 fork 出一个子进程来实现 RDB 持久化。那么 Redis 到底是多线程还是单线程的呢?
Redis 的网络 IO 和键值的读写是单线程完成的。
但是在 Redis4.0 之后,Redis 引入了多线程模型,但是 IO 部分还是由单线程完成,而其他的如持久化存储模块、集群支撑模块等是多线程的。(Redis 6.0 之后将网络 IO 改为了多线程)

[!info]
前面我们讲到的 RDB 持久化,以及 Redis 集群支撑都是基于多线程完成的

1、多线程的好处

多线程的好处在于能够更大程度的利用 CPU 资源以及 IO 资源。
首先 Redis 是否需要提升 CPU 利用?
我们都知道 Redis 是基于内存的数据库,CPU 的资源不是 Redis 的性能瓶颈
所以,通过多线程技术来提升 Redis 的 CPU 利用率这一点是完全没必要的。

那么,使用多线程技术来提升 Redis 的 l/O 利用率呢?是不是有必要呢?
Redis 确实是一个 I/O 操作密集的框架,他的数据操作过程中,会有大量的网络 I/O 和磁盘 I/O 的发生。要想提升 Redis 的性能,是一定要提升 Redis 的 I/O 利用率的,这一点毋膏置疑。
但是,提升 I/O 利用率,并不是只有采用多线程技术这一条路可以走。
image.png|700
Redis 基于 I/O 多路复用来提高 IO 利用率。

2、多线程的坏处

我们都知道 Java 针对并发安全做出了很多的方案。如内存模型、锁、CAS 等,这些者都是 Java 中提供的一些在多线程情况下保证线程安全的技术。
和 Java 类似,所有支持多线程的编程语言或者框架,都不得不面对的一个问题,就是如何解决多线程编程模式带来的共享资源的并发控制问题。
虽然,采用多线程可以帮助我们提升 CPU 和I/O 的利用率,但是多线程带来的并发问题也给这些语言和框架带来了更多的复杂性。而且,多线程模型中,多个线程的互相切换也会带来一定的性能开销。
所以,在提升I/O 利用率这个方法上,Rdis 并没有采用多线程技术,而是选择了多路复用 I/O 技术。

3、Redis 是否需要多线程?

6.0 之前没使用多线程原因:

  1. Redis 是基于内存的, 执行速度非常快,CPU 资源不是瓶颈。
  2. 采用多线程,避免不必要的上下文切换,避免线程不安全的问题。
  3. 采用了 I/O 多路复用,非阻塞式 IO。
    引入多线程的原因:
  4. 随着业务的越来越复杂,Redis 的网络 IO 还是成为了最大的瓶颈。
  5. Redis 6.0 的多线程,只是在处理网络 IO 处使用,在执行命令依然是单线程
### Redis 线程模型概述 Redis 的线程模型经历了不同的发展阶段,早期版本(v4.0 之前)主要采用单线程模型,而自 Redis v6.0 开始引入了多线程支持。以下是两种模型的区别及其特点。 #### 单线程模型 Redis 在 v6.0 之前的版本中采用了经典的单线程架构[^3]。这种模型的核心在于通过一个事件循环(event loop),利用 I/O 多路复用技术(如 `select`、`epoll` 或 `kqueue`)来高效地管理客户端连接并处理请求。具体来: - **文件事件处理器**:Redis 基于 Reactor 模式实现了文件事件处理器(File Event Handler)。该处理器负责监听多个 socket 连接上的事件,并根据事件类型调用相应的回调函数进行处理[^5]。 - **优点**: - 避免了多线程环境下的锁竞争和上下文切换开销。 - 设计简单,易于调试和优化。 - 对于绝大多数场景而言,CPU 并不是 Redis 性能的主要瓶颈;真正的瓶颈通常是网络 I/O[^3]。 然而,单线程模型也有局限性——当某个命令的执行时间较长时(如复杂计算或大对象操作),可能会阻塞整个事件循环,影响其他客户端的响应速度。 --- #### 多线程模型 随着 Redis 功能的扩展和技术需求的变化,Redis 自 v6.0 起引入了部分多线程的支持[^2]。尽管如此,Redis 的核心仍然是围绕单线程运行,新增的多线程特性主要用于特定场景下提升性能。主要包括以下几个方面: - **I/O 处理中的多线程**:在 Redis v6.0 中,网络读写操作可以通过配置启用多线程模式。此时,主线程仍然负责接收新连接和分发任务给工作线程池,而实际的数据读取/写入由这些工作线程完成[^1]。 - **持久化过程中的多线程**:对于 AOF 日志重写等耗时操作,也可以分配独立的工作线程来减少对主线程的影响[^4]。 需要注意的是,即使启用了多线程功能,默认情况下 Redis 的命令执行依然保持串行化,即每次只有一个命令会被解析和执行。这有助于维持 Redis 数据结构的一致性和高性能表现。 --- ### 单线程 vs 多线程区别总结表 | 特性 | 单线程模型 | 多线程模型 | |-------------------|----------------------------------|----------------------------------| | 核心逻辑 | 所有操作都在单一主线程内完成 | 主线程配合辅助线程共同协作 | | 使用范围 | 请求处理、数据存储与检索 | 网络 IO 及某些后台任务 | | 上下文切换成本 | 极低 | 较高 | | 锁机制依赖 | 不需要额外加锁 | 存在线程间同步问题 | 综上所述,虽然 Redis 已经具备了一定程度上的多线程能力,但从整体上看它依旧保留着以单线程为主导的设计理念[^2]。 ```python import redis # 创建 Redis 客户端实例 r = redis.Redis(host='localhost', port=6379, decode_responses=True) # 测试简单的键值操作 r.set('test_key', 'value') print(r.get('test_key')) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东莞呵呵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值