《Redis核心技术与实战》学习总结(1)

63681b0234a6cf64ee4ffa0ff1d96527.gif

【Redis| 总结/Edison Zhou

0写在开头

作为Key/Value键值数据库,Redis的应用非常广泛。在之前多年的工作生涯中,我也只是关注了零散的技术点,没有对Redis建立起一套整体观,但只有建立了系统整体观,才能更好地定位问题和解决问题,更重要的是应付面试。

刚好,极客时间推出了一门《Redis核心技术与实战》课程,于是我就入手了,这是我的学习总结,化繁为简,只留重点,分享与你。

1KV数据库的基本架构

为了建立系统观,最好的方法就是对其总体架构和关键模块有一个全局认知,因此这门课在最开始便给出了一个简单的KV数据库的基本架构,它包括了:

(1)访问框架

(2)索引模块

(3)操作模块

(4)存储模块

84b97f630f88e5aef9e9db4ca3ff6ff0.png

SimpleKV - 来自极客时间

为了支持更加丰富的业务场景,其实 Redis 对这些组件或者功能进行了扩展,或者说是进行了精细优化,从而满足了功能和性能等方面的要求。

下图展示了从SimpleKV到Redis的变化:

fd71b98cc616c4b48732916a2a5c3f91.png

SimpleKV to Redis - 来自极客时间

上图中展示了几点变化:

一是Redis主要使用网络框架来进行访问,使得Redis可以作为一个独立的基础网络服务;

二是Redis数据模型中的value类型更加丰富,可以提供更多的接口;

三是Redis扩展了持久化模块,提供日志(AOF)和快照(RDB)。

四是Redis提供了集群的支持,使得HA和可扩展成为可能。

2Redis的数据结构

Redis之所以“快”,一方面因为它是内存数据库,所有操作都在内存上完成,内存的访问速度本来就快。另一方面则是因为高效的数据结构,使得操作键值效率较高。

总体来说,Redis使用了一个用来保存每个Key/Value的全局哈希表结构,其中Value类型又包括了支持集合类型的双向链表、压缩列表、跳表等五大底层结构。

K/V的组织结构:全局哈希表

Redis使用了一个全局维度的哈希表来保存所有的Key/Value,每个哈希表本质上都是一个数组,这个数组的每个元素称为一个哈希桶

哈希桶中的元素保存的并不是Value本身,而是指向Value的指针,如下图所示:

9e995e99af36a448c34fc51c35077d61.png

由数据结构的知识可以知道,哈希表的时间复杂度为O(1),因此它非常适合快速查找的场景

哈希冲突及其解决

当往哈希表中写入的数据变的很多时,哈希冲突问题就会出现。所谓哈希冲突,就是两个Key的哈希值正好落到了同一个哈希桶中(哈希桶的个数毕竟通常少于Key的个数)。

因此,和我们在数据结构课程学到的一致,Redis也采用了链式哈希来解决哈希冲突。所谓链式哈希,就是同一个哈希桶中的多个元素用一个链表来保存,它们之间依次用指针连接,如下图所示:

6fadde8875a65fa79f9088aa8cd3ebe7.png

但是,如果哈希表里写入的数据越来越多,哈希冲突链也会进而变得很长,从而导致这个链条上得元素查找耗时长,效率降低。

因此,Redis还会对哈希表做rehash操作。所谓rehash,就是增加现有的哈希桶的数量,让逐渐增多的entry元素能够在更多的桶之间分散保存,减少单个桶中的元素数量,从而减少单个桶中的冲突。

在具体操作中,Redis会开辟一个新的哈希表(比如:大小为之前的两倍),然后把之前哈希表的数据重新映射到新的哈希表,最后释放之前的哈希表。

画外音:是不是跟.NET中的集合类型动态扩容的思想类似?

58797daa1fd9da54dcadf4aa90f4ae99.png

But,在拷贝之前哈希表数据到新哈希表时,涉及到数据量过大,有可能会造成Redis的线程阻塞,从而无法服务其他的请求。因此,Redis采用了渐进式哈希的解决方案

