Redis是一个使用ANSI C编写的开源、支持网络、基于内存、分布式、可选持久性的键值对存储数据库。凭借强大的性能和丰富的API,成为目前最流行的键值对存储数据库,Redis也成为了目前后端必备的技术之一。本文通过多个维度分析了Redis快的原因。
Redis 为什么快
面试中常见的一个问题就是 Redis为什么快? 我认为主要有以下几点:
-
Redis使用内存存储数据,避免了磁盘IO的开销。内存访问速度是纳秒级(10的-9次方),硬盘的访问速度是微秒级(10的-3次方)。
-
极致优化的数据结构:Redis 有诸如可以直接应用的优化数据结构的实现,应用层可以直接使用原生的数据结构提升性能。
比如对字符串,
Redis实现了自己的SDS字符串,相比于C++ 的字符串,获取字符串的长度操作的复杂度为O(1)。 -
Redis的工作线程是一个单线程应用,避免了多线程之前线程切换和锁资源竞争的开销。引申: 线程上下文切换具体指什么 (保存、恢复栈上的信息,寄存器上的信息)
-
非阻塞式IO: Redis 使用IO多路复用技术,在 poll、epoll、kqueue 选择最优IO实现。
Redis开发了自己的网络事件处理器(file event handler),程序在编译时会自动选择系统中性能最高的I/O多路复用函数库来作为Redis的I/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 多路复用
参考资料
- Redis IO FAQ
- 《Redis设计与实现》
Q.E.D.