https://www.jianshu.com/p/28138a5371d0

系列

redis数据淘汰原理
redis过期数据删除策略
redis server事件模型
redis cluster mget 引发的讨论
redis 3.x windows 集群搭建
redis 命令执行过程
redis string底层数据结构
redis list底层数据结构
redis hash底层数据结构
redis set底层数据结构
redis zset底层数据结构
redis 客户端管理
redis 主从同步-slave端
redis 主从同步-master端
redis 主从超时检测
redis aof持久化
redis rdb持久化
redis 数据恢复过程
redis TTL实现原理
redis cluster集群建立
redis cluster集群选主

set底层存储

 redis的集合对象set的底层存储结构特别神奇,我估计一般人想象不到,底层使用了intset和hashtable两种数据结构存储的,intset我们可以理解为数组,hashtable就是普通的哈希表(key为set的值,value为null)。是不是觉得用hashtable存储set是一件很神奇的事情。

 set的底层存储intset和hashtable是存在编码转换的,使用intset存储必须满足下面两个条件,否则使用hashtable,条件如下:

  • 结合对象保存的所有元素都是整数值
  • 集合对象保存的元素数量不超过512个

 hashtable的数据结构应该在前面的hash的章节已经介绍过了,所以这里着重讲一下intset这个新的数据结构好了。

intset的数据结构

 intset内部其实是一个数组(int8_t coentents[]数组),而且存储数据的时候是有序的,因为在查找数据的时候是通过二分查找来实现的。


