网站优化关键词排名怎么做,网站自然优化,二手车网站的建设,wdcp备份网站大家好#xff0c;我是大明哥#xff0c;一个专注「死磕 Java」系列创作的硬核程序员。 本文已收录到我的技术网站#xff1a;https://www.skjava.com。有全网最优质的系列文章、Java 全栈技术文档以及大厂完整面经 Redis 的线程模型其实是分两块的#xff1a;
Redis 6.0 … 大家好我是大明哥一个专注「死磕 Java」系列创作的硬核程序员。 本文已收录到我的技术网站https://www.skjava.com。有全网最优质的系列文章、Java 全栈技术文档以及大厂完整面经 Redis 的线程模型其实是分两块的
Redis 6.0 之前的单线程模型。其实从 4.0 开始Redis 并不是严格意义上的单线程模型因为 Redis 除了主线程外也有一些后台的线程或者子进程在处理任务例如清理脏数据、生成快照、AOF 重写这个时候大家所说的单线程应该是 Redis 的主线程模型。Redis 6.0 之后的多线程模型。Redis 在 6.0 之后引入了一种多线程模型用于处理网络 I/O 的任务。
所以你的回答要涉及这两个方面。
Redis 的单线程是指Redis 在执行一次命令时是单线程的。其过程包括「接收客户端请求 - 解析请求 -数据读写等操作-返回结果给客户端」这个过程是由一个主线程来完成的这也是我们常说 Redis 是单线程的原因。Redis 的模型是基于单线程事件驱动模型内部使用文件事件处理器而这个文件事件处理是单线程的也就决定了 Redis 是单线程的。其核心原理是采用 IO多路复用机制同时监听多个 socket将产生事件的 socket 压入内存队列中事件分派器根据 socket 上的事件类型来选择对应的事件处理器进行处理。随着底层网络硬件越来越好Redis 的性能瓶颈逐渐体现在网络 I/O 的读写上单个线程处理网络 I/O 读写的速度跟不上底层网络硬件执行的速度。所以为了提高 Redis 的性能在 Redis 6.0 引入多线程模型该多线程模型只用来处理网络数据的读写和协议解析执行读写命令的仍然是单线程。
Redis 线程模型详解
Redis 的单线程模型
Redis 的单线程是指Redis 在执行一次命令时是单线程的。Redis 客户端与服务端的模型可以简化如下图 步骤2 执行命令为单线程其过程包括「接收客户端请求 - 解析请求 -数据读写等操作-返回结果给客户端」这个过程是由一个主线程来完成的这也是我们常说 Redis 是单线程的原因。
从 Redis 的内部设计来说Redis 是基于 Reactor 模式开发了自己的网络事件处理器这个处理器称之为文件事件处理器而这个文件事件处理器是单线程的这就决定了 Redis 是单线程的。文件事件处理器包含 5 个部分
多个 socketRedis 网络通信的起点Redis 服务器为每个连接的客户端维护一个套接字用于接收请求和发送响应。IO 多路复用程序文件事件处理器的核心。它负责监控所有套接字并确定哪些套接字准备好进行读写操作。任务队列处理的任务的队列。文件事件分派器当 I/O 多路复用程序确定某个套接字准备好读写时文件事件分派器负责将这个事件分派给相应的事件处理器。事件处理器Redis 对不同类型的文件事件定义了相应的事件处理器。当特定类型的事件发生时对应的事件处理器会被触发以处理这些事件。
多个 socket 会产生不同的操作每个操作对应一个不同的文件事件 IO 多路复用程序会监听多个 socket将产生的事件放入到任务队列中排队文件事件分派器每次从任务队列中获取一个事件将其转发给对应的事件处理器进行处理。如下 客户端与 Redis 服务端建立连接的过程 Redis sever 启动时会把 AE_READABLE 事件与连接应答处理器关联。当客户端向 Redis 发起连接时这是 Server Socket 会产生一个 AE_READABLE 事件IO 多路复用程序监听到该事件后将 socket信息压入到任务队列中。文件事件分派器每次从任务队列中取一个 socket 将其交给事件处理器由于在 Redis 初始化时 AE_READABLE 是与连接应答处理器关联所以就由连接应答处理器来处理该事件。连接应答处理器会创建一个与该客户端通信的 Socket我们这里叫 socket1并将 socket1 的 AE_READABLE 事件与命令请求处理器关联。 客户端发送请求给 Redis 服务端过程 客户端发送读写请求比如 set key value给服务端首先会在对应的 Socketsocket1上面产生一个 AE_READABLE事件IO 多路复用程序监听到该事件后将 socket信息压入到任务队列中。文件事件分派器从任务队列中取 Socket 信息转发给事件处理器由于建立连接时 socket1 的 AE_READABLE 事件已经与命令请求处理器关联了所以文件事件分派器将命令请求处理器。命令处理器读取该 Socket 的相关信息后执行相关命令操作完成后会将 socket01 的 AE_WRITABLE 事件与命令回复处理器关联。 如果客户端已经准备好了接收结果那么 socket1 会产生一个 AE_WRITABLEIO 多路复用程序将 Socket 压入队列然后由文件事件派发器转发给事件处理器。由于 socket1 的AE_WRITABLE 事件与命令回复处理器关联所以由命令回复处理器处理命令回复处理器将准备好的相应数据写入socket01(socket连接是双向的)返回给客户端之后解除 socket01 的 AE_WRITABLE 事件与命令回复处理器的关联。 Redis 的 I/O 多线程模型
我们 Redis 是基于内存操作内存的响应时长大约为 100 纳秒单线程的 Redis 处理数据的极限是 80,000 到 100,000 QPS对于绝大多数的场景来说单线程的 Redis 其实是已经够用了。
但是随着底层网络硬件越来越好Redis 的性能瓶颈逐渐体现在 I/O 的读写上CPU 从来都不是 Redis 的性能瓶颈单个线程处理网络 I/O 读写的速度跟不上底层网络硬件执行的速度。所以为了提高 Redis 的整体性能在 6.0 引入多线程注意引入的多线程模型只⽤来处理处理网络数据的读写和协议解析对于 Redis 的读写命令依然是单线程处理。 Redis 6.0 引入 I/O 多线程模型后将一个命令的执行分为了两部分
Socket 读写和请求解析使用多线程处理多个 socket 读写可以并⾏化执行请求依然还是使用主线程存内存操作在高效的同时也保证了安全性。
主要流程如下
主线程负责接收并建立多个连接请求获取 socket 后放入全局等待处理队列主线程处理完这些事件之后通过RRRound Robin 轮询将可读 socket 分配给这些 IO 线程主线程阻塞等待 IO 线程完成命令的读取、解析主线程执⾏ IO 线程读取和解析出来的 Redis 请求命令并将结果写到输出缓冲区主线程阻塞等待 IO 线程将命令执⾏结果写回 socket客户端主线程执行所有命令并清空整个等待队列等待客户端后续的请求队列。
如下图