Redis 常见数据类型的使用场景以及底层结构

2023-11-01

前言

Redis 是一种基于内存的高性能的键值存储系统,支持多种数据类型、持久化、高可用集群等。在 Redis 中,每种数据类型都有自己独特的底层实现方式,这些实现方式直接影响着 Redis 的性能。本文将介绍 Redis 各种数据类型的使用场景以及底层结构实现方式。

在介绍类型之前,不妨先了解下 Redis 在 C 语言中的结构长什么样?
redis struct

大概的结构如上图所示(并未列出所有字段,在文末会将具体的 C 语言结构列出),其实 Redis 的所有数据类型都是用同一张外层哈希表(ht[2])来保存的,通过 key 可以定位这个数据需要保存在 entry 数组的哪个位置,因为 dictEntry 的值是 viod* 表示任意类型(一般为 redisObject),所以不伦是 string、int、ziplist、linkedlist、intset、hashtable、skiplist 等都能支持。

为什么需要定义为 dictht dt[2] 呢?
这里的 ht[2] 数组,一个用来存储正常的数据,另一个是扩容时渐进式 rehash 时使用。由于 redis 扩容需要 rehash,如果一次性把所有的数据都进行 rehash 操作的话会导致线程阻塞,严重影响性能,因此在每次扩容时先把一部分数据先迁移到新的 ht 中,后续再渐进式的迁移,直到全部完成时释放掉旧的 ht。需要注意的是,在访问数据的时候,两个 ht 都需要去查找,新加的数据会被放到新的 ht 中。


数据类型构成及使用场景

String类型

String 类型的值最大长度为 512MB,它是 Redis 最简单的数据类型,也是我们用的最多的一种,类似我们平常使用的 HashMap 都是键值对,底层结构实现方式也是最简单的。在 Redis 中,字符串类型的值被实现为一个简单的动态字符串,即 RedisObject 结构体。
这里的 String 并不是所有的都保存为 String,如果保存整数、浮点数,Redis 也只会保存整数、浮点数,并不一定为 String。

使用场景
  • 用来做计数器
  • 分布式锁
  • 当分布式的 HashMap 使用

Hash 类型

Hash 是一个键值对集合,类似于关联数组。哈希表类型的值是一个由多个键值对组成的无序集合。可以快速地查找某个键对应的值,还可以对键值对进行批量操作。
当数量不多时使用 ziplist 实现,键值对也是按照在 ziplist 中的对应顺序去取,如 hmset hkey a 1 b 2,存在 ziplist 的顺序为[a, 1, b, 2] ;当 ziplist 中的元素数量超过 hash-max-ziplist-entries(默认为 512)时,Redis 会将其转换为 hashtable。此外,当哈希表中的某个元素的大小超过 hash-max-ziplist-value(默认为 64 字节)时,Redis 也会将其转换为 hashtable。

使用场景
  • 存储对象属性

List 类型

List 数据类型是一种双向链表的结构,支持在链表头部或尾部进行元素的添加、删除和查找,因此它可以用来表示队列或者栈等数据结构。List 的每个节点都存储了一个字符串类型的值,这些节点之间通过指针进行链接,从而形成了一个链表。
当数据量不多时,使用 ziplist 实现,达到一定数量时(list-max-ziplist-entries=512),为了减少更新操作对 ziplist 的影响,会将这些 ziplist 分段,并用 linkedlist 连接。

使用场景
  • 消息队列
  • 简单的发布订阅

Set 类型

Set 是一种无序的不重复的数据类型,类似于 Java 中的 Set 接口,它能进行稽核的交并差集计算。
如果保存的是整型数据且数据较少(server.set_max_intset_entries=512)时,则使用 intset 来保存,intset 其实就是一个数组,添加时需要判重;当不是整数或者超过数据限制最大值时将使用 Hashtable 实现。

使用场景
  • 记录 websocket 连接数
  • 记录网站的 IP 白名单、IP 黑名单等
  • 社交关系:某个用户的粉丝列表、关注列表、好友列表
  • 点赞收藏:存储某个微博的点赞用户 ID、收藏用户 ID

ZSet 类型

ZSet 作用于 Set 类似,只不过它是有序的,可以通过 score 进行排序,可以按照分数去做排名操作。
它的底层在数据量少的时候同样的使用的是 ziplist 达到一定数量后才转为 skiplist

使用场景
  • 通过将 score 设置为时间戳来实现延时队列
  • 某网红直播间的排行榜,可以清楚的知道榜一大哥

其他

