制作网站对话框,网站建设公司是什么,微信管理系统在哪里找,dede5.7微电影网站模板我们通常说#xff0c;Redis 是单线程#xff0c;主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的#xff0c;这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能#xff0c;比如持久化、异步删除、集群数据同步等#xff0c;其实是由额外的线…我们通常说Redis 是单线程主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的这也是 Redis 对外提供键值存储服务的主要流程。但 Redis 的其他功能比如持久化、异步删除、集群数据同步等其实是由额外的线程执行的。Redis 为什么用单线程多线程的开销对于一个多线程的系统来说在有合理的资源分配的情况下可以增加系统中处理请求操作的资源实体进而提升系统能够同时处理的请求数即吞吐率。线程数与系统吞吐率管理共享资源的开销多线程并发访问Redis采用多线程开发一般会引入同步原语来保护共享资源的并发访问这也会降低系统代码的易调试性和可维护性。为了避免这些问题Redis 直接采用了单线程模式。单线程 Redis 为什么那么快Redis 的大部分操作在内存上完成采用了高效的数据结构采用了多路复用机制使其在网络 IO 操作中能并发处理大量的客户端请求实现高吞吐率基本 IO 模型与阻塞点下图显示了这一过程其中bind/listen、accept、recv、parse 和 send 属于网络 IO 处理而 get 属于键值数据操作。既然 Redis 是单线程那么最基本的一种实现是在一个线程中依次执行上面说的这些操作。Redis基本IO模型在这里的网络 IO 操作中有潜在的阻塞点分别是 accept() 和 recv()。当 Redis 监听到一个客户端有连接请求但一直未能成功建立起连接时会阻塞在 accept() 函数这里导致其他客户端无法和 Redis 建立连接。类似的当 Redis 通过 recv() 从一个客户端读取数据时如果数据一直没有到达Redis 也会一直阻塞在 recv()。这就导致 Redis 整个线程阻塞无法处理其他客户端请求效率很低。不过幸运的是socket 网络模型本身支持非阻塞模式。非阻塞模式在 socket 模型中不同操作调用后会返回不同的套接字类型。socket() 方法会返回主动套接字然后调用 listen() 方法将主动套接字转化为监听套接字此时可以监听来自客户端的连接请求。最后调用 accept() 方法接收到达的客户端连接并返回已连接套接字。Redis套接字类型与非阻塞设置基于多路复用的高性能 I/O 模型Linux 中的 IO 多路复用机制是指一个线程处理多个 IO 流就是我们经常听到的 select/epoll 机制。简单来说在 Redis 只运行单线程的情况下该机制允许内核中同时存在多个监听套接字和已连接套接字。内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达就会交给 Redis 线程处理这就实现了一个 Redis 线程处理多个 IO 流的效果。下图就是基于多路复用的 Redis IO 模型。图中的多个 FD 就是刚才所说的多个套接字。Redis 网络框架调用 epoll 机制让内核监听这些套接字。此时Redis 线程不会阻塞在某一个特定的监听或已连接套接字上也就是说不会阻塞在某一个特定的客户端请求处理上。正因为此Redis 可以同时和多个客户端连接并处理请求从而提升并发性。基于多路复用的Redis高性能IO模型为了在请求到达时能通知到 Redis 线程select/epoll 提供了基于事件的回调机制即针对不同事件的发生调用相应的处理函数。这些事件会被放进一个事件队列Redis 单线程对该事件队列不断进行处理。这样一来Redis 无需一直轮询是否有请求实际发生这就可以避免造成 CPU 资源浪费。同时Redis 在对事件队列中的事件进行处理时会调用相应的处理函数这就实现了基于事件的回调。因为 Redis 一直在对事件队列进行处理所以能及时响应客户端请求提升 Redis 的响应性能。以连接请求和读数据请求为例具体解释一下:这两个请求分别对应 Accept 事件和 Read 事件Redis 分别对这两个事件注册 accept 和 get 回调函数。当 Linux 内核监听到有连接请求或读数据请求时就会触发 Accept 事件和 Read 事件此时内核就会回调 Redis 相应的 accept 和 get 函数进行处理。