【.com原创稿件】面试官:Redis 有哪几种数据类型?今天存储原理是什么?具体适应哪些应用场景?是否历历在目,这是才知 Redis 关于数据类型的面试 3 连问,是有种除“Redis 持续化”外的最常见 Redis 考题。 图片来自 Pexels 但是数据,无论面试官的类型提问、网上的今天答案,基本都是才知错的!本文将依据源码向读者做剖析,深入浅出,有种过目不忘。数据 查谷歌众说纷纭 说法一:5 种 Redis 支持 5 种数据类型: 这也是类型被行业普遍认可,最最常见的今天答案。至于这 5 种类型的才知详解,网上已经铺天盖地,有种这里不打算重复探讨,数据请读者自行温习。类型 说法二:6 种 包含了“说法一”的 5 种,还包含了:HyperLogLog(基数)。 也就是:String(字符串)、服务器托管List(列表)、Set(集合)、Sorted Set(有序集合)、Hash(哈希)、HyperLogLog(基数)共 6 种。 说法三:9 种 包含了“说法二”的 6 种,还包含了:Bitmap(位集合)、Geospatial(地理空间索引)、Streams(流信息)3 种。 也就是:String(字符串)、List(列表)、Set(集合)、Sorted Set(有序集合)、Hash(哈希)、HyperLogLog(基数)、Bitmap(位集合)、Geospatial(地理空间索引)、Streams(流信息)共 9 种。 还有一说,并未包含 Streams(流信息),但是包含了 BloomFilter(布隆过滤器),这个不重要,但都称是 9 种,尚未见有 10 种的说法。 从官网找答案 英文官网:https://redis.io/,中文官网:http://www.redis.cn/,首页如下: 请留意这一句: Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams. 很明显,官网提到 Redis 支持的香港云服务器数据类型一共有 9 种。跟上文的“说法三”基本一致。 另外值得注意的是,中文官网没有提及 Stream,也就是漏了一句话。因为 Stream 是在 2018 年 10 月 5.0 版本引入,但是中文官网至今没有更新,是个非常明显的文案 Bug(不知道反馈被采纳会不会有奖金)。 那么问题到此解决了?还没有!问题才刚刚开始。 具体问题具体分析 “说法一:5 种” 为什么会被行业普遍认可 先来看看 Redis 的各种高级功能类型被引入的版本,如下表: 很明显,原因是:这些功能都是后续版本陆续引入的,5 种数据类型乃最经典的 5 种类型,所以代代相传,传承已久。 再来看看 Redis 的各个大版本的发布时间,如下表: 也就是网站模板说,“5 种数据类型”的认知,业界持续已有 10 年之久,认知的错误也有 10 年之久。 “说法三:9 种” 是否正确 要回答这个问题,先了解 Redis 的数据类型如何查看,可通过 type KEY_NAME 命令。 另外,通过 object encoding KEY_NAME 命令可查具体的编码结构,这里仅稍作提及,不在本文的讨论范围内。 ①String ②Bitmap 很明显,Bitmap 底层也是 String 实现,赋值的每一个 bit 均对应 ASCII 码的二进制位。 ③HyperLogLog 很明显,HyperLogLog 底层也是 String 实现,与其说 HyperLogLog 是一种单独的数据类型,倒不如说是对 String 数据类型做 API 封装的应用程序。 ④归纳 其他几种高级功能类型的验证方式同,这里不做赘述,留给读者自行验证。 这里归纳结论如下: 饶了一圈似乎又回到了起点,“说法一:5 种”其实并没有错?毕竟任何类型的底层都是基于 5 种之一实现的。接着往下说。 Talk is cheap, Show me the code. 能说算不上什么,有本事就把你的代码给我看看。 源码文件列表 如下图: t_(type) 开头的,有且仅有 6 个,除了“5 种数据类型”外,还包含了:t_stream。 Stream 是 Redis 5.0 版本引入的一个新的数据类型,支持消费者组,借鉴 Kafka 设计的支持多播的可持久化消息队列(支持 group,不支持 partition)。 我们做下验证: 没有问题:6 种,让我们重新梳理一下: 源码就是源码,让人豁然开朗,查谷歌众说纷纭、千篇一律,确实都不对! 那么问题答案到此解决?还没有。但现在已经不是刚刚开始了,只差最后一步。 源码内容 不能徒有其表,只看源码文件列表,不看源码内容。 这是关于类型的枚举定义,0 到 6,什么?OBJ_MODULE?这是什么鬼? 请留意这一句描述: * The "module" object type is a special one that signals that the object * is one directly managed by a Redis module. 尤其是 special 一词,这是 special 的类型,其余 6 类都是非 special 类型。既然 special,为什么其枚举值是 5 会夹在 hash 和 stream 的非 special 之间? 历史原因,Redis 4.0 引入了模块扩展功能,当时已经认为是最后一个类型。 但是 Redis 5.0 又引入了 Stream 数据结构,可能是觊觎 Kafka 的市场份额,说白跟 RocketMQ 一样都是仿照 Kafka 去实现的。 言归正传,所以该枚举值的定义是不是跟我们日常业务开发的场景似曾相识,因为状态值编号已经被占了,那么新加的状态值就只能往后面排,导致五花八门一点都不连续。没错,就这么接地气。 那么,module 用在什么场景?有很多场景,举个最常用的例子:Leaky Bucket(漏桶算法),也就是 Redis 4.0 引入的 redis-cell 模块。 示例如下: 那么问题答案到此解决?是的,通过分析源码终于有了结论。 结论 Q:Redis 有哪几种数据类型? A:Redis 6.0 最新版本有且仅有 7 种。 按源码中枚举值定义的顺序,分别为: Q:高级功能类型,比如 HyperLogLog、Bitmap 等呢? A:高级功能类型是对数据类型做 API 封装的应用程序。 HyperLogLog、Bitmap、Bloom Filter 的底层都是 String 数据类型,Geospatial 的底层是 Sorted Set 数据类型,cl.throttle(Redis-Cell) 的底层是 Module 数据类型。均可通过 type KEY_NAME 命令逐一核对。 所以,当面试官下次问你“Redis 数据类型的面试 3 连问”时候,可以好好的怼回去了,让面试官看到你的理解、你对底层逻辑的掌握比面试官本人更系统、更专业,给面试官带来些许的惊喜,相信面试效果会完全不一样。 万一惊喜变成了惊吓怎么办?也许该团队是个固执己见的守旧团队,面试官的考题可能也只是来自照本宣科的题库,那么你可以把你的简历慢慢合上,挥一挥衣袖不带走一片云彩。 最后,Talk is cheap,Show me the code。实践才是检验真理的唯一标准,共勉,请不要再错下去了。 作者:大黄蜂 简介:曾就职于华为、腾讯等大型互联网公司,于 2018 年 5 月加盟独角兽公司 akulaku 担任技术管理职务,对分期、金融借贷等核心系统的架构设计具有丰富的实战经验。精通 Redis 和 JVM,非常重视底层原理,对高级用法、协议、源码等具有深入的研究。并且,具有自己独特的团队管理理念,另辟蹊径,专注研发质量和效率,为公司培养出多名青年高潜,并多次荣获各类表彰。 编辑:陶家龙 征稿:有投稿、寻求报道意向技术人请添加小编微信 gordonlonglong 【原创稿件,合作站点转载请注明原文作者和出处为.com】