Redis学习(单线程vs多线程)(10.28)
版本
-
版本3.x,最早版本,单线程
-
版本4.x,处理客户端请求单线程,异步删除多线程
-
版本6.0.x,7.0,多线程
所谓“单线程”
网络io和键值对读写由一个线程完成
处理客户端请求(主线程:顺序串行):获取,解析,执行,内容返回
额外线程执行:持久化RDB,AOF,异步删除,集群数据共享
Redis命令工作线程单线程,整个Redis多线程
版本3.x单线程时代性能快
-
基于内存操作:数据存在内存,所有运算内存级别
-
数据结构简单:查找和操作时间大部分复杂度o(1)
-
多路复用和非阻塞io:i/o多路复用功能来监听多个socket连接客户端,使用一个线程来处理多个请求,减少线程切换带来的开销,避免了i/o阻塞
-
避免上下文切换:单线程模型,不会导致死锁
扫描二维码关注公众号,回复: 17480894 查看本文章
版本4.0之前一直采用单线程
-
开发维护简单
-
单线程模型也可并发处理多客户端请求,采用io多路复用和非阻塞io
-
主要性能瓶颈为内存或网络带宽而非cpu
多线程特性出现
-
大key问题
-
del bigkey一直阻塞,导致主线程卡顿
-
-
引入惰性删除避免卡顿
-
解决删除效率低
-
删除操作从主线程剥离BIO子线程处理,提高性能稳定性
-
狭义单线程:引入多线程实现异步惰性删除,处理读写请求的任然只有一个线程
Redis6/7真正多线程
单线程处理网络请求的速度跟不上底层网络硬件的速度
采用多个io线程来处理网络请求,提高网络请求的并行度
Redis只是将i/o读写变成了多线程,而命令的执行依旧由主线程串行执行
主线程与io线程的四个阶段
-
服务端和客户端建立Socket连接,并分配处理线程
-
主线程负责接收建立连接请求
-
将Socket放入全局等待队列
-
主线程通过轮询分配给io线程
-
-
io线程读取并解析请求
-
阻塞状态,等待io线程完成对客户端请求读取和解析(多io线程并行处理)
-
-
主线程执行请求操作
-
io线程解析完毕,主程序执行
-
-
io线程回写Socket和主线程清空全局队列
-
返回结果入缓冲区
-
等待io线程写回Socket(多io线程并行处理)
-
主线程清空全局队列
-
io读和写本身就是堵塞的,Socket中有数据时,Redis通过调用先将数据从内核态空间拷贝到用户态空间,再交给Redis调用,这个拷贝的过程就是堵塞的,数据量越大,拷贝需要的时间越多,这些操作基于单线程完成
版本6开始,新增多线程功能提高io的读写性能,将主进程的io读写任务(Socket读取,请求解析,写入)拆分给一组独立的线程去执行,使多个Socket的读写并行化,采用多路复用技术让单个线程高效处理多个连接请求(尽量减少网络io的时间消耗)。
Redis为什么这么快
直接原因:io多路复用+epoll函数使用
肤浅原因:单线程命令+redis安装在内存
在单机模式下,可以开启多线程,在其他模式下,最好不要开启