一、前言

Redis 6.0首次引入了多线程。

看下官方发布的新版和旧版的性能对比:

1)get的性能对比:

redis可以多线程运行吗 redis 6.0多线程原理_数据库


2)set的性能对比:

redis可以多线程运行吗 redis 6.0多线程原理_多线程_02


可以看出,无论读还是写,多线程性能都远好于单线程,几乎翻倍了。上图仅是简单验证,仅作为参考,不能作为线上生成环境的指标。

二、Redis多线程

2.1、Redis 6.0之前的版本真的是单线程吗?

Redis是基于Reactor模式开发了网络事件处理器,这个处理器被称为文件事件处理器。他的组成分4部分:

  • 多个socket
  • IO 多路复用
  • 文件事件分派器
  • 事件处理器

正因为文件事件分派器是单线程的,所以Redis才叫做单线程模型。

redis可以多线程运行吗 redis 6.0多线程原理_redis可以多线程运行吗_03


Redis之前用单线程模型,是因为性能不在CPU,而在内存和网络。如要用到CPU多核,可搭建多个Redis实例来解决。

其实,Redis 4.0开始就有了多线程概念了,比如Redis通过多线程在后台删除对象。

2.1.1、Redis 6.0之前为什么一直不用多线程?

多线程引入了程序执行顺序不确定的问题,且带来了线程切换、加锁等性能问题。

Redis通过Reactor模型,性能已经非常好,没必要使用多线程。

且单线程使得redis内部实现复杂度大大降低,Hash的惰性Rehash, lpush等线程不安全的命令,都不必加锁。

2.1.2、Redis 6.0为什么要引入多线程呢?

Redis的性能瓶颈不在CPU,而在内存和网络。

内存不够,可以做数据结构优化。所以网络才是关键,网络IO在执行期间大量占用了CPU,所以如果网络IO时引入多线程,对性能提升很大。

所以总结起来,Redis6.0支持多线程有两个原因:
1)充分利用CPU多核,6.0之前主线程只能利用一个核
2)多线程任务可以分摊Redis同步IO读写负荷。

2.2、Redis 6.0是否默认开启了多线程?

没有,默认关闭。但可以在conf文件中配置。

官方建议:4核的机器建议设置为2或3个线程,8核的建议设为6个线程,线程数一定要小于机器核数,尽量不要超过8个。

三、Redis 6.0多线程的实现机制

redis可以多线程运行吗 redis 6.0多线程原理_redis_04

流程简述为:
1)主线程负责接收并建立连接请求,获取socket放入全局等待读处理队列
2)主线程处理完读事件后,通过Round Robin讲这些连接分配给这些IO线程
3)主线程阻塞等待IO读取socket完毕
4)主线程通过单线程的方式执行请求命令,请求数据读取并解析完成,但并不执行。
5)主线程阻塞等待IO线程将数据回写socket完毕
6)解除绑定,清空等待队列

也就是说,真正执行redis命令时,还是单线程的,如步骤4.
多线程,发生在网络IO,步骤三和步骤五

redis可以多线程运行吗 redis 6.0多线程原理_数据库_05


见上图的红字。

3.1、开启多线程后,是否会存在线程并发安全问题?

不会:
1)Redis多线程部分仅用于处理网络IO和协议解析
2)Redis执行命令仍然是单线程的