达内广州C++学院|c++培训|广州达内科技C++/C#培训|.NET培训|IT培训|达内广州岗顶中心 达内广州C++学院|c++培训|广州达内科技C++/C#培训|.NET培训|IT培训|达内广州岗顶中心
java程序员
 当前位置:主页 > 高端课程 > java程序员 >

我再也不怕面试被问 Redis 排行榜底层轮子了

时间:2020-05-21  来源:未知  作者:广州达内培训

file
[Redis]相信大家都不陌生,由于它是基于内存的,所以它相比 [MySQL] 等数据库在处理速度上,要快上 N 个数量级。

基于此,Redis 已经是现在面试中非问不可的知识点之一了。

掀起了一股学习 Redis 源码的热潮,所以今天就趁热打铁解读一个面试必问的 Redis 实时排行榜。

Redis 实现排行榜有多火呢?你只要在百度搜索 "Redis 实现排行榜", 一大波文章会跳出来。

基本都是围绕 Redis的有序集合—— zset 的 ZRANK 、ZADD 等命令展开。
file
如上代码所示,更多的命令用法这里就不再展开了,我们重点说说这些命令背后的原理是什么?

说到这里,你在网上接着搜索,关于底层原理几乎没有文章谈起。所以我这里打算从 Redis 4.0.9 的源码入手,针对 如何在O(logN)时间内获取一个 Redis 有序集合中的元素的排名 这一问题进行分析,并且最后手撸一个简化版的排行榜的轮子以加深理解。

分析

Redis 的 zset 的获取元素排名的核心命令为 ZRANK,官方给出的复杂度是 O(log(N))。
除了内存快于硬盘这个原因外,O(log(N)) 的时间复杂度也是根本上优于 MySQL 的 order by 进行排行的原因之二。那么我们自然好奇 Redis 是如何实现这一算法的。

在开始解毒源码之前,我们先来了解一下跳表。

跳表是神犇William Pugh于1990年发明的,这里会用最形象的语言讲清楚这玩意。

学过数据结构的都知道,数组和链表是最基本的线性数据结构,增删改查中,数组查快,增删改慢;链表恰好相反。

而且分别都是快到极致,数组 O(1) 时间完成查,链表 O(1) 时间完成增删改。

他俩就是有得必有失的典型代表。但是有些问题需要增删改查都有不错的性能,于是聪明的人类发明了半线性的数据结构,就是一大票的树结构。

例如最典型的平衡树,它能在均摊 O(logN) 时间内完成增删改查。针对特定问题,树结构成为不错的选择。

但是 William Pugh 这哥们不信邪,非要使用链表这种线性数据结构搞出 O(logN) 的查询效果出来。

于是办法就是空间换时间——多搞几层出来。

所以,典型的跳表长下面的样子(你可以将下面圆圈中的数字就视作 zset 中的分数)。
file
这里必须要指出跳表的特点

  1. 由若干层链表构成,每层都是有序的, 例如单调递增。
  2. 上层拥有的元素,下层一定都有,最底层拥有全部元素。

首先,跳表这玩意依旧是链表,所以完美的继承了链表的增删改的 O(1) 优良传统。其次,跳表查询的时候非常牛掰。

比如在上图中查询 117, 查询的轨迹如下图红线。
file
具体说要经过如下几个步骤

(1) 比较 21,比 21 大,往后面找

(2) 比较 37,比 37大,比链表最大值小,从 37 的下面一层开始找

(3) 比较 71,比 71 大,比链表最大值小,从 71 的下面一层开始找

(4) 比较 85, 比 85 大,从后面找

(5) 比较 117, 等于 117, 找到了节点。

我们知道,链表哪怕有序,也得老老实实一个一个遍历的顺序遍历去找一个元素,花费时间是 O(N),而不能像数组那样二分查找,花费时间是O(logN)。

但是跳表呢? 如上图所示,我们跳着、跳着就把元素找到了。所以跳表的名字取的还是很到位的。所谓跳着跳着,意思就是不像链表一个一个元素的去遍历,而是大步流星的前进,找到一个元素。所以跳表查询的性能远胜于普通链表。

那么, 回到获取排名的话题, 我们怎么 O(logN) 时间获取一个元素的排名呢? ?还是贴图,贴图秒懂~
file
看到了吗? 我们想定位 13 这个元素在 zset 中的排名,只需要在跳表数据结构中额外维护一个叫 span 的域,它表示它在本层链表中到达下一个节点还需要走几步。上图中节点后面的圆括号里面的数字就是该节点的 span 域的值。例如第三层的节点 9 需要经过 9->10、10->13、13->14、14->15 走这 4 步才能来到它在本层链表的下一个节点 15,所以 9 的 span 是4。

有了 span 域之后,只需要在搜索 13 的过程中累加 span 即可得到。就像上图演示的那样,13 的排名是 4+2=6。

有了这些了解,我们再来回看 Redis 的源码就好懂很多了。

