为什么说Redis是单线程的
误区: "通常说'Redis 是单线程的',指的是其核心的数据操作(命令执行)是单线程的 。实际上,Redis 内部还有后台线程(如 RDB/AOF 异步刷盘、Lazy Free 等)。从 Redis 6.0 开始,网络 I/O(接收请求、发送响应)和协议解析 可以启用多线程,但命令执行仍由主线程串行处理。"
一个计算机程序执行的过程中主要分为两种操作:分别是读写操作 和计算操作
注意: 这里的读写操作指的是网络请求**(** I/O操作 ) ,计算操作指的是数据处理操作**(涉及到CPU)**
先说下 多线程 的适用场景
**前情提要:**一个计算机程序执行过程中主要分为两个操作:分别是读写操作和计算操作
其中读写操作涉及到的就是I/O操作,计算操作涉及到的是CPU
而 多线程 的目的就是通过并发的方式提高 I/O 和CPU的利用率
但是Redis不需要利用多线程的方式来提高I/O和CPU的利用率
为什么呢?
关于CPU的利用率
由于Redis是基于内存存储的,所以它的操作非常快,CPU根本来不及成为瓶颈;
❤️ 先理解:什么是"基于 内存 存储"?🧠
🔹 内存 vs 磁盘的速度对比:
|---------|----------|-------------------|
| 存储类型 | 访问速度 | 举个例子 |
| 内存(RAM) | ~100 ns | 读一个字节 ≈ 1/1000 秒 |
| 磁盘(HDD) | ~10 ms | 读一个字节 ≈ 1/100 秒 |
| SSD | ~100 μs | 读一个字节 ≈ 1/10000 秒 |
👉 内存比磁盘快上万倍!
关于 I/O 利用率
I/O的利用率确实是Redis的瓶颈,但是不一定要通过多线程的方式来解决(😂虽然6.0版本还是使用了多线程方式解决,不过需要手动开启不然用的还是多路复用I/O技术(下面开始讲))
为什么不用 多线程 来解决这个问题呢?
因为虽然采用多线程技术可以帮助我们解决提高I/O和CPU利用率的问题,但是多线程带来的并发问题也给我们带来了更多的复杂性**(比如:我们平常用到的编程语言都有用到多线程技术,我们都会遇到** 线程安全 问题比如调用某个方法时,我们应该如何保证共享变量的正确性,如果正确处理多个线程之间的共享变量)。而且多线程模型,多个线程的上下文切换也会有性能的开销
所以Redis使用的是多路复用 I/O 技术保证的I/O利用率
多路复用 I/O **技术:**将进程的请求都放入一个管道当中,这个管道会统一和内核进行交互,当管道中的某一个请求的数据准备好之后,进程再把相应的数据拷贝到用户空间
为什么Redis在6.0引入了 多线程
其实前面就已经说过在6.0版本网络请求模块已经变成多线程的了,但是数据处理模块还是单线程的
虽然Redis的性能已经很高,已经可以满足绝大多数的应用了,但是不可避免地是大公司的数据量都是很大的,所以为了QPS都会部署Redis集群,但是这种做法是很耗资源的。
其实主要还是多路复用I/O技术产生的问题,我们都知道多路复用I/O技术是将进程的请求都放入管道中,但这种模型,是同步阻塞型I/O模型
多路复用I/O模型在处理网络请求的过程是阻塞的,也就是说这个过程会阻塞线程,如果并发量很高此处会成为瓶颈。
虽然现在很多服务器都是多个CPU核的,但是对于Redis来说,因为使用了单线程,在一次数据操作的过程中,有大量的CPU时间片是耗费在了网络I0的同步处理上的,并没有充分的发挥出多核的优势。
如果能采用 多线程 ,使得网络处理的请求并发进行,就可以大大的提升性能。多线程除了可以减少由于网络I/0等待造成的影响,还可以充分利用 CPU 的多核优势。
那么引入 多线程 之后不会造成 线程安全 问题吗?
前面其实也说过了只是对网络请求模块使用多线程模块,对数据处理模块并没有使用多线程