Redis为什么这么快?

答案写在前面

Redis 之所以如此快,主要有以下几个方面的原因:

  1. 基于内存:Redis 是一种基于内存的数据库,数据存储在内存中,数据的读写速度非常快,因为内存访问速度比硬盘访问速度快得多。
  2. 单线程模型:Redis 使用单线程模型,这意味着它的所有操作都是在一个线程内完成的,不需要进行线程切换和上下文切换。这大大提高了 Redis 的运行效率和响应速度。
  3. 多路复用 I/0 模型:Redis 在单线程的基础上,采用了I/0 多路复用技术,实现了单个线程同时处理多个客户端连接的能力,从而提高了 Redis 的并发性能。
  4. 高效的数据结构:Redis 提供了多种高效的数据结构,如哈希表、有序集合、列表等,这些数据结构都被实现得非常高效,能够在 O(1)的时间复杂度内完成数据读写操作,这也是 Redis 能够快速处理数据请求的重要因素之一
  5. 多线程的引入:在Redis 6.0中,为了进一步提升I0的性能,引入了多线程的机制。采用多线程,使得网络处理的请求并发进行,就可以大大的提升性能。多线程除了可以减少中于网络 /0 等待造成的影响,还可以充分利用 CPU 的多核优势。

扩展

1、为什么Redis设计成单线程也能这么快?

Redis的性能很好,除了因为他基于内存、有高效的数据结构等等原因以外,还有一个重要的原因那就是他在单线程中使用多路复用 I/O技术也能提升Redis的I/O利用率。

1.1Redis的多路复用

多路复用这个词,相信很多人都不陌生。那么,Redis的多路复用技术有什么特别的呢?
这里先讲讲Linux多路复用技术,就是多个进程的I0可以注册到同一个管道上,这个管道会统一和内核进行交互,当管道中的某一个请求需要的数据准备好之后,进程再把对应的数据拷贝到用户空间中。

多看一遍上面这张图和上面那句话,后面可能还会用得到,

也就是说,通过一个线程来处理多个I0流。

多路复用在Linux下包括了三种,select、poll、epol,抽象来看,他们功能是类似的,但具体细节各有不同。

其实,Redis的I0路复用程序的所有功能都是通过包装操作系统的多路复用函数库来实现的。每个多路复用函数库在Redis源码中都有对应的一个单独的文件。

在Redis 中,每当一个套接字准备好执行连接应答、写入、读取、关闭等操作时,就会产生一个文件事件。因为个服务器通常会连接多个套接字,所以多个文件事件有可能会并发地出现。

以旦有请求到达,就会交给 Redis 线程处理,这就实现了一个 Redis 线程处理多个 流的效果
所以,Redis选择使用多路复用I0技术来提升I/O利用率,

而之所以Redis能够有这么高的性能,不仅仅和采用多路复用技术和单线程有关,此外还有以下几个原因:

  1. 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。
  2. 数据结构简单,对数据操作也简单,如哈希表、跳表都有很高的性能
  3. 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗D
  4. 使用多路//O复用模型

还是要记住:Redis并不是完全单线程的,只是有关键的键值对读写是由一个线程完成的

2、为什么Redis 6.0引入了多线程?

2020年5月份,Redis正式推出了6.0版本,这个版本中有很多重要的新特性,其中多线程特性引起了广泛关注

但是,需要提醒大家的是,Redis 6.0中的多线程,也只是针对处理网络请求过程采用了多线程,而数据的读写命令,仍然是单线程处理的。

但是,不知道会不会有人有这样的疑问:

Redis不是号称单线程也有很高的性能么?

不是说多路复用技术已经大大的提升了I0利用率了么,为啥还需要多线程?

主要是因为我们对Redis有着更高的要求。

根据测算,Redis 将所有数据放在内存中,内存的响应时长大约为 100 纳秒,对于小数据包

Redis 服务器可以处理 80,000 到 100.000 QPS,这么高的对于 80% 的公司来说,单线程的 Redis 已经足够使用了。

但随着越来越复杂的业务场景,有些公司动不动就上亿的交易量,因此需要更大的 QPS,

为了提升QPS,很多公司的做法是部署Redis集群,并且尽可能提升Redis机器数。但是这种做法的资源消耗是巨大的。

而经过分析,限制Redis的性能的主要瓶颈出现在网络的处理上,虽然之前采用了多路复用技术。但是我们前面也提到过,多路复用的模型本质上仍然是同步阻塞型I0模型,

下面是多路复用中select函数的处理过程

从上图我们可以看到,在多路复用的10模型中,在处理网络请求时,调用 select (其他函数同理)的过程是阻塞的,也就是说这个过程会阻塞线程,如果并发量很高,此处可能会成为瓶颈。

虽然现在很多服务器都是多个CPU核的,但是对于Redis来说,因为使用了单线程,在一次数据操作的过程中,有大量的CPU时间片是耗费在了网络I0的同步处理上的,并没有充分的发挥出多核的优势。

如果能采用多线程,使得网络处理的请求并发进行,就可以大大的提升性能。多线程除了可以减少由于网络 I0等待造成的影响,还可以充分利用 CPU 的多核优势。

所以,Redis 6.0采用多个I0线程来处理网络请求,网络请求的解析可以由其他线程完成,然后把解析后的请求交由主线程进行实际的内存读写。提升网络请求处理的并行度,进而提升整体性能。
但是,Redis 的多 10 线程只是用来处理网络请求的,对于读写命令,Redis 仍然使用单线程来处理,

那么,在引入多线程之后,如何解决并发带来的线程安全问题呢?

这就是为什么我们前面多次提到的"Redis 6.0的多线程只用来处理网络请求,而数据的读写还是单线程”的原因。

Redis 6.0 只有在网络请求的接收和解析,以及请求后的数据通过网络返回给时,使用了多线程。而数据读写操作还是由单线程来完成的,所以,这样就不会出现并发问题了。

  • 37
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小徐很努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值