前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >盘一盘Redis的底层数据结构

盘一盘Redis的底层数据结构

作者头像
陌溪
发布2022-10-27 10:16:15
7740
发布2022-10-27 10:16:15
举报

大家好,我是陌溪

前言

Redis 是一个高性能的分布式内存数据库,在国内的公司也有着非常广泛的使用场景。因此,在面试过程中,关于 Redis 相关的知识点,也是经常被问到的。

下面这题,就是之前面试的时候遇到过的,让我们一起来学习一下吧~

Redis 有那些数据结构?以及它们的使用场景?

Redis五种数据结构

Redis 为我们提供了 5 种数据结构,分别是以下几种:

  • String(终究是我扛下来所有)
  • Hash(存储对象我也行)
  • List(栈和队列我都行)
  • Set(标签系统我在行)
  • Sort Set(排起名来我最棒)

然而,在我们的实际编程开发中,有大多数的开发者仅仅只会使用简单的 RedisString 类型,也就是里面的 GetSet 方法

当然也包括我,终究还是用 String 扛下了全部

代码语言:javascript
复制
// 设置键值
stringRedisTemplate.opsForValue().set("key", "value");
// 获取键值
stringRedisTemplate.opsForValue().get("key");

下面,就让我们一起来深入学习 Redis5 种数据类型,以便能够在不同的业务场景中游刃有余,而不是做一个只会用 String 的同学。

字符串

字符串类型是 Redis 最基础的数据结构,其他几种数据结构都是在字符串类型基础上构建的。

