面试官问我redis为什么是单线程的?

本文解释了Redis选择单线程的原因,包括内存操作高效、避免上下文切换和竞争条件。介绍了多路I/O复用模型如何提高并发处理。同时提到Redis5.0引入多线程以优化性能,但需注意删除大键可能导致阻塞,可使用UNLINK异步删除。生产环境需谨慎启用多线程IO以平衡性能和稳定性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前被面试官问redis为什么是单线程的、脑子一片空白?首先想到的答案是没有必要、因为redis基本都是操作内存的、效率很快、没必要开启多线程、显然这样的答案比较肤浅,回家赶紧恶补一下相关知识点。

Redis 并不是 CPU 密集型的服务

redis是单线程的原因在于redis用单个CPU绑定一块内存的数据,然后针对这块内存的数据进行多次读写的时候,都是在一个CPU上完成的。redis核心就是 如果我的数据全都在内存里,我单线程的去操作就是效率最高的。所以,redis是单线程。

一、 Redis为什么那么快

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

3、采用单线程,保证操作的原子性,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型,非阻塞IO;

5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

以上几点都比较好理解,下边针对多路 I/O 复用模型进行简单的探讨:

(1)多路 I/O 复用模型

多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。

这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。

二、为什么Redis是单线程的

首先要明白,上边的种种分析,都是为了营造一个Redis很快的氛围。官方FAQ表示,因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。

这里我们一直在强调的单线程,只是在处理我们的网络请求的时候只有一个线程来处理,一个正式的Redis Server运行的时候肯定是不止一个线程的,这里需要大家明确的注意一下。例如Redis进行持久化的时候会以子进程或者子线程的方式执行。

三、Redis多线程版本、以及多线程操作

其实最新版本也支持了多线程、面试官的说法也不严谨

Redis在版本5.0中引入了多线程的支持。在此之前,Redis是单线程运行的,这意味着Redis无法充分利用多核处理器的性能优势。为了提高Redis的并发处理能力,Redis引入了多线程技术,从而在一定程度上提高了Redis的性能

Redis作为一个基于内存的缓存系统,一直以高性能著称,因没有上下文切换以及无锁操作,即使在单线程处理情况下,读速度仍可达到11万次/s,写速度达到8.1万次/s。但是,单线程的设计也给Redis带来一些问题:

  • 只能使用CPU一个核;
  • 如果删除的键过大(比如Set类型中有上百万个对象),会导致服务端阻塞好几秒;
  • QPS难再提高。

在Redis中,删除大键可能会导致阻塞,特别是当键的大小超过了服务器的处理能力时。为了避免删除大键时阻塞Redis服务器,可以使用UNLINK命令来异步删除键。

UNLINK命令类似于DEL命令,但它是异步执行的,这意味着Redis会在后台删除给定的键,而不会阻塞当前的连接。

默认情况下,Redis是以单线程模式运行的,但是可以通过配置文件来开启多线程IO。

在redis.conf配置文件中,可以通过修改以下两个参数来开启多线程IO:

  1. io-threads-do-reads yes:开启多线程读操作。

  2. io-threads 4:设置线程数为4。

示例配置:

io-threads-do-reads yes
io-threads 4

在开启多线程IO后,Redis会使用多个线程来处理网络读写,但是仍然使用单个线程来处理实际的命令操作。

注意:在生产环境中,应当充分测试多线程IO模式对性能的影响,因为启用该特性可能会影响到Redis的性能和稳定性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值