redis 为什么快
- 最最最重要的原因——内存数据库。纯内存访问,所有数据都在内存中,所有的运算都是内存级别的运算,内存响应时间的时间为纳秒级别。因此 redis 进程的 cpu 基本不存在磁盘 I/O 等待时间、内存读写性能问题,CPU 不是 redis 的瓶颈(内存大小和网络I/O 才是 redis 的瓶颈,也就是客户端和服务端之间的网络传输延迟)
- 采用单线程模型,单线程实现简单。避免了多线程频繁上下文切换,以及同步机制加锁带来的开销。由于执行很快,对于上下文切换以及加锁带来的消耗相对占比就变得很大,所以不划算。
- 简单高效的基础数据结构:动态字符串(SDS),链表,字典,跳跃链表,整数集合、压缩列表、快表和listpack(一共8个数据结构)。然后 redis 在这个基础上去实现用户能操作的对象:字符串,列表,哈希,集合,有序集合等对象(一共5个对象)。
- reactor 模式的网络事件处理器。它使用了 I/O 多路复用去同时监控多个套接字,这是一种高效的I/O模型。reactor 相关知识可见Webserver专栏的#这篇文章.
为什么使用单线程
-
采用单线程,避免了不必要的上下文切换和竞争条件;不存在多线程导致的切换而消耗CPU
-
不用考虑各种锁的问题,不存在加锁和释放锁的的操作,没有因为可能出现的死锁而导致的性能消耗
-
简单可维护,多线程模式会使得程序的编写更加复杂和麻烦,单线程实现易实现
redis 是单线程系统?
我们常说 redis 单线程是指其网络事件处理模型 reactor 是单线程,实际上Redis确实是在主事件处理上使用了单线程,但是对于最新版本中持久化 以及 批量处理等操作时考虑使用了多线程的:
如果一次 client 请求会删除几百万 keys 值,那么这条命令可能会导致阻塞。在 redis 4.0 选择引入多线程来实现这一类非阻塞的命令
在 redis6.0 版本正式引入多线程去处理客户端的 I/O 读写响应,而 redis 命令事件的处理还是在主线程单线处理
假如是针对整个 redis 系统,则一直有其他线程去处理异步任务,如 AOF、RDB 的同步