美文网首页
3. 高性能IO模型,探究Redis单线程为何很快

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

作者: one_8274 | 来源:发表于2020-09-27 00:20 被阅读0次

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示例如下图,依次执行如下操作:

Redis基本IO模型
  • 潜在阻塞点如下:
    • accept()
      • 当 Redis 监听到一个客户端有连接请求,但一直未能成功建立起连接时,会阻塞在 accept() 函数这里,导致其他客户端无法和 Redis 建立连接
    • recv()
      • 当 Redis 通过 recv() 从一个客户端读取数据时,如果数据一直没有到达,Redis 也会一直阻塞在 recv()。

4.2 socket的非阻塞模式

socket 模型,不同操作调用后会返回不同的套接字类型。
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模型

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单线程为何很快

    1. Redis单线程 通常说Redis单线程是指Redis的网络IO和键值对读写是由一个线程完成的 2. 为什么...

  • Redis学习之旅~原理篇

    内容依旧来自 核心原理 线程IO模型 单线程非阻塞IO redis是单线程模型。redis的...

  • 要记得

    redis 1,redis是一个单线程的高性能缓存数据库,redis底层采用网络io的多路复用(事件驱动模型)来监...

  • Redis的事件模型(文件描述符号&polling 机制 基础)

    Redis的高性能和他的事件模型是密不可分的,最大程度上利用了单线程、非阻塞IO模型来快速的处理请求(单线程处理多...

  • Redis高级应用总结

    Redis的线程模型 Redis是单进程单线程的,但是使用的是单线程非阻塞的多路IO复用的模型。多线程模型会导致线...

  • redis-io-nio

    redis-io模型 单线程的程序有哪些? nginx node.js redis 单线程为什么快 全是内存运...

  • 2020-06-24

    redis IO模型 学习方法 应该从对比的角度去分析其特性; 本篇博客主要针对redis的单线程模型,epoll...

  • Redis单线程

    目录 理解Redis也会有多个线程Redis单线程处理事件Redis高性能基于内存+多路复用I/O模型 优势避免引...

  • Redis单线程为什么快?

    Redis使用了单线程和I/O多路复用模型来实现高性能的内存数据库服务器。 1 Redis单线程为什么那么快? (...

  • 一篇文章完全理解Redis为什么这么快

    单线程架构 Redis使用了单线程架构和I/O多路复用模型来实现高性能的内存数据库. 为什么单线程还能这么快? 纯...

网友评论

      本文标题:3. 高性能IO模型,探究Redis单线程为何很快

      本文链接:https://www.haomeiwen.com/subject/bntkuktx.html