通俗分析单线程的Redis为什么这么快

1、纯内存操作

Redis 绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,查找和操作的时间复杂度都是O(1)。

想了解下什么是时间复杂度O(1) ? 请点击这里。

拿笔记本电脑来说,假设主频是3.1G,也就是说每秒可以执行3.1*10^9个指令。所以说CPU看世界是非常非常慢的,内存比它慢百倍,磁盘比他慢百万倍。

 

 

2、单线程+多路IO复用机制

想了解下什么是多路复用以及多路复用常见的实现方式?请点击这里

单线程想要实现高性能,必须和多路IO复用机制结合在一起。因为单线程最怕的是什么?最怕的就是阻塞,以为所有的程序都是串行的,一个点堵住了,后面所有的程序执行都会成为问题。

举个形象的例子说下,就像是汽车行驶的单行道,中间有一辆车抛锚了,后面的车全都堵住了,根本过不去。

 

现在很多文章在分析为什么Redis单线程更快的时候,都要顺便踩一脚多线程的缺点,比如说上下分切换成本比较高。

但是我现在却感觉不能把多线程有如此的缺点才导致了Redis单线程的快,而是Redis单线程+多路IO复用这种黄金组合的存在已经使得Redis抗住大并发,实现了高性能,就没有必要再去用更复杂的多线程来实现。

用redis官方的回答就是:redis这种单线程+多路IO复用的方式实现的高性能,如果再想提高性能,CPU已经不是瓶颈。没有必要利用多线程榨干CPU来实现高性能。

所以,我们再分析Redis高性能的时候,可以专注于分析单线程+多路IO的强大作用。

想了解下多线程相对于单线程的劣势?请点击这里。

 

客户端与 redis 的一次通信过程:

 

 

  1. 客户端 socket01 向 redis 的 server socket 请求建立连接,此时 server socket 会产生一个 AE_READABLE 事件,IO 多路复用程序监听到 server socket 产生的事件后,将该事件压入队列中。
  2. 文件事件分派器从队列中获取该事件,交给连接应答处理器。连接应答处理器会创建一个能与客户端通信的 socket01,并将该 socket01 的 AE_READABLE 事件与命令请求处理器关联。
  3. 假设此时客户端发送了一个 set key value 请求,此时 redis 中的 socket01 会产生 AE_READABLE 事件,IO 多路复用程序将事件压入队列,此时事件分派器从队列中获取到该事件,由于前面 socket01 的 AE_READABLE 事件已经与命令请求处理器关联,因此事件分派器将事件交给命令请求处理器来处理。命令请求处理器读取 socket01 的 key value 并在自己内存中完成 key value 的设置。操作完成后,它会将 socket01 的 AE_WRITABLE 事件与命令回复处理器关联。
  4. 如果此时客户端准备好接收返回结果了,那么 redis 中的 socket01 会产生一个 AE_WRITABLE 事件,同样压入队列中,事件分派器找到相关联的命令回复处理器,由命令回复处理器对 socket01 输入本次操作的一个结果,比如 ok,之后解除 socket01 的 AE_WRITABLE 事件与命令回复处理器的关联。

这样便完成了一次通信。

 

备注:

  • AE_READABLE 事件 从字面就比较容易理解,这个直接告诉IO多路复用程序,我可以读了,赶紧来处理我吧
  • AE_WRITABLE 事件 从字面就比较容易理解,这个直接告诉IO多路服用程序,我可以写了,赶紧来处理我吧

 

子模块的选择:

众所周知,redis是可以安装在多个平台的,比如win,Mac,Linux等等。但是我们也已经知道,多路IO复用的实现在不同的系统下也是不一样的。那么redis怎么保证在不同的系统下都使用系统的多路复用功能?下面大概讲解下。

redis为不同的系统都的多路IO复用功能的实现都进行了接口的封装,然后最顶层给出了一个统一的接口。也就意味着,无论你在什么系统下,redis都可以自动切换接口来实现多路复用功能。下面我们通过源码说明下:

因为 select 函数是作为 POSIX 标准中的系统调用,在不同版本的操作系统上都会实现,所以将其作为保底方案。

#ifdef HAVE_EVPORT
#include "ae_evport.c"
#else
    #ifdef HAVE_EPOLL
    #include "ae_epoll.c"
    #else
        #ifdef HAVE_KQUEUE
        #include "ae_kqueue.c"
        #else
        #include "ae_select.c"
        #endif
    #endif
#endif

 

 

参考资料:

https://www.jianshu.com/p/68e949a5ef79

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值