文章开头说的,Redis 在 C 语言中的结构代码(为了代码顺序好看,不考虑报错):

typedef struct redisServer {
    redisDb *db;    // 数据库数组
    int dbnum;    // 数据库数量
    dict *commands;    // Redis 命令表
    dict *lua_scripts;    // Lua 脚本缓存
    // ...
} redisServer;

typedef struct redisDb {
    dict *dict;    // 数据库的键值对存储在这里
    dict *expires;    // 存储所有键的过期时间
    dict *blocking_keys;    // 存储被阻塞的键
    dict *ready_keys;    // 存储已经就绪的键
    dict *watched_keys;    // 存储被 WATCH 命令监视的键
    int id;    // 数据库编号
} redisDb;

typedef struct dict {
    dictType *type;             // 类型特定函数
    void *privdata;             // 私有数据
    dictht ht[2];               // 两个哈希表
    long rehashidx;             // 重哈希进度标记
    unsigned long iterators;    // 正在迭代哈希表的迭代器数量
} dict;

typedef struct dictht {
    dictEntry **table;  // 哈希表数组
    unsigned long size; // 哈希表大小
    unsigned long sizemask; // 哈希表大小掩码,用于计算索引值
    unsigned long used; // 已经使用的节点数量
} dictht;

typedef struct DictEntry {
    void *key;    // 指向键的指针
    union {
        void *val;    // 指向值的指针
        uint64_t u64;    // 64 位无符号整数
        int64_t s64;    // 64 位有符号整数
        double d;    // 双精度浮点数
    } v;
    struct DictEntry *next;    // 哈希冲突时使用,指向下一个哈希表节点的指针
} dictEntry;

还有最重要的 redisObject

 typedef struct redisObject {
    unsigned type:4;       // 对象类型,字符串类型,type 值为 0、列表类型,type 值为 1、哈希表类型,type 值为 2、集合类型,type 值为 3
    unsigned encoding:4;   // 对象编码
    // 引用计数
    unsigned lru:LRU_BITS; /* lru time (relative to server.lruclock) */
    int refcount;
    void *ptr;             // 指向实际值的指针
} robj;

总结

文章一开头就先介绍了 Redis 其实都是通过 key 来共用一张哈希表,不同的数据类型只不过是 val 对应的类型有所区别;并介绍了各种数据类型需要什么数据结构以及在什么使用用哪种,但没有提到很多细节,只是简单的总结;最后给出 c 的结构体源码,这样能够更加清晰的了解他们的存储,但对于类似 ziplistskiplist 等数据结构这里就不作介绍了,不是本文的重点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Redis 常见数据类型的使用场景以及底层结构 的相关文章

