Redis是一个使用ANSI C编写的开源、支持网络、基于内存分布式、可选持久性键值对存储数据库。凭借强大的性能和丰富的API,成为目前最流行的键值对存储数据库,Redis也成为了目前后端必备的技术之一。本文通过多个维度分析了Redis快的原因。

Redis 为什么快

面试中常见的一个问题就是 Redis为什么快? 我认为主要有以下几点:

  1. Redis 使用内存存储数据,避免了磁盘IO的开销。

    内存访问速度是纳秒级(10的-9次方),硬盘的访问速度是微秒级(10的-3次方)。

  2. 极致优化的数据结构:Redis 有诸如可以直接应用的优化数据结构的实现,应用层可以直接使用原生的数据结构提升性能。

    比如对字符串,Redis实现了自己的 SDS 字符串,相比于C++ 的字符串,获取字符串的长度操作的复杂度为 O(1)

  3. Redis 的工作线程是一个单线程应用,避免了 多线程之前线程切换锁资源竞争的开销。

    引申: 线程上下文切换具体指什么 (保存、恢复栈上的信息,寄存器上的信息)

  4. 非阻塞式IO: Redis 使用IO多路复用技术,在 poll、epoll、kqueue 选择最优IO实现。

    Redis 开发了自己的网络事件处理器(file event handler),程序在编译时会自动选择系统中性能最高的 I/O 多路复用函数库来作为 RedisI/O

    多路复用程序的底层实现。

纯内存数据操作

极致优化的数据结构

工作线程单线程

​ 很多人可以很不理解,在当前多核 CPU 如此强大的今天,为何单线程反而能让Redis更快。Redis 官方其实给了我们回答,一般情况下,在普通 Linux 系统上使用单线程 Redis 每秒甚至可以处理 100万 个请求,Redis 主要使用 O(N)O(log(N)) 的操作命令,所以几乎不会使用太多 CPU , CPU 一般不会成为 Redis 的瓶颈 , Redis 的瓶颈主要在于内存网络

​ 官方提到的 Redis 主要使用 O(N)O(log(N)) 的操作命令,说的其实是Redis 的命令简单且高效,单条命令执行速度极快,这离不开上面提到的数据结构等方面的优化,比如获取 SDS 字符串这个命令的复杂度仅为O(1)。如果工作线程使用多线程,那么不可避免的得处理并发问题(``锁机制等),处理多线程的上下文切换问题,这些不仅会增加Redis` 命令的操作复杂度,而且会带来额外的开销,得不偿失。

I/O 多路复用

img

参考资料

Q.E.D.