简单来说,所谓渐进式哈希就是不一次性把老哈希表中的数据迁移完,而是在每次处理一个请求时,从老哈希表中的第一个索引位置开始,顺带着将这个索引位置上的所有entries拷贝到新哈希表中;等下一个请求时,再顺带拷贝下一个索引位置的entries。如此,便将一次性的大量拷贝的开销,分摊到多次处理请求的过程中,避免了耗时的操作 和 服务的中断

渐进式哈希的示例流程如下图所示:

b6e7b3397aff2c15f8057d5c671b5e4f.png

此外,渐进式rehash执行时,除了根据键值对的操作来进行数据迁移,Redis本身还会有一个定时任务在执行rehash,如果没有键值对操作时,这个定时任务会周期性地(例如每100ms一次)搬移一些数据到新的哈希表中,这样可以缩短整个rehash的过程。

底层数据结构概览

Redis的Key/Value是通过哈希表进行组织的,对于String类型,找到哈希桶就可以直接CRUD了,因此O(1)就是String类型的操作复杂度了。

但是,对于集合类型来说,还需要进一步操作。在此之前,我们先了解一下都有哪些底层数据结构。

我们所熟知的String、List、Hash、Sorted Set 和 Set其实只是Redis中数据的保存形式,而一般所说的数据结构其实是它们的底层实现

如下图所示,Redis的底层数据结构一共有6种,其和常见数据类型的对应关系已经清晰地体现在了下面这张图片里(给个赞)。

00bbd420670ebdff6b71e5f8638b6605.png

Redis数据类型与底层数据结构 - 来自极客时间

除了String类型的底层实现只有一种,即简单动态字符串。其余数据类型(List、Hash、Sorted Set和Set)都有两种底层实现,他们又被称为集合类型,即一个键对应了一个集合的数据

底层数据结构复杂度

通过上面的描述,我们可以知道哈希表的复杂度是O(1),而数组 和 双向链表 也很常见,其复杂度基本是O(N)。学习过数据结构课程的都知道,O(N)的操作效率并不高,因此Redis引入了压缩列表 和 跳表。虽然压缩列表和跳表并不为我们所熟知,但它俩却是对整数数组和双向链表所做的优化。

9239c316da8f9d2a155db8161fcccc00.png

首先,来看压缩列表,压缩列表也类似于一个数组,但和数组不同的是,压缩列表在表头有三个字段,分别表示列表长度、列表尾的偏移量 和 列表中entry的个数。压缩列表在表尾还有一个字段,表示列表结束,如下图所示:

b1777bb2ecf32feab70f991a605f21ae.png

由上图可知,在压缩列表中定位第一个和最后一个元素,只需要通过表头三个字段即可直接定位,无须遍历一次,因此查找首元素和尾元素的复杂度为O(1)。而需要查找其他元素时,就只能遍历查找了,此情景的复杂度退化为O(N)。

然后,来看跳表。跳表是在链表的基础之上,增加了多级索引,通过索引位置的几个跳转,实现数据的快速定位。一个具体的查找案例,如下图所示:

43339b7486bdb7edde2fde5b7a96b9e5.png

从上图可以看到,这个查找过程其实是在多级索引上跳来跳去,最后定位到具体的要查找的元素。我们常听到,没有什么不是一顿火锅解决不了的事情,如果不行,那就两顿。对于跳表来说,没有什么不是增加索引解决不了的查询,如果不够快,那就再加一级索引。

当数据量非常大时,跳表的查找复杂度就是O(logN),学过数据结构的都知道,它比O(N)效率要高。因此,我们也可以知道Sorted Set类型在数据元素较少时采用压缩列表,而一旦超过阈值,就会转为跳表结构来保证查询效率不受影响。

End总结

本文总结了Redis的基础架构 和 底层数据结构,这部分内容通常也是后端开发面试中的常见内容,希望对你有所帮助。

参考资料

极客时间,蒋德钧《Redis核心技术与实战》

cd6dc046dd1394c864d4d879fae261e1.gif

年终总结:Edison的2020年终总结

数字化转型:我在传统企业做数字化转型

C#刷题:C#刷剑指Offer算法题系列文章目录

.NET面试:.NET开发面试知识体系

