Redis(八)——多线程与单线程

redis到底是多线程还是单线程?

首先我们需要知道的,redis处理用户请求一直都是单线程,只是redis4(包含redis4)之后才引入了多线程的概念,比如后台线程的RDB保存io线程、aof后台io线程、异步删除、集群同步等这些都是后台线程,也就是说redis整体来说是多线程的(redis4),而redis的用户请求则是单线程的。

那为什么redis4之前乃至现在用户请求还是单线程?

首先是因为单线程的架构比较简单,方便调试和开发,其次就是redis的性能其实主要是和内存和网络有关,和cpu的性能其实没多大关系,另外就是redis使用的非阻塞IO和IO多路复用也可以在单线程的架构下解决多客户端的并发需求。

redis为什么那么快?

首先就是他是一个内存数据库,没有频繁的磁盘IO,另外就是设计的数据结构让每次操作都能在时间复杂度O(1),还有就是上面说到的多路复用和非阻塞IO,让一个线程来完成多客户端的请求,没有频繁的线程切换而导致的性能损失,以及单线程的架构让各个客户端之间不存在锁竞争和死锁造成的性能问题。主要原因就是多路复用+epoll函数+内存+多网络IO才是redis为什么这么快的直接原因。

那为什么又要在redis4之后使用多线程?

首先就是随着工业的发展多核心多线程已经开始普及,所以没必要再墨守成规只使用单线程,当然这里的单线程我指的是redis整体,其次就是redis4之前的大Key删除缓慢的问题,虽然读写的速度非常快,但是在删除一个有成千上万个成员的key时时间就会下降了,这个时候其他客户端是被阻塞的状态,如果频繁出现这种情况那对整个服务来说还是十分恐怖的性能影响,所以引入了异步删除,当然我们得使用对应的异步删除命令如下对比:

删除操作 同步/异步 阻塞情况 适用场景 命令示例
DEL 同步阻塞 阻塞当前客户端 小数据量,立即需要结果 DEL key
UNLINK 异步非阻塞 不阻塞当前客户端 大数据量,性能敏感 UNLINK key
FLUSHDB async 异步非阻塞 不阻塞当前客户端 清空整个数据库 FLUSHDB ASYNC
FLUSHDB 同步阻塞 阻塞所有客户端 需要立即结果的小数据库 FLUSHDB
FLUSHALL async 异步非阻塞 不阻塞当前客户端 清空所有数据库 FLUSHALL ASYNC

redis性能瓶颈之网络IO

我们都知道redis的主要性能瓶颈就是内存和网络,内存我们可以增加redis的配置来使用更多的内存,而网络呢?这个我们不能单纯的改配置就行了,这个需要改架构,也就是redis6引出的多网络IO线程,之前的版本一个线程IO处理多个客户端网络请求,那么越多的客户端这个网络IO的线程压力是不是就越大?但是再大一个线程也只能吃我们网络硬件的一部分性能,也就是一个网络IO无法充分榨干网络硬件的性能。所以提出了多线程网络IO,用多线程来解决不断激增的客户端网络请求,这样redis的网络瓶颈就被打破了,真正做到了机器有多好性能就有多好的性能。但是我们redis的读写还是单线程的,只是处理网络请求变成了多线程IO,既解决了网络瓶颈的问题,也不用考虑读写的事务、锁竞争的问题。

那这个网络IO是干什么的?单线程和多线程有什么区别?

首先这个网络IO就是解析客户端连接的信息、命令的,只有把客户端的socket连接解析正确了,才能知道这个客户端在哪里、要干什么,之前单线程的就是并发执行的,也就是A解析比如10毫秒,B连接解析10毫秒,不停的切换,只有解析好了主线程也就是我们的读写线程才能通过多路复用epoll的方式去处理客户端的请求,那假如这个IO线程要解析的东西太多了,是不是就没办法最快把所有客户端的请求解析完,那么这个时候的主线程是不是没办法最大功率执行,因为在你主线程执行完了上一个客户请求,下一个用户请求还没解析完。另外如果像之前一个网络IO,主线程执行完需要把数据返回客户端,也是需要网络IO进行解析的,那这个时候网络IO又要解析连接又要打包返回数据,实在是有点太忙了。所以多网络IO就解决了这个问题,一个人解析肯定比多人干活要慢的,这不就解决了这个问题吗。

redis单线程和多线程的执行流程?

单线程模式:用户发来连接请求,主线程监听到了马上让网络IO去解析,解析完成后执行命令,主线程执行命令,然后通知网络IO打包数据返回客户端。如果客户端请求过多就会堵塞,因为读和写本事就是阻塞的。

多线程模式:100个用户发来连接请求,主线程监听到了使用多路复用epoll将这些请求全部外包给多线程网络IO解析,然后主线程继续监听,只要监听到网络IO解析完成,主线程马上执行命令,执行完成后主线程又通过多路复用把需要打包的数据外包给了网络IO去执行,他继续接待其他请求的命令。

注意点:多路复用和非阻塞IO(网络IO)redis一直都是这个架构,只是redis6推出了网络IO多线程。另外redis6/7都是默认关闭网络IO多线程的,如果要使用需要去配置文件中修改。

总结

本篇主要讲的就是redis多线程和单线程之间的区别。

相关推荐
YOU OU4 小时前
Redis基础常识与命令
数据库·redis·缓存
腻害兔4 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社5 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
萧瑟余晖6 小时前
JDK 26 新特性详解
java·开发语言
Database_Cool_6 小时前
OLTP 和 OLAP 区别详解:分析型数据库和事务型数据库怎么选(附阿里云 AnalyticDB MySQL 选型指南)
数据库·mysql·阿里云
爱写代码的阿森6 小时前
鸿蒙三方库 | harmony-utils之KvUtil键值型数据库操作详解
数据库·华为·harmonyos·鸿蒙·huawei
马优晨6 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
Database_Cool_7 小时前
单机 MySQL 迁移到分布式数据库方便吗?阿里云 PolarDB-X 100% MySQL 协议兼容零改造平滑迁移
数据库·分布式·mysql
姜太小白7 小时前
【MySQL】 索引优化实战:解决 WHERE 等值 + IS NULL 查询,TEXT 字段报错 1167 的完整指南
数据库·mysql