redis为啥那么快?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28165595/article/details/81637288

前言

现在是内存数据库大行其道的时候,无论是redis还是Memcached 。在处理大数据量高并发请求的时候,他们的优异性能是传统关系型数据库无法比拟的。内存数据库在快速响应的上独领风骚。但是也并不是说,关系型数据即将淘汰。如果将redis作为一个持久化数据库来使用想必也是不合适的。我们都知道redis的响应很快,但是是什么支撑着redis在面对大流量请求时能够从容不迫呢?

为何redis选择单进程单线程模式呢?

redis 作为一个内存数据库,内存操作是很快的。网络 io 是瓶颈,如果用多线程,还要引起线程切换,线程切换的开销是很大的,切换线程之后要保留现场,要做很多预处理。所以用单线程反而能起到更好的作用。下面简单具体列举几点redis选择单线程的原因

  • 都是通过网络来调用 redis 的,如果是内网调用情况稍微比外网调用好点。但是这些和内存操作的时间不是一个量级的。用单线程处理完全能应付。
  • redis 是采用单线程 - 多路复用 IO 模型来实现高性能内存数据服务的。这样就避免了使用锁。网络层利用 IO 多路复用,这使用了内核级别的线程池,就是说还是存在并发的,只是在网络层的并发。但是网络 Io 本身是很慢的。是瓶颈。那么你在业务处理阶段设计再多的线程,使用再多的 cpu 内核,也没法逾越网络 Io 的瓶颈。
  • redis 和传统的多线程服务器不同。比如 tomcat 这些,后端往往存在很重的 IO 操作,会产生长时间的等待。所以采用多线程是有必要的。

这里我们一直在强调的单线程,只是在处理我们的网络请求的时候只有一个线程来处理,一个正式的Redis Server运行的时候肯定是不止一个线程的,这里需要大家明确的注意一下!

你都单线程了为啥还这么快?

1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
4、使用多路I/O复用模型,非阻塞IO;
5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

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

这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。
和 Memcached 不同,Redis 并没有直接使用 Libevent,而是自己完成了一个非常轻量级的对 select、epoll、evport、kqueue 这些通用的接口的实现。在不同的系统调用选用适合的接口,linux 下默认是 epoll。因为 Libevent 比较重,更通用,代码量也就很庞大,拥有很多 Redis 用不上的功能,Redis 为了追求“轻巧”并且去除依赖,就选择自己去封装了一套。
上面的对于多路复用讲的太绕口了,要想深入了解可以看看这篇文章,用小例子形象的描述BIO,NIO,AIO的区别。比较着去学习才会印象深刻。
白话BIO,NIO,AIO

参考文献

Redis 为什么使用单进程单线程方式也这么快
redis为什么要设计成单线程
为什么说Redis是单线程的以及Redis为什么这么快!

猜你喜欢

转载自blog.csdn.net/qq_28165595/article/details/81637288