Redis 官网上显示,ZRANK 这一命令在 Redis2.0.0 开始就有了,我们翻看 Redis-4.0.9 的源码,就在 t_zset.c 文件中的zslGetRank 函数中。
file
注释写的很明白,就是通过 key 和 score 在入参 zsl 中寻找该键的排名。zsl 就是跳表,Redis 能 O(logN) 时间定位海量元素中任何一个元素的排名就靠这玩意儿。

第 11 行的 for 循环中的第 16 行在干的事情就是在累加每一层 span。而且通过第 13 行~第 15 行我们知道了 Redis 底层的排名逻辑是分数是第一关键字,key(字典序)是第二关键字进行升序排序。

最后理解了上面的跳表的思想之后,我们就可以理解,为什么 Reids 的 ZRANK 那么快,因为用跳表来实现实时排行榜功能是再合适不过的了。

Java 中,ConcurrentSkipListMap、ConcurrentSkipListSet 就是基于跳表的。根据我面试过的人来看,基本上很少有人看过它的源码,后面有时间我来唠叨它。

那么看完本文,我的面试问题来了!Redis Zset 采用跳表而不是平衡树的原因是什么?

Redis Zset 作者是这么解释的:
file
Redis 源码中还有非常多的精妙绝伦的设计,后面我们一起来揭开它的更多面纱吧!

收集了各方面的,当前公司的,还有自己收集总结的,下面的图片截取的有pdf,有如果有需要的自取.

各大公司面试题集合:

简历模板:

链接:?https://pan.baidu.com/s/1DO6XGkbmak7KIt6Y7JQqyw
提取码:fgj6
不知道会不会失效,如果失效点击(778490892)或者扫描下面二维码,进群获取,链接补发不过来,谢谢。

在这里插入图片描述




上一篇:Spring Boot 如何做参数校验?
下一篇:没有了

友情链接:
  • 全球最大晶圆代工半导体制造厂,台积电斥资订购艾斯摩尔机器设备
  • 英特尔依然是那个英特尔,且看英特尔的城防体系
  • 支持双 DRAM 内存接口,慧荣企业级 SSD 主控方案披露
  • 在全球被反垄断罚款,冤!高通到底哪里得罪了欧盟?
  • 强强联合!万业、微电子所和芯鑫共同打造全新半导体设备
  • 复旦大学校长称:对于集成电路产业发展,大学应该主动担当
  • 技术再升级!无锡中科芯攻克晶圆级再布线及晶圆级凸点制备关键技
  • 聚力!万业企业设立集成电路装备集团,提供自主可控设备
  • 德州仪器C2000微控制器增强连通性和控制性
  • 英特尔打出降价策略,以免被竞争对手 AMD 打败?
  • 贸易摩擦的闹剧没有赢家,苹果有勇气离开中国吗?
  • 图像信号与视觉处理器的发展趋势
  • 真干快消品定位方案班(第二期)火热开班
  • Java集合 ArrayList原理及使用
  • TDD(测试驱动开发)死了吗?
  • JAVA基础之XML相关
  • javaweb项目搭建ehcache缓存系统
  • 每日一码——字符串统计
  • 一篇文章帮你彻底搞清楚“I/O多路复用”和“异步I/O”的前世今生
  • 九:模板方法模式
  • 十二:命令模式(人员解耦和)
  • Java 转PPT为图片、PDF、SVG、XPS、ODP以及PPT和PPTX互转
  • SpringCloud学习(SPRINGCLOUD微服务实战)一
  • 记一次微信网页授权后获取用户信息并重定向
  • 速途新营销五点实战洞察解码“品效合一”
  • 十一:外观模式详解(Service,action与dao)
  • 手把手教你学会 基于JWT的单点登录
  • mysql锁机制总结,以及优化建议
  • 解决多个版本jar包冲突【jar内包名重命名】
  • 中国首张5G终端电信设备进网许可证 华为Mate 20 X 5G版入网
  • RPC之Thrift
  • 高级Java工程师必备 ----
  • 天猫618期间实物支付GMV增长38.5%
  • 换季了,老板你的库存处理好了吗?
  • 从“618”大数据看中国消费新活力
  • 小米生态链:贵在格局感与收放度
  • CODING 2.0 企业级持续交付解决方案
  • 老铁奇趴“新京济” 快手*京东618战报出炉
  • 中小企业新媒体运营基本技能
  • 上汽大通房车再度携手LINE FRIENDS 魔都巡游顺利开启
  • 华为高端手机国内市场份额超苹果夺得榜首
  • 中国智能制造分析报告
  • iPlus艾加营销助力腾讯广告牵手吴晓波 推进商业IP变现
  • 2019世界新能源汽车大会7月1日将在海南举行
  • 区域酒企如何转型突围
  • 时时彩论坛
  • 五星体育斯诺克
  • 北单比分直播
  • 河北11选5走势图
  • 福建体彩36选7开奖结果
  • 九龙图库下载