3. 高性能IO模型,探究Redis单线程为何很快

1. Redis单线程

  • 通常说Redis单线程是指Redis的网络IO和键值对读写是由一个线程完成的
但Redis的其他功能,比如持久化,异步删除,集群数据同步等都是由额外的线程完成的

2. 为什么Redis使用单线程


2.1 多线程的开销

  • 问题:
    • 通常情况,假如没有良好的设计,在刚开始增加线程数时,吞吐率会有所增加,但进一步增加线程时,吞吐率就会增长迟缓甚至会出现下降情况
  • 原因:
    • 系统中常会存在被多线程同时访问的共享资源,比如一个共享的数据结构,当多个线程要修改共享资源时,就要有额外的机制来保证共享资源准确性,就会带来额外的开销
    • 比如,redis中的lpush和lpop操作,假如两个线程同时对list分别做lpush和lpop操作,就会遇到这个问题
  • 问题就是多线程编程面临的共享资源的并发访问控制问题

2.2 其他原因

  • 多线程开发一般会引入同步原语来保护共享资源并发访问,会降低系统的调试和维护性

3. 为什么那么快

  • 大部分操作内存中完成
  • 高效的数据结构设计(如哈希表和跳表)
  • 采用多路复用机制

4. 基本IO模型和阻塞点

4.1 SimpleKV处理GET请求,IO示例如下图,依次执行如下操作:

3. 高性能IO模型,探究Redis单线程为何很快_第1张图片
Redis基本IO模型
  • 潜在阻塞点如下:
    • accept()
      • 当 Redis 监听到一个客户端有连接请求,但一直未能成功建立起连接时,会阻塞在 accept() 函数这里,导致其他客户端无法和 Redis 建立连接
    • recv()
      • 当 Redis 通过 recv() 从一个客户端读取数据时,如果数据一直没有到达,Redis 也会一直阻塞在 recv()。

4.2 socket的非阻塞模式

socket 模型,不同操作调用后会返回不同的套接字类型。
3. 高性能IO模型,探究Redis单线程为何很快_第2张图片
image.png
    1. socket() 方法会返回主动套接字,
    1. 调用 listen() 方法,将主动套接字转化为监听套接字,此时,可以监听来自客户端的连接请求。
    1. 调用 accept() 方法接收到达的客户端连接,并返回已连接套接字。
1. 针对监听套接字,可以设置非阻塞模式:当Redis调用accept()但一直未有连接请求到达时,Redis线程可以返回处理其他操作,不用一直等待。但调用accept()时,已经存在监听套接字了
2. 同理,也可以对已连接套接字设置非阻塞模式,如数据没有到达,可以返回处理其他操作
3. 问题:需要有机制,在监听套接字等待后续连接(有请求时通知Redis),继续监听已连接套接字,在有数据到达时通知Redis

Redis机制:基于多路复用的高性能I/O模型

引言:

  • linux中IO多路复用:指一个线程处理多个IO流,也就是select/epoll机制
  • Redis中:在一个内核中,同时存在多个监听套接字和已连接套接字。内核会一直监听这些套接字上的连接请求或数据请求。有请求到达,就交给redis线程处理

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

3. 高性能IO模型,探究Redis单线程为何很快_第3张图片
Redis高性能IO模型
    1. 图中的多个FD指多个套接字。Redis网络框架调用epoll机制,让内核监听这些套接字。这样,Redis线程不会阻塞在某个特定的监听或已连接套接字(不会阻塞在某一个特定的客户端请求处理)。所以,Redis可以同时和多个客户端连接并处理请求,提升并发性
    1. 为了在请求到达时通知到Redis,select/epoll提供了基于事件的回调机制(针对不同事件发生,调用相应处理函数)

回调机制

  • select/epoll一旦监测到FD上有请求,出发相应事件将事件放进一个队列,Redis单线程对该事件队列不断进行处理
  • 以连接请求和读数据请求为例:
    • 两个请求分别对应Accept事件和Read事件,Redis分别对这两个事件注册accept和get回调函数。当linux内核监听到有连接请求或读数据请求时,就会触发Accept事件和Read事件,此时,内核就会回调Redis相应的accept和get函数进行处理

总结:

  • Redis单线程是指它对网络IO和数据读写的操作采用了一个单线程,核心原因是避免多线程开发的并发控制问题
  • Redis单线程获得高性能的原因在:
    • 多路复用的IO模型:避免了accept()和send()/recv()潜在的网络IO操作点

你可能感兴趣的:(3. 高性能IO模型,探究Redis单线程为何很快)