您的位置:首页 > 数据库 > Redis

redis面试突击专题--2.redis的线程模型?为什么redis单线程还能有很高的效率?

2020-01-13 14:41 267 查看

声明:
1.这是根据网上的一些视频资料等总结的,而且只是面试突击,讲的不是很复杂。第一次写博客,后续也会写其他的东西。诸如《redis设计与实现》的读书笔记等,继续深入相关技术。
2. 这同时也是我自己的一个整理笔记吧,想看后续笔记的可以关注我哦。

本文目录

  • 2. 面试题解析
  • 1. 面试场景

    1.1 面试题

    1.redis和memcached有什么区别?
    2.redis的线程模型是什么?
    3.为什么单线程的redis比多线程的memcached效率要高得多?
    4.为什么redis是单线程的但是还可以支撑高并发?

    1.2 面试官心理

    这个是问redis的时候,最基本的问题吧,redis最基本的一个内部原理和特点,就是redis实际上是个单线程工作模型,你要是这个都不知道,那后面玩儿redis的时候,出了问题岂不是什么都不知道?

    2. 面试题解析

    2.2.4有图,建议跟着图一起看,比较容易理解

    2.1 redis和memcached有啥区别

    这个事儿吧,你可以比较出N多个区别来,但是我还是采取redis作者给出的几个比较吧

    1. Redis支持服务器端的数据操作:
    Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。

    2. 性能对比:
    由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色

    3. 集群模式:
    memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据;但是redis目前是原生支持cluster模式的,redis官方就是支持redis cluster集群模式的,比memcached来说要更好

    2.2 redis的线程模型

    2.2.1 文件事件处理器

    1. redis基于reactor模式开发了网络事件处理器,这个处理器叫做文件事件处理器,file event handler。这个文件事件处理器,是单线程的,redis才叫做单线程的模型,采用IO多路复用机制同时监听多个socket,根据socket上的事件来选择对应的事件处理器来处理这个事件。

    2. 如果被监听的socket准备好执行accept、read、write、close等操作的时候,跟操作对应的文件事件就会产生,这个时候文件事件处理器就会调用之前关联好的事件处理器来处理这个事件。

    3. 文件事件处理器是单线程模式运行的,但是通过IO多路复用机制监听多个socket,可以实现高性能的网络通信模型,又可以跟内部其他单线程的模块进行对接,保证了redis内部的线程模型的简单性。

    4. 文件事件处理器的结构包含4个部分:多个socket,IO多路复用程序,文件事件分派器,事件处理器(命令请求处理器、命令回复处理器、连接应答处理器,等等)。

    5. 多个socket可能并发的产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序会监听多个socket,但是会将socket放入一个队列中排队,每次从队列中取出一个socket给事件分派器,事件分派器把socket给对应的事件处理器。

    6. 然后一个socket的事件处理完之后,IO多路复用程序才会将队列中的下一个socket给事件分派器。文件事件分派器会根据每个socket当前产生的事件,来选择对应的事件处理器来处理。redis基于reactor模式开发了网络事件处理器,这个处理器叫做文件事件处理器,file event handler。这个文件事件处理器,是单线程的,redis才叫做单线程的模型,采用IO多路复用机制同时监听多个socket,根据socket上的事件来选择对应的事件处理器来处理这个事件。

    7. 如果被监听的socket准备好执行accept、read、write、close等操作的时候,跟操作对应的文件事件就会产生,这个时候文件事件处理器就会调用之前关联好的事件处理器来处理这个事件。

    8. 文件事件处理器是单线程模式运行的,但是通过IO多路复用机制监听多个socket,可以实现高性能的网络通信模型,又可以跟内部其他单线程的模块进行对接,保证了redis内部的线程模型的简单性。

    9. 文件事件处理器的结构包含4个部分:多个socket,IO多路复用程序,文件事件分派器,事件处理器(命令请求处理器、命令回复处理器、连接应答处理器,等等)。

    10. 多个socket可能并发的产生不同的操作,每个操作对应不同的文件事件,但是IO多路复用程序会监听多个socket,但是会将socket放入一个队列中排队,每次从队列中取出一个socket给事件分派器,事件分派器把socket给对应的事件处理器。

    11. 然后一个socket的事件处理完之后,IO多路复用程序才会将队列中的下一个socket给事件分派器。文件事件分派器会根据每个socket当前产生的事件,来选择对应的事件处理器来处理。

    2.2.2 文件事件

    1. 当socket变得可读时(比如客户端对redis执行write操作,或者close操作),或者有新的可以应答的sccket出现时(客户端对redis执行connect操作),socket就会产生一个AE_READABLE事件。

    2. 当socket变得可写的时候(客户端对redis执行read操作),socket会产生一个AE_WRITABLE事件。

    3. IO多路复用程序可以同时监听AE_REABLE和AE_WRITABLE两种事件,要是一个socket同时产生了AE_READABLE和AE_WRITABLE两种事件,那么文件事件分派器优先处理AE_REABLE事件,然后才是AE_WRITABLE事件。

    2.2.3 文件事件处理器

    如果是客户端要连接redis,那么会为socket关联连接应答处理器
    如果是客户端要写数据到redis,那么会为socket关联命令请求处理器
    如果是客户端要从redis读数据,那么会为socket关联命令回复处理器

    2.2.4 客户端与redis通信的一次流程

    1. 在redis启动初始化的时候,redis会将连接应答处理器跟AE_READABLE事件关联起来,接着如果一个客户端跟redis发起连接,此时会产生一个AE_READABLE事件,然后由连接应答处理器来处理跟客户端建立连接,创建客户端对应的socket,同时将这个socket的AE_READABLE事件跟命令请求处理器关联起来。

    2. 当客户端向redis发起请求的时候(不管是读请求还是写请求,都一样),首先就会在socket产生一个AE_READABLE事件,然后由对应的命令请求处理器来处理。这个命令请求处理器就会从socket中读取请求相关数据,然后进行执行和处理。

    3. 接着redis这边准备好了给客户端的响应数据之后,就会将socket的AE_WRITABLE事件跟命令回复处理器关联起来,当客户端这边准备好读取响应数据时,就会在socket上产生一个AE_WRITABLE事件,会由对应的命令回复处理器来处理,就是将准备好的响应数据写入socket,供客户端来读取。

    4. 命令回复处理器写完之后,就会删除这个socket的AE_WRITABLE事件和命令回复处理器的关联关系。
    图1

    有人可能对Socket这块不太了解
    推荐一篇文章:Java的Socket网络编程

    2.2.5 为什么redis是单线程的但是还可以支撑高并发

    1. 纯内存操作

    1). 事件处理器都是基于纯内存操作的

    2. 核心是基于非阻塞的IO多路复用机制

    1). 客户端发来请求,图1中的IO多路复用程序只负责监听Socket和将Socket压入队列,并不处理请求,所以它的效率很高,可以同时监听几百个甚至几千个socket。
    IO多路复用详解

    3. 单线程反而避免了多线程的频繁上下文切换问题

    推荐一篇文章
    redis线程模型

    • 点赞
    • 收藏
    • 分享
    • 文章举报
    Youth_lql 发布了4 篇原创文章 · 获赞 0 · 访问量 79 私信 关注
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: