Redis为什么使用单进程单线程还这么快

Redis为什么这么快

单进程单线程

Redis采用的是基于内存的单进程单线程模型的 KV 数据库由C语言编写。 对读写等事件的响应是通过对epoll函数的包装来做到的。Redis的实际处理速度完全依靠主进程的执行效率。因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。

  1. 操作的瓶颈在于网络的I/O,I/O操作的步骤分为:

    • 数据通过网关到达内核,内核准备好数据
    • 数据从内核缓存缓存写入到用户程序数据
  2. 单进程单线程的优势:

    • 避免上下文的切换:上下文其实不难理解,它就是CPU寄存器和程序计数器。主要的作用就是存放没有被分配到资源的线程,多线程操作的时候,不是每一个线程都能够直接获取到CPU资源的,我们之所以能够看到我们电脑上能够运行很多的程序,是应为多线程的执行和CPU不断对多线程的切换。但是总有线程获取到资源,也总有线程需要等待获取资源,这个时候,等待获取资源的线程就需要被挂起,也就是我们的寄存。这个时候我们的上下文就产生了,当我们的上下文再次被唤起,得到资源的时候,就是我们上下文的切换。
    • 避免竞争资源:竞争资源相对来说比较好理解,CPU对上下文的切换其实就是一种资源分批,但是在切换之前,到底切换到哪一个上下文,就是资源竞争的开始。在Redis中由于是单线程的,所以所有的操作都不会涉及到资源的竞争。
    • 避免锁的消耗:对于多线程的情况来讲,不能回避的就是锁的问题。如果说多线程操作出现并发,有可能导致数据不一致,或者操作达不到预期的效果。这个时候我们就需要锁来解决这些问题。当我们的线程很多的时候,就需要不断的加锁,释放锁,该操作就会消耗掉我们很多的时间。
Redis为什么这么快
  • 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

  • 数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

  • 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

  • 使用多路I/O复用模型,非阻塞IO;

  • 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

多路 I/O 复用模型

对于I/O阻塞可能有很多人不知道,I/O操作的阻塞到底是怎么引起的,Redis又是怎么解决的呢?

  • I/O操作的阻塞:当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除block状态。

多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。

**这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。**采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。

总结

Reids之所以单线程还如此之快的原因就是因为内部采用了I/O多路复用机制模型,但是这种机制不是什么情况下都是使用的,应用于大量的链接,处理时间又不是很长的业务,连接数最好是大于1000,并发程度不高或者局域网环境下NIO并没有显著的性能优势。

下一篇:Redis的持久化——RDB与AOF对比

发布了54 篇原创文章 · 获赞 11 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/dong_W_/article/details/105170381