我了解的Redis - 3. 为什么这么快?

March 21, 2019, 10:50 p.m.

大家都说 Redis 很快,可以用来实现分布式锁,还有分布式ID,Redis的官方给的压测数据是,大约7万到30万每秒的请求数,取决于操作的数据类型,数据量还有服务器硬件的配置等。官方测试数据

我们逐一看下快的原因吧

1. 采用 C 语言编写的

因为使用 C 语言开发的库没有太多运行时(Runtime)依赖,而且系统的兼容性好,稳定性高。

同样是 C 语言编写的,还有 Python,SQLite等

既然 C 语言这么厉害,那用编写 C 语言的那个语言来编写 Redis ,那不是还可以更快吗

如果我和你说,C语言是用C语言来编写的呢,你是不是会疯掉

这叫自编译性,也叫自举性,拥有自编译性的语言是一个语言是否强大的标志

  • 简单的说,先用汇编语言写一个能编译C语言最最最基础功能的编译器,这里称为C0
  • 然后再用C0去实现一个复杂一点的语言,这里称为C1,C1是需要编译器的吧,C1的编译器是C0编写出来的
  • 这样一直循环,这个过程也叫自举
  • 一直循环到Cn,Cn的功能强大到可以实现C

上面的描述只有第一句提到了汇编语言,而且汇编语言也只是编译了最最最基础功能的C语言而已

从这个角度看,你可以感受到 C 语言的厉害了吧

至于为什么不全用汇编语言来编写,是因为可读性实在是太差了,维护起来太麻烦了

2. 基于于内存

上学时,我们学过的计算机组成原理,计算系统的存储结构是有层次的,大致分为以下三类:

|  指标  | CPU缓存  | 内存 |  磁盘  |
-----------------------------------
|  速度  |   最快   | 中等 |  最慢  |
|  容量  |   最小   | 中等 |  最大  | 
|  价格  |   最高   | 中等 |  最低  | 

从速度、容量、价格三个指标综合来看,基于内存是比较合理的综合性方案

如果你还想更快,使用CPU缓存的话,太贵,而且容量也不大,不实用

谷歌云现在最大可以提供 3,844GB 内存大小的服务器

3. 键值对数据结构

  • 也就是我们最熟悉的哈希表数据结构,通过键来取这个键对应的值,时间复杂度是O(1)

  • 对应的值可以是字符串对象,列表对象,哈希对象,集合对象,有序集合对象这5个之一

  • 对这些对象进行具体的插入删除等操作的时间复杂度就不一定是O(1)了

  • 注意区别一下这里的说O(1)所指的数据结构

4. 单进程单线程模型

  • 不存在多线程模型中的上下文切换开销,也不存在线程之间的资源竞争问题

  • 是多线程提升的效率更高,还是单线程省掉上下文切换开销及资源竞争时的等待更多,已经被证明是后者

  • 就拿 Redis 的需求来说,是基于内存的数据操作,不存在网络I/O这样需要等待的场景,除了持久化之外也不需要和硬盘频繁地打交道,也就是说,耗时的场景不存在,没有特别显著的理由去使用多线程,而且多线程从实现的角度来看,也会增加不可忽视的复杂度

5. 多路 I/O 复用技术

  • 多路指的是多个 socket 网络连接
  • 复用指的是复用同一个线程
  • 其明显的好处是可以在同一个线程中处理多个I/O请求,减少了网络I/O的消耗,也就提升了效率,也就更快了

6. 使用多种数据结构

  • 最具代表性的就是有序集合的实现,当使用的是跳跃表时,还结合了字典,使得查询单个成员和按范围查找,性能都能维持在一个较理想的水平

  • 还有 Redis 的 SDS 抽象数据类型,如果使用 C 字符串,获取字符串长度的复杂度为O(n),SDS只需要O(1)

最近一直在看 Redis 的源码,找个时间分享一下

返回首页