苏炳添开启“涡轮增压”震惊老外,Redis 这么快又是为什么?

苏炳添上演世界级弯道超车 9.83 刷新亚洲100米田径赛纪录,拉爆其他运动员,开启“涡轮增压”模式震惊老外!隔着屏幕看依然激动万分。

8aaa8c866c28bf9d6ac1b33eb29f62de.png

他无疑成了百米程全亚洲跑得最快的男人。

Redis 为什么这么快?

Chaya:“苏炳添是亚洲跑的最快的人,因为开启了涡轮增压,那 Redis 为什么这么快呢?”

我是 Redis,如今已经成为软件系统必备的中间件之一,是面试官青睐的对象。本节从面试角度提炼知识点,带你融会贯通。

65 哥前段时间去面试某大厂,被问到“Redis 的性能为什么这么快”。

65 哥:“额……因为它是基于内存操作数据的,内存速度很快。”

面试官:“还有呢?”

很多人仅仅知道Redis 基于内存实现,并不了解其核心原因。今日,我带你一起探索真正的原因。

在进入正文前,先宣传我的新书。原价 100,现在新书上市优惠力度特别大,五折优惠,只需提供 50 灵石即可到手。

点击下方小程序,直接购买

新书上市,就冲入榜单 Top2!推荐大家冲一波。

f27127a8f4b87050a33cf90aff90c7a2.png

本书基于 Redis 7.0 版本的源码来讲解,并建立了一个完整的 Redis 知识框架,从全局视角整理 Redis 知识体系,结合难点给出158 张图片,希望能让你们更容易理解。

49b6006cbbe47e3d3697aa41fbb60a0f.png

以下内容节选自《Redis 高手心法》,防止走火入魔,请修炼完整版,哈哈哈哈~


正文开始……

根据官方数据,Redis 的每秒请求数(Qequests Per Second,QPS)可以达到 100000。

dbf0a2ef77129a16ba1f7caec5d391e8.png

Redis 的性能强大主要有以下原因。

◎   基于内存实现。

◎   使用 I/O 多路复用模型。

◎   单线程模型。

◎    6.0 推出 I/O 多线程模型。

◎   高效的底层数据结构。

◎   全局散列表。

01 基于内存实现

读、写操作都是在内存上完成的,内存直接由 CPU 控制,也就是由 CPU 内部集成内存控制器,所以说内存是直接与 CPU 对接的,享受与 CPU 通信的“最优带宽”。

Redis 将数据存储在内存中,读/写操作不会被磁盘的 I/O 速度限制。如下图是磁盘操作调用栈。

71d9a90493c0cd4ac71bbc1ddd78d1f7.png

02 I/O 多路复用模型

Redis 采用 I/O多路复用技术并发处理连接。采用 epoll + 自己实现的简单的事件框架。

将 epoll 中的读、写、关闭、连接都转化成事件,再利用 epoll 的多路复用特性实现一个ae高性能网络事件处理框架,绝不在 I/O 上浪费一点时间。

“多路”指多个 socket 连接,“复用”指共同使用一个线程。多路复用主要有select、poll和epoll 三种技术。

epoll的基本原理是,内核不监视应用程序本身的连接,而是监视应用程序的文件描述符。

客户端在运行时会生成具有不同事件类型的套接字。在服务器端,I/O 多路复用程序(I/O 多路复用模块)会将消息放入队列(图2-53中的I/O 多路复用程序的 socket 队列),然后通过文件事件分派器将其转发到不同的事件处理器。

4c8d52b3eb4892124af002669fb2c6ed.png

Redis 线程不会阻塞在某一个特定的监听或已连接套接字上,也就是说,不会阻塞在某一个特定的客户端请求处理上。

正因如此,Redis 可以同时和多个客户端连接并处理请求,从而提升并发能力。

03单线程模型

65 哥:“为什么 Redis 不采用多线程并行执行,以充分利用 CPU 呢?”

单线程指 Redis 的网络 I/O 以及field-value pairs命令读/写是由一个线程来执行的。

Redis 的持久化、集群数据同步、异步删除等操作都是其他线程执行的。