随机推荐

  • 使用WinDbg Preview 查看Windows 10蓝屏Dump文件

    从应用商店安装WinDbg Preview 1 登陆应用商店 搜索WinDbg Preview 2 选择获取 我的Windows 10 系统已经安装过了 3 在启动菜单可以找到WinDbg Preview 4 找到蓝屏文件 并选择使用Win
  • 【Github】错误解决:OpenSSL SSL_read: Connection was reset, errno 10054

    git 报错信息 OpenSSL SSL read Connection was reset errno 10054 Git 中 push 或者 pull 报错 OpenSSL SSL read Connection was reset e
  • arthas的trace、watch、tt、profiler命令的使用

    arthas的trace watch tt profiler命令的使用
  • 通过C语言实现小数整数求原码,反码,补码

    通过C语言实现小数 整数求原码 反码 补码 判断输入的值是整数还是小数 是正是负 求纯整数不含符号的原码 求纯小数不含符号的原码 完善整个原码 符号 小数 整数合在一起 将求原码的函数封装在一个函数里 求反码的函数 求补码的函数 main函
  • Linux-线程学习(上)

    本文导航 内容 所占百分比 线程概念 40 线程与进程区别与联系 20 线程优缺点 10 线程控制 创建 终止 等待 30 线程的概念 谈到线程 我们先从进程说起 我们写的程序从硬盘加载到内存开始运行时 进程就产生了 也就是操作系统开始为这
  • 水仙花数(Java实现)

    春天是鲜花的季节 水仙花就是其中最迷人的代表 数学上有个水仙花数 他是这样定义的 水仙花数 是指一个三位数 它的各位数字的立方和等于其本身 比如 153 1 3 5 3 3 3 现在要求输出所有在m和n范围内的水仙花数 import jav
  • 栈溢出原理

    栈溢出原理 文章目录 栈溢出原理 前言 栈 一 栈溢出原理 二 栈保护技术 三 常发生栈溢出的危险函数 四 可利用的栈溢出覆盖位置 总结 前言 栈 栈是一种LIFO的数据结构 应用程序有一到多个用户态栈 栈自底向上增长 由指令PUSH和PO
  • tcpdump抓包注意事项

    使用tcpdump进行抓包 然后用wireshark进行分析的时候 出现了 Packet size limited during capture 也不算是错误 只是数据包里的内容无法完全查看清楚 经过查询 原因是因为我在Linux下进行抓包
  • es6合并对象

    es5 let name name sea age age 15 person Object assign person name age console log person name sea age 15 es6 let name na
  • golang 读取项目配置文件

    golang读取文件配置 介绍golang项目中配置文件的读取相关内容 包括项目结构 具体实现代码等内容 ref 煎鱼 实际上这只是煎鱼博客项目中的一小部分 项目结构 配置读取相关文件结构如下 config文件夹下存放config yaml
  • 大数据从入门到精通(超详细版)之 Hive的配置与基本语法

    前言 嗨 各位小伙伴 恭喜大家学习到这里 不知道关于大数据前面的知识遗忘程度怎么样了 又或者是对大数据后面的知识是否感兴趣 本文是 大数据从入门到精通 超详细版 的一部分 小伙伴们如果对此感谢兴趣的话 推荐大家按照大数据学习路径开始学习哦
  • xman的思维导图快捷键_思维导图软件——MindMaster常用快捷键汇总

    原标题 思维导图软件 MindMaster常用快捷键汇总 思维导图 英文是The Mind Map 又叫心智导图 是表达发散性思维的有效图形思维工具 MindMaster Mac版是最新推出的一款免费跨平台 多功能的思维导图软件 可以帮助您
  • 发明计算机的人的名人名言,60句关于发明的名言

    1 没有艰苦的学习 就没有最简单的科学发明 南斯拉夫谚语 2 需要是发明之母 拉丁谚语 3 天才是不足恃的 聪明是不可靠的 要想顺手拣来的伟大科学发明是不可想象的 华罗庚 4 一项发明创造会带来更多的发明创造 爱默生 5 科学的真正的与合理
  • Selenium下Chrome配置 (含启动无痕界面--无界面浏览器)

    转载 https www cnblogs com kaibindirver p 11432850 html Selenium下Chrome配置 含启动无痕界面 无界面浏览器 例子 设置无界面模式浏览器启动 chrome options we
  • MapReduce shuffle过程详解

    一 MapReduce计算模型 我们知道MapReduce计算模型主要由三个阶段构成 Map shuffle Reduce Map是映射 负责数据的过滤分法 将原始数据转化为键值对 Reduce是合并 将具有相同key值的value进行处理
  • OpenMV4开发笔记4-舵机控制

    OpenMV4的舵机控制脚有3个 P7 P8 P9 即可以控制3个舵机 Servo 1 gt P7 PD12 Servo 2 gt P8 PD13 OpenMV3 M7 OpenMV4 H7上增加 Servo 3 gt P9 PD14 注意
  • 论EI、SCI和ISTP检索论文的收录号和期刊号查询方法

    http www scitsg com Article 134240802101541 aspx 需要申请博士后进站和国家自然科学基金的朋友都知道申请博士后进站和国家自然科学基金需要填写很多申请表格 其中就需要填写所发表的EI SCI和IS
  • Activiti 流程引擎之流程任务创建、部署流程、流程任务启动、查看当前任务、完成当前任务

    1 流程任务创建 1 在项目中创建diagram文件夹 并创建Activiti Diagram文件MyProcess bpmn 2 创建MyProcess bpmn 流程 详情如下 整体结构示意图 右击diagram文件夹 新建一个Acti
  • 折半查找——(递归,非递归C语言实现)

    折半查找 基本概念 1 折半查找 对半查找 二分查找 a 在 有序表 假设为递增 lt 先排序 gt 中 取中间记录作为比较对象 b 若给定值与中间记录相等 则查找成功 若给定值小于中间记录 则在有序表的左半区继续查找 若给定值大于中间记录
  • Redis 常见数据类型的使用场景以及底层结构

    前言 Redis 是一种基于内存的高性能的键值存储系统 支持多种数据类型 持久化 高可用集群等 在 Redis 中 每种数据类型都有自己独特的底层实现方式 这些实现方式直接影响着 Redis 的性能 本文将介绍 Redis 各种数据类型的使