🗒️Redis 中单线程的理解
2024-8-1
| 2024-9-7
0  |  阅读时长 0 分钟
type
status
date
slug
summary
tags
category
icon
password
notion image
一次完整的 Redis 操作包括以下步骤:
  1. 创建套接字:使用 socket()函数创建一个新的套接字。──socket()函数返回主动套接字
  1. 绑定地址:使用 bind() 函数将该套接子绑定到特定 IP 地址和端口号上。──bind() 函数返回监听套接字
  1. 监听连接请求:使用 listen() 函数使得该套接子进入监听状态,等待客户端发起连接请求。
  1. 接受连接请:使用 accept() 函数从队列中取出第一个客户机连接请求,并返回一个新的已建立连接的套接字, 用于后续与客户端通信。原来的监听用的那个套接字回到 listen 状态,等待其他客户机发来连接请求。(注意:监听套接字相当于引路人,不用作通信。当你连接建立完成,关闭监听套接字,还是可以通信的。)──accept() 函数返回已连接套接字(新套接字)
  1. 发送/接受数据:通过新建的已建立链接上的套接字和客户端进行双向的数据收发操作,可以调用send() , recv()。下面补充 Redis 线程中的操作:
    1. 从客户端请求中读取数据(recv
    2. 解析客户端的请求(parse
    3. *根据请求类型读取键值数据(get)──数据读写(Redis 本身的功能)
    4. 客户端返回结果,即向套接字中写回数据(send
  1. 关闭套接字,清理资源
从上面的步骤中,我们发现,如果 Redis 按照上述的流程中,效率并不会很高。原因是 Redis 是单线程,上面的流程,Redis 需要一口气走完,但是在 acceptrecv 出现问题(连接建立出现问题、数据传输出现问题),Redis 会一直阻塞在这里。(主:在实际生产中,不是每来一个连接就重新建立连接,而是长连接)
幸运的是,socket 网络模型支持非阻塞模式。当调用 accept() 但一直未有连接请求到达时,可以返回处理其他操作,而不用一直等待。调用 send()/recv() 并且操作不能立即完成,可以返回处理其他操作。但是,我们还需要在他们完成的时候,通知当前线程一声,可以继续处理了。到此,Linux 中的 IO 多路复用机制就要登场了。
Linux 中的 IO 多路复用机制是指一个线程处理多个 IO 流,就是我们经常听到的 select/epoll 机制。 为了在请求到达时能通知到当前线程,select/epoll 提供了基于事件的回调机制,即针对不同事件的发生,调用相应的处理函数。如下图所示:
notion image
资料都说:Redis 中单线程是指它在网络 I/O 和数据读写操作采用一个线程。而在 Redis 的网络 I/O (网络通信编程中)是基于操作系统内核实现的多路复用机制,例如在 Linux 系统下是 selectepoll 实现。我的理解是 Redis 的单线程仅仅是指执行命令的时候是单线程。IO 模型是 OS 的 IO 模型,Redis 只是使用多路复用技术,由系统负责监听客户端的连接等,通知 Redis 的工作线程。
补充:Redis 6.0 引入了多线程来处理网络 I/O 操作,以提高其处理网络 I/O 的性能。具体来说,多线程主要用于读取客户端请求、解析协议以及发送响应等耗时较长的操作,而实际的数据操作仍然是在主线程中完成(执行 Redis 命令) 。而在 Redis 6.0 之前,Redis 是单线程运行的,这意味着所有操作都是由一个主线程完成,在高并发场景下,网络的 I/O 可能成为性能瓶颈。

📎 参考

  ‍
  
  • Redis
  • redis 中 ZSet的范围查询的时间复杂度是多少EM 算法
    Loading...
    目录