typedef struct intset {// 编码方式uint32_t encoding;// 集合包含的元素数量uint32_t length;// 保存元素的数组int8_t contents[];} intset;

intset存储结构

redis set存储过程

 以set的sadd命令为例子,整个添加过程如下:

  • 检查set是否存在不存在则创建一个set结合。
  • 根据传入的set集合一个个进行添加,添加的时候需要进行内存压缩。
  • setTypeAdd执行set添加过程中会判断是否进行编码转换。
void saddCommand(redisClient *c) {robj *set;int j, added = 0;// 取出集合对象set = lookupKeyWrite(c->db,c->argv[1]);// 对象不存在,创建一个新的,并将它关联到数据库if (set == NULL) {set = setTypeCreate(c->argv[2]);dbAdd(c->db,c->argv[1],set);// 对象存在,检查类型} else {if (set->type != REDIS_SET) {addReply(c,shared.wrongtypeerr);return;}}// 将所有输入元素添加到集合中for (j = 2; j < c->argc; j++) {c->argv[j] = tryObjectEncoding(c->argv[j]);// 只有元素未存在于集合时,才算一次成功添加if (setTypeAdd(set,c->argv[j])) added++;}// 如果有至少一个元素被成功添加,那么执行以下程序if (added) {// 发送键修改信号signalModifiedKey(c->db,c->argv[1]);// 发送事件通知notifyKeyspaceEvent(REDIS_NOTIFY_SET,"sadd",c->argv[1],c->db->id);}// 将数据库设为脏server.dirty += added;// 返回添加元素的数量addReplyLongLong(c,added);
}

 稍微深入分析一下set的单个元素的添加过程,首先如果已经是hashtable的编码,那么我们就走正常的hashtable的元素添加,如果原来是intset的情况,那么我们就需要进行如下判断:

  • 如果能够转成int的对象(isObjectRepresentableAsLongLong),那么就用intset保存。
  • 如果用intset保存的时候,如果长度超过512(REDIS_SET_MAX_INTSET_ENTRIES)就转为hashtable编码。
  • 其他情况统一用hashtable进行存储。
/** 多态 add 操作** 添加成功返回 1 ,如果元素已经存在,返回 0 。*/
int setTypeAdd(robj *subject, robj *value) {long long llval;// 字典if (subject->encoding == REDIS_ENCODING_HT) {// 将 value 作为键, NULL 作为值,将元素添加到字典中if (dictAdd(subject->ptr,value,NULL) == DICT_OK) {incrRefCount(value);return 1;}// intset} else if (subject->encoding == REDIS_ENCODING_INTSET) {// 如果对象的值可以编码为整数的话,那么将对象的值添加到 intset 中if (isObjectRepresentableAsLongLong(value,&llval) == REDIS_OK) {uint8_t success = 0;subject->ptr = intsetAdd(subject->ptr,llval,&success);if (success) {// 添加成功// 检查集合在添加新元素之后是否需要转换为字典// #define REDIS_SET_MAX_INTSET_ENTRIES 512if (intsetLen(subject->ptr) > server.set_max_intset_entries)setTypeConvert(subject,REDIS_ENCODING_HT);return 1;}// 如果对象的值不能编码为整数,那么将集合从 intset 编码转换为 HT 编码// 然后再执行添加操作} else {setTypeConvert(subject,REDIS_ENCODING_HT);redisAssertWithInfo(NULL,value,dictAdd(subject->ptr,value,NULL) == DICT_OK);incrRefCount(value);return 1;}// 未知编码} else {redisPanic("Unknown set encoding");}// 添加失败,元素已经存在return 0;
}

redis底层数据结构相关推荐

  1. 保存到redis的字符串类型出现斜杆_深入浅出Redis:这次从Redis底层数据结构开始...

    1.概述 相信使用过Redis 的各位同学都很清楚,Redis 是一个基于键值对(key-value)的分布式存储系统,与Memcached类似,却优于Memcached的一个高性能的key-valu ...

  2. redis底层数据结构之跳跃表

    redis底层数据结构之跳跃表 redis 的zset有序连表为啥选择用跳跃表? 我们要思考一问题,首先多问问自己为什么,才容易理解它,ps:这是个人观点.首先我们选择的数据结构和算法原因有以下几种: ...

  3. 02 Redis 底层数据结构

    一.不同数据类型存储结构 Redis底层数据结构一共有 6 种,分别是简单动态字符串.双向链表.压缩列表.哈希表.跳表和整数数组.它们和数据类型的对应关系如下图所示: 1 数组与链表的区别 数组和链表 ...

  4. Redis底层数据结构详解(一)

    Redis底层数据结构 一.简单动态字符串SDS 1. SDS 2. 为什么Redis没用C语言原生字符串? 2.1 C语言中的字符串 2.2 使用SDS的好处 二.链表linkedlist 三.压缩 ...

  5. Redis面试题-Redis底层数据结构

    本文参考 嗨客网 Redis面试题 Redis底层数据结构 Redis 的五大数据类型也称五大数据对象,即分别为 string. list. hash. set 和 zset,但 Redis 并没有直 ...

  6. Redis底层数据结构详解

    Redis底层数据结构详解 我们知道Redis常用的数据结构有五种,String.List.Hash.Set.ZSet,其他的集中数据结构基本上也是用这五种实现的,那么,这五种是Redis提供给你的数 ...

  7. redis底层数据结构简述

    2019独角兽企业重金招聘Python工程师标准>>> redis的数据库对象有五种,分别是字符串对象(key-value),列表对象(list),哈希对象(hash),集合对象(s ...

  8. Redis底层数据结构介绍

    文章目录 前言 1. 哈希表 2. 简单动态字符串 使用SDS的好处 对比C字符串 3. 压缩列表 4. 跳表 5. 整数集合.双向链表 Redis数据类型与底层数据结构对照表 前言 一谈到Redis ...

  9. Redis——底层数据结构原理

    摘要 Redis 发展到现在已经有 9 种数据类型了,其中最基础.最常用的数据类型有 5 种,它们分别是:字符串类型.列表类型.哈希表类型.集合类型.有序集合类型,而在这 5 种数据类型中最常用的是字 ...

  10. Redis底层数据结构(图文详解)

    目录 前言 Redis为什么要使用2个对象?两个对象的好处 redisObject对象解析 String 类型 1.int 整数值实现 2.embstr 3.raw List 类型 1.压缩链表:zi ...

最新文章

  1. 安全保密领域人工智能的应用
  2. python读取txt文件写入-python 读取、写入txt文件的示例
  3. printf输出字符串_C语言入门必学第一课,学习“输入与输出”!
  4. Fluent Ribbon 第三步 应用程序菜单
  5. 利用matlab实现SAR 图像线性拉伸显示
  6. InfluxDB学习之InfluxDB数据保留策略(Retention Policies)
  7. Map集合根据key,value排序
  8. javascript示例代码
  9. 计算机类专业工程认证,计算机类专业工程教育专业认证补充标准
  10. exoplay切换全屏_ExoPlayer播放视频的简单使用及播放视频宽高设置的源码分析
  11. 克鲁斯卡尔算法、并查集
  12. 将数字0-9转为中文大写数字
  13. 专为mac用户设计的苹果手机助手。爱思助手 Mac版结构更清晰,功能更好用,界面更清晰,让你能够轻松查看设备信息,下载最新最火的应用游戏。
  14. CYPRESS S6E1C3 系列 FM0+ 32位单片机串口uart0 问题
  15. Java基础笔记-Java8及其他新特性
  16. 计算机软著在线登记,计算机软件著作权登记收费标准
  17. 时间戳转换为String
  18. xff头使用sqlmap注入(心血来潮的分享)
  19. RadioButton的排版,图标样式修改和图标文字间距修改
  20. 王者荣耀小游戏3.0更新完成!

热门文章

  1. intellij idea下载安装以及创建项目(输出Hello World)
  2. 二维凸包 Graham扫描算法
  3. 软件需求与分析——大二下需会知识点
  4. 微信小程序------开发测试
  5. 软件工程概论网站系统开发基础及目标概述
  6. DataNucleus之JDO操作演示样例
  7. 如何开启VMware串口
  8. jumpserver跳板机docker安装小小趟坑
  9. Docker客户端连接Docker Daemon的方式
  10. Spark官方3 ---------Spark Streaming编程指南(1.5.0)