03 单线程Redis速度快的原因

Redis 是单线程,主要是指 Redis 的网络 IO 和键值对读写是由一个线程来完成的,这是 Redis 对外提供键值存储服务的主要流程。

但 Redis 的其他功能,比如持久化、异步删除、集群数据同步等,其实是由额外的线程执行的

Redis 使用单线程的原因

系统中通常会存在被多线程同时访问的共享资源,当有多个线程要修改这个共享资源时,为了保证共享资源的正确性,就需要有额外的机制进行保证,就会带来额外的开销。

并发访问控制是多线程开发中的一个难点,如果没有精细的设计,即使增加了线程,大部分线程也在等待获取访问共享资源的互斥锁并行变串行,系统吞吐率并没有随着线程的增加而增加避免多线程开发的并发控制问题,Redis 直接采用了单线程模式。


单线程 Redis 快的原因

  1. Redis 的大部分操作在内存上完成。
  2. 采用了高效的数据结构,例如哈希表和跳表。
  3. 采用了多路复用机制,使其在网络 IO 操作中能并发处理大量的客户端请求,实现高吞吐率。

基本IO模型和阻塞点

以 Get 请求为例,SimpleKV 为了处理一个 Get 请求,需要监听客户端请求(bind/listen),和客户端建立连接(accept),从 socket 中读取请求(recv),解析客户端发送请求(parse),根据请求类型读取键值数据(get),最后给客户端返回结果,即向 socket 中写回数据(send)。

Redis基本IO模型

在网络 IO 操作中,有潜在的阻塞点,分别是 accept() 和 recv()。

当 Redis 监听到客户端有连接请求,但一直未能成功建立起连接时,会阻塞在 accept() 函数,导致其他客户端无法和 Redis 建立连接。

当 Redis 通过 recv() 从一个客户端读取数据时,如果数据一直没有到达,Redis 也会一直阻塞在 recv()。

这导致 Redis 整个线程阻塞,无法处理其他客户端请求,效率很低。不过幸运的是,socket 网络模型本身支持非阻塞模式

非阻塞模式

Redis套接字类型与非阻塞设置
  • 针对监听套接字,可以设置非阻塞模式:当 Redis 调用 accept() 但一直未有连接请求到达时,Redis 线程可以返回处理其他操作,而不用一直等待。
  • 针对已连接套接字设置非阻塞模式:Redis 调用 recv() 后,如果已连接套接字上一直没有数据到达,Redis 线程同样可以返回处理其他操作。

基于多路复用的高性能I/O模型

在 Redis 只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字

内核会一直监听这些套接字上的连接请求或数据请求。一旦有请求到达,交给 Redis 线程处理,实现了一个 Redis 线程处理多个 IO 流的效果

基于多路复用的Redis高性能IO模型

图中的多个 FD 就是刚才所说的多个套接字。


:在“Redis 基本 IO 模型”图中,还有哪些潜在的性能瓶颈吗?

:在 Redis 基本 IO 模型中,主要是主线程在执行操作,任何耗时的操作,例如 bigkey、全量返回等操作,都是潜在的性能瓶颈。

posted @ 2024-02-20 15:41  zhyan0502  阅读(39)  评论(0编辑  收藏  举报