字符串类型的值是字符串(简单的字符串、复杂的字符串(例如 JSONXML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频)等。

字符串

字符串对象的内部编码有 3 种 :intrawembstrRedis 会根据当前值的类型和长度来决定使用哪种编码来实现

  • int:如果一个字符串对象保存的是整数值,并且这个整数值可以用long类型来表示
  • raw:如果字符串对象保存的是一个字符串值,并且这个字符串值的长度大于32字节
  • embstr:如果字符串对象保存的是一个字符串值,并且这个字符申值的长度小于等于32字节

Reids 字符串的使用场景是最为广泛的,甚至有些对 Redis 其它几种对象不太熟悉的人,基本所有场景都会使用字符串(序列化一下直接扔进去),这让本身很单纯的字符串承受了它这个年纪本不该承受的重量。其实 Redis 的主要使用场景主要有以下几种:

  • 作为缓存层,缓存热点数据
  • Redis 字符串可以自增自减的特性可以用来做计数器、限速器、自增ID生成等
  • 分布式系统的 Session 共享
  • 二进制数据的存储

哈希

哈希对象用来存储一组数据对,每个数据对又包含键值两部分

哈希

Hash对象也有两种实现方式:ziplist(压缩列表)和 hashtable(哈希表)

同样,只有当存储的数据量比较小的情况下,Redis才使用压缩列表来实现哈希对象,具体需要满足两个条件

  • 字典中保存的键和值的大小都要小于 64 字节
  • 字典中键值对的个数要小于 512

当不能同时满足上面的两个条件时,Redis 就使用哈希表来实现Hash对象

当存储的内容是对象的时候,Redis 字符串对象很多功能使用Redis 哈希对象也可以实现,如缓存用户信息的时候,使用 Redis 哈希对象存储,简单直观,如果使用合理可以减少内存空间的使用。

但是也有其缺点,就是要控制哈希在 ziplisthashtable 两种内部编码的转换,hashtable 将会消耗更多的内存。

此外,Hash对象还可以实现购物车和计数器等功能

列表

列表这种对象支持存储一组有序的,且可以重复的数据。因为其有序性,它可以获取指定范围的元素列表,可以在 O(1) 的时间复杂度获取指定索引的下标的元素等。

列表

Redis3.2 版本以前列表类型的内部编码有两种。当满足下面两个条件的时候,Redis 列表对象使用 ziplist(压缩列表)来实现。

  • 当列表的元素个数小于 list-max-ziplist-entries 配置(默认512个)
  • 当列表中每个元素的值都小于 list-max-ziplist-value 配置时(默认64字节)

当列表类型无法满足 ziplist 条件时,Redis会使用linkedList作为列表的内部实现。

而在Redis3.2版本开始怼列表数据结构进行改造,使用quickList代替了zipList和linkedList。

由于列表对象的有序且不可重复的特性,它比较适合用来做文章、商品等列表的存储。

列表类型可以lpush(左侧push),同时又可以使用rpop(右侧弹出)第一个元素,所以列表类型具有先进先出的特性,可以用来实现消息队列,也可以lpush(左侧push)和lpop(左侧弹出),具有后进先出的特性,因此开发中需要使用栈的时候,我们可以使用列表对象来实现。

集合

集合对象是一个无序且唯一的键值集合。它的存储顺序不会按照插入的先后顺序进行存储,与列表不同的是它存储的数据是无序且不重复的。

集合

集合对象的内部编码也有两种,intest(整数集合)与hashtable(哈希表),当满足下面两个条件的时候,集合对象使用intset来实现

  • 集合中的元素都是整数
  • 集合中元素的个数小于 set-maxintset-entries 配置(默认 512 个)

不满足上面两个条件时,集合对象使用hashtable来实现

集合对象的主要两个特性就是:无序不可重复支持并交差,因此可以用来做标签系统

而集合中的 SPOP (随机移除并返回集合中一个或多个元素)和 SRANDMEMBER (随机返回集合中一个或多个元素) 命令可以帮助我们实现一个抽奖系统

有序集合

有序集合类型 ( Sorted SetZSet ) 相比于集合类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序结合的元素值,一个是排序值。有序集合保留了集合不能有重复成员的特性(分值可以重复),但不同的是,有序集合中的元素可以排序。

有序集合

有序集合是由 ziplist (压缩列表)或 skiplist (跳跃表)组成的。

当数据比较少时,有序集合使用的是 ziplist 存储的,有序集合使用 ziplist 格式存储必须满足以下两个条件:

  • 有序集合保存的元素个数要小于 128 个;
  • 有序集合保存的所有元素成员的长度都必须小于 64 字节。

如果不能满足以上两个条件中的任意一个,有序集合将会使用 skiplist 结构进行存储。

有序集合比较典型的使用场景就是排行榜系统例如学生成绩的排名。某视频(博客等)网站的用户点赞、播放排名、电商系统中商品的销量排名等。

小结

Redis 提供了五种最基础也是最常用的对象(数据类型):String、Hash、ListSet、ZSet。了解这五种对象的有助于我们更好的在日常开发中对Redis进行使用。

博主就职于字节跳动商业化部门,一直维护校招笔记仓库 LearningNote「在Gitee上已有 5k star,地址 https://gitee.com/moxi159753/LearningNotes」,公众号上的文章也会在此同步更新,欢迎各位小伙伴一起交流学习,回复 「PDF」获取PDF笔记。

同时,想要丰富项目经验的小伙伴,可以参考我维护的开源微服务博客项目:蘑菇博客「 Gitee 官方推荐项目,博客类搜索排名第一,在 Gitee 已有 4.7K star,仓库地址:https://gitee.com/moxi159753/mogu_blog_v2 」。

本公众号申请较晚,暂时没有开通留言功能,欢迎小伙伴们添加我的私人微信 coder_moxi【备注:加群】,我将邀请你加入到蘑菇博客交流群中,欢迎小伙伴们找陌溪一块聊天唠嗑,共同学习进步。最后,如果你觉得本文对你有所帮助,麻烦小伙伴们动动手指给文章点个「赞」和「在看」,非常感谢大家的支持。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-06-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 陌溪教你学编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • Redis五种数据结构
  • 字符串
  • 哈希
  • 列表
  • 集合
  • 有序集合
    • 小结
    相关产品与服务
    云数据库 Redis
    腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档