不过Redis从 6.0 版本开始支持多线程模型,需要注意的是,Redis 多 I/O 线程模型只用来处理网络读/写请求,Redis 的读/写命令依然是单线程处理的。

使用多线程,通常可以增加系统吞吐量,充分利用 CPU 资源。

但是如果没有良好的系统设计,就可能出现图2-54所示的场景:在增加线程数量的初期,吞吐量随之增加,当进一步增加线程数量时,系统吞吐量几乎不再增加,甚至下降!

d37b39a26c8e0182c7988c1f45dec191.png

Redis 选择使用单线程处理命令以及高性能的主要原因如下。

◎   不会因为创建线程消耗性能。

◎   避免上下文切换引起的 CPU 消耗,没有多线程切换的开销。

◎   避免了线程之间的竞争问题,例如添加锁、释放锁、死锁等,不需要考虑各种锁问题。

◎   代码更清晰,处理逻辑简单。

使用 Redis 时,几乎不存在 CPU 成为瓶颈的情况,Redis 的性能瓶颈主要受限于内存和网络。

单线程机制让 Redis 内部实现的复杂度大大降低,渐进式 Rehash、Lpush 等线程不安全的命令都可以无锁进行。

04高效的数据结构

65 哥:“为了提高检索速度,MySQL 使用了 B+ Tree 数据结构,所以 Redis 速度快应该也跟数据结构有关。”

回答正确,这里所说的数据结构并不是 Redis 提供给我们使用的 5 种数据类型 String、Lists、Hashes、Sets和Sorted Sets。

为了在性能和内存之间取得平衡,有的数据类型底层使用了不止一种数据结构,如图2-55所示。

9060d78929b5b236a4672805425821ce.png

05全局散列表

Redis 通过一个散列表来保存所有的key-value,散列表的本质就是数组 + 链表,数组的槽位被叫作哈希桶。每个桶的 entry 保存指向具体key和value的指针。

key 是 String 类型,value 的数据类型可以是 5 种中的任意一种。如图所示。

15d64c63f9258afc9e6b952e56b61d88.png

全局散列表的时间复杂度是 O(1)。通过计算每个键的哈希值,可以知道对应的哈希桶位置,再通过哈希桶的 entry 找到对应的数据,这也是 Redis“快”的原因之一。

06Redis I/O多线程模型

我们已经知道,Redis 使用全局 dict + 内存数据库 + 丰富高效的数据结构 + 单线程模型 + I/O 多路复用事件驱动框架“快到飞起”。

Redis 的网络 I/O及key-value命令读/写是由单个线程来执行的,避免了不必要的线程上下文切换和资源竞争,对于提升性能有很大帮助。

然而,Redis 官方在 2020 年 5 月正式推出 6.0 版本,引入了 I/O 多线程模型。

现在,咱们就详细地聊一下 I/O 多线程模型带来的效果到底是“林黛玉骑鬼火,该强强,该弱弱”;还是“光明顶身怀绝技的张无忌,招招都是必杀技”。

随着底层网络硬件性能的提升,Redis 的性能瓶颈逐渐体现在网络 I/O 的读/写上,单个线程处理网络读/写的速度跟不上底层网络硬件执行的速度。

读/写网络的读/写系统调用占用了 Redis 执行期间大部分 CPU 时间,所以 Redis 采用多个 I/O 线程来处理网络请求,提高网络请求处理的并行度。

需要注意的是,Redis 多 I/O 线程模型只用来处理网络读/写请求,对于 Redis 的读/写命令,依然由单线程处理。

主线程与 I/O 多线程共同协作处理命令的架构图如图所示。

60376df45d2d9467382dfac6aff9293e.png

现在新书上市,优惠力度很大,原价 100,现在 5 折优惠,各位道友只需拿出 50 灵石,购买查看完整版的《Redis 高手心法》进行修炼。

点击下方小程序即可购买

来自 IT 大佬对本书的赞誉

e1afd322c5e7f2ae707fbf5cbb2d7366.jpeg

购买了的小伙伴可加我的微信:MageByte1024,备注 Redis 高手,我会创建一个 Redis 高手心法读书群,为大家答疑解惑。

601c68293211fe8551635ef58e873886.jpeg

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值