Redis6.0之前为什么不使用多线程?模型+客户端缓存

前言

Redis 于 2020 年 5 月正式推出 6.0 版本,提供了许多令人兴奋的新功能,因此备受关注。

它提供了哪些功能?你知道我能不能加薪?

主要特点如下:

多线程网络IO;客户端缓存;细粒度的权限控制(ACL);使用RESP3协议;用于复制的 RDB 文件不再有用,将立即删除;RDB 文件加载速度更快;

其中,“多线程模型+客户端缓存”是备受关注的一种。只有掌握了新特性的原理,才能判断什么时候使用6.0版本,以及如何更好更快的使用而不踩坑。

本文从Redis多线程模型入手,至于客户端缓存等,听听接下来的分解。

最后线程标识符 有什么用,点击下方卡片关注“码哥字节”获得加薪。

为什么 Redis 在 6.0 之前没有使用多线程?

官方回答:

Redis 通过 AE 事件模型和 IO 多路复用具有非常高的处理性能,因此无需使用多线程。

单线程机制大大降低了Redis内部实现的复杂度。Hash 的惰性 Rehash、Lpush 和其他“线程不安全”命令可以在没有锁的情况下执行。

在为什么 Redis 这么快?”码哥对快的原理有详细的介绍。

在Redis6.0之前线程标识符 有什么用,单线程意味着Redis只有一个线程可以工作吗?

不,Redis在处理客户端请求时,包括获取(socket读取)、解析、执行、内容返回(socket写入)等,都是由一个顺序串行的主线程处理的,称为“单线程”。

在命令执行阶段,由于 Redis 以单线程处理命令,所有到达服务器的命令都不会立即执行,所有命令都会进入一个 Socket 队列。当socket可读时,会一一交给单线程事件调度器。被执行。

此外,一些命令操作可以通过后台线程或子进程执行(例如数据删除、快照生成、AOF 重写)。

代码又老又湿,为什么 Redis 6.0 会引入多线程呢?

随着硬件性能的提升,Redis的性能瓶颈可能会出现网络IO读写,即单线程处理网络读写的速度跟不上底层网络硬件的速度。

在 Redis 执行过程中,读写网络的 read/write 系统调用占用了大部分 CPU 时间。瓶颈主要是网络的IO消耗。优化主要有两个方向:

添加对用户态网络协议栈的支持需要修改Redis源码中与网络相关的部分(例如修改所有网络发送和接收请求函数),这会带来很大的开发工作量。

而且新代码还可能引入新的bug,导致系统不稳定。

因此,Redis 使用多个 IO 线程来处理网络请求,以提高网络请求处理的并行度。

需要注意的是,Redis 多 IO 线程模型仅用于处理网络读写请求。对于 Redis 的读写命令,依然是单线程处理。

这是因为网络处理往往是瓶颈,通过多线程并行处理可以提高性能。

继续使用单线程执行读写命令,不需要开发多线程安全机制来保证Lua脚本、事务等,实现更简单。

架构图如下:

主线程和IO多线程如何配合?

如下所示:

主要工艺:

主线程负责接收连接建立请求,获取socket并放入全局等待读处理队列;主线程通过轮询将可读socket分配给IO线程;主线程阻塞并等待IO线程读取socket;主线程执行IO线程读取和解析后的Redis请求命令;主线程阻塞并等待IO线程将命令执行结果写回socket;主线程清除全局队列并等待来自客户端的后续请求。

思路:将主线程IO读写任务拆分为一组独立的线程进行处理,这样多个socket读写任务可以并行化,但Redis命令还是由主线程串行执行。

如何启用多线程?

Redis 6.0 的多线程默认是禁用的,只使用主线程。要启用它,需要修改 redis.conf 配置文件:io-threads-do-reads yes。

代码又老又湿,线程数是不是越多越好?

当然不是。关于线程数的设置,官方有一个建议:4核机建议设置为2或3线程,8核机建议设置为6线程,线程数必须小于机器核心数。

线程数不是越多越好。官方认为超过8个基本没有意义。

另外,开启多线程后,还需要设置线程数,否则不会生效。

io-threads 4
1.

总结与思考

随着互联网的飞速发展,互联网业务系统要处理的在线流量越来越大。Redis 的单线程模式会导致系统在网络 I/O 上消耗大量 CPU 时间,从而降低吞吐量。要提升Redis的性能,需要从两个方向:

后者取决于硬件的发展,暂时没有解决方案。所以只能从前者入手,网络I/O的优化可以分为两个方向:

模型缺陷

Redis 的多线程网络模型实际上并不是标准的 Multi-Reactors/Master-Workers 模型。在Redis的多线程方案中,I/O线程任务只是通过socket读取和解析客户端请求命令,并没有真正执行命令。

所有客户端命令仍然需要回到主线程执行,所以多核的利用率不高,而且每次分配任务后主线程都要忙于轮询,等待所有I/O线程完成任务before 继续其他逻辑。

在我看来,Redis 目前的多线程方案更像是一种折中的选择:既保持原有系统的兼容性,又使用多核来提升 I/O 性能。

终于

分享一张Redis知识图谱,请点赞。

此外,还整理了40多套PDF文档:一套完整的Java面试合集手册,“性能调优+微服务架构+并发编程+开源框架+分布式”等7个面试专栏,包括Tomcat、JVM、 MySQL、SpringCloud、SpringBoot、Dubbo、并发、Spring、SpringMVC、MyBatis、Zookeeper、Ngnix、Kafka、MQ、Redis、MongoDB、memcached 等等。如果你对此感兴趣,我可以免费分享。

添加博主获取Redis集合信息

​​​

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论