.NET大会:2020年中国.NET开发者大会PDF资料

950a79ab323b59b72891769c3e3b2062.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云管边端架构图_中移物联网布局构建“云-管-端”全方位体系架构

随着物联网的步伐,国内三大运营商纷纷成立自己的物联网团队,而在物联网连接管理平台方面,电信与爱立信合作,联通与Jasper合作,移动则采取自主研发的OneLink平台。在此环境下,全球物联网管理平台逐渐形成四分…

c++学习笔记九

程序文件和预处理指令1 程序文件头文件:类型定义和其他用于程序中一个或多个源文件的代码 后缀名为&#xff1a;.h源文件&#xff1a;要编译成机器指令的代码 后缀名为&#xff1a;.cpp .c .cxx引入头文件 代码格式如下:#include<iostream>名称的作用域程序文件的连链…

SIP for android

SIP for android 会话发起协议 Android提供了一个支持会话发起协议&#xff08;SIP&#xff09;的API&#xff0c;这可以让你添加基于SIP的网络电话功能到你的应用程序。Android包括一个完整的 SIP协议栈和集成的呼叫管理服务&#xff0c;让应用轻松无需管理会话和传输层的沟…

饿了么翻车,美团被质疑,马云也赔了40亿,这项技术为什么让人害怕?

全世界只有3.14 % 的人关注了爆炸吧知识人类还没用力AI可能就倒下了8日&#xff0c;一篇《外卖骑手&#xff0c;困在系统里》的文章刷爆了朋友圈。看过的人多半都不好受&#xff0c;除了作为社畜感叹生活不易外&#xff0c;就是感叹外卖系统的AI算法对人类的裹挟是那么的残酷。…

如何强制 .NET 程序以 管理员模式 运行 ?

咨询区 Gold&#xff1a;我有一个 winform 程序部署客户的PC机上&#xff0c;请问我如何通过编码的形式强制让程序以管理员模式运行&#xff1f;回答区 Gaspa79&#xff1a;如果你用的是 Visual Studio 2019&#xff0c;可以通过工具去配置&#xff0c;右键 项目 -> 新建项 …

bitmap 转byte[]后读取_闲谈redis的bitmap

bitmap的原理bitmap就是通过最小的单位bit(8bit 1b 0.001kb)来进行0或者1的设置&#xff0c;表示某个元素对应的值或者状态。一个bit的值&#xff0c;或者是0&#xff0c;或者是1&#xff1b;也就是说一个bit能存储的最多信息是2。优点基于最小的单位bit进行存储&#xff0c;…

序1--年轻正当时(特权)

序1 年轻正当时 这本所谓的书&#xff0c;恐怕不一定能够带还没入门的U杀进FPGA开发的大门&#xff0c;当然也肯定不能达到进阶的目的。但是&#xff0c;姑且应了Bingo老弟所谓的对“图像的直觉”&#xff0c;确实图文并茂的从某一个山寨面把FPGA开发赤裸裸的展现给了大家。 被…

ecshop在首页调用dedecms文章

ecshop的文章功能实在是太过于简单了&#xff0c;所以我们为了丰富网站的内容&#xff0c;一般会集成DEDECMS来添加一些资讯文章&#xff0c;主要是DEDECMS文章处理相当强大&#xff0c;便于二次开发&#xff0c;下面通过两大步骤实现ecshop在首页调用dedecms文章&#xff1a;一…

Windows 11 dapr 环境安装

安装其实很简单按照dapr官网操作步骤其实没什么大问题的,不过在没有好的网络访问github的情况下真是有点揪心啦&#xff01;推荐使用 工具 fastgithub 访问githubFast&#xff1a;Github让Github畅通无阻windows 11 下的安装方式1.安装dapr cli 直接到Releases dapr/cli GitH…

eclipse 运行MapReduce程序错误异常汇总(解决Map not fount)

错误一&#xff1a; Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class wordCount.wordCount$Map not foundat org.apache.hadoop.conf.Configuration.getClass(Configuration.java:2074)at org.apache.hadoop.mapreduce.task.JobContextImpl.getMa…

日本原装进口雪平锅,煎炸炒煮全搞定,日本人用了 1000 年

▲ 点击查看小爆我虽然热爱烹饪&#xff0c;但不得不说「下厨房」&#xff0c;也是个坑。光是锅&#xff0c;我就要买好几个。为了蒸包子馒头买蒸锅&#xff0c;为了炒菜买炒锅&#xff0c;偶尔想精致喝热牛奶又买了小奶锅&#xff0c;为了煲汤、做点卤味解解馋&#xff0c;买炖…

Android开发学习笔记:浅谈Content Provider

一.Content Provider的概念介绍 Content Providers是所有应用程序之间数据存储和检索的桥梁&#xff0c;它使得各个应用程序之间实现数据共享。是应用程序间共享数据的唯一途径。Content Provider 主要的功能就是存储并检索数据以及向其他应用程序提供访问数据的接口。其中包括…

小米3g刷高格固件_小米路由器3G刷了老毛子之后恢复官方固件

这个教程我没有亲自试过,看到了只是为了保存记录一下,方便自己日后用!1、断电路由器后&#xff0c;按住Reset恢复出厂设置5秒&#xff0c;接入电源&#xff0c;灯闪烁三下后松开。浏览器输入192.168.1.1即可进入breed 控制台&#xff01;2、固件更新-Bootloader-选择Bootloader…

VS2010插件之NuGet

Visual Studio&#xff08;简写VS&#xff09;是.net程序员开发必不可少的开发工具&#xff0c;随着VS的版本不断的升级和使用用户的扩大&#xff0c;现在针对VS开发了许多的开源免费的插件&#xff0c;大大的方便了程序员的开发&#xff0c;提高了开发效率。今天&#xff0c;我…

C# WPF Caliburn.Micro框架下利用Mef加载其它项目界面

01—前言MEF是微软自家的托管可扩展框架&#xff0c;在这里我把它用成了ioc容器。在Caliburn.Micro框架下&#xff0c;view和viewmodel被注入到CompositionContainer容器中&#xff0c;然后通过名称可以实现view和viewmodel的匹配。利用这一特点&#xff0c;在多人合作项目开发…

thinkpade450装内存条_thinkpad e450可以加内存条吗

展开全部结论&#xff1a;肯定是可以加的。原因62616964757a686964616fe59b9ee7ad9431333361313362&#xff1a;thinkpad e450自带两个内存插槽&#xff0c;最高可扩展至16G内存&#xff0c;也就是插两根8G内存条&#xff0c;这款笔记本增加内存的话&#xff0c;建议插两根4G的…

女朋友竟然提出这种奇怪的要求......

1 为什么女朋友会提这么奇怪的要求&#xff1f;▼2 我的数学能力▼3 一看就是老龙人了阁下是古墓派传人吧▼4 如果可爱能晋级的话你已经赢了▼5 要做个与众不同的垃圾▼6 女孩子喜欢帅哥是不分年龄的▼‍‍7 单身狗又做错了什么呢&#xff1f;▼扫描这个二维码你将会有机…

java内存:堆、栈、常量池、方法区

java中内存主要包含4块&#xff0c;即heap(堆内存)、stack(栈内存)、data segment(静态变量或是常量存放区)、codesegment(方法区). 参考&#xff1a; http://jameszhao1987.iteye.com/blog/1320630转载于:https://www.cnblogs.com/zhouqg/p/4758422.html

Java编码规范,在您进行编码之前应该阅读的规范

为什么80%的码农都做不了架构师&#xff1f;>>> 本文转载于&#xff1a;http://www.web3d.com.cn/new/teach/java3d/2006/11/13/363276161.html Java编码规范 说明 1.1 为什么要有编码规范 编码规范对于程序员而言尤为重要&#xff0c;有以下几个原因&#xff1a; …

ensp查看历史配置命令_华为eNSP常用命令

开启DHCP功能[R1-GigabitEthernet0/0/2]dhcp select interface开启接口的DHCP服务功能[R1-GigabitEthernet0/0/2]dhcp server lease day 2配置IP地址租用有效期限为2天,默认为1天,超过租期后该地址将会重新分配[R1-GigabitEthernet0/0/2]dhcp server excluded-ip-address 192.1…