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.