1.SDS

简介:Redis没有采用C语言的以空字符串结尾的字符数组,而是构建一种简单动态字符串(Simple dynamic string,SDS),并将它作为string的表示。

struct sdshdr {// buf 中已占用空间的长度int len;// buf 中剩余可用空间的长度int free;// 数据空间char buf[]; // 依然以’\0’结尾
};

SDS与C语言的字符串的区别

  1. 常数复杂度获取字符串长度。
  2. 通过free杜绝缓存区溢出
  3. 空间预分配(如果len小于1MB,那么分配的free将等于len,如果len大于1MB那么分配free1MB)和惰性空间释放(缩短SDS时不立即回收内存而是记录到free中)
  4. 二进制安全,所以能保存图片,视频,音频文件
    常用操作:

    • get:sdsrange—O(n)
    • set:sdscpy—O(n)
    • create:sdsnew—O(1)
    • len:sdslen—O(1)
        

2.链表

typedef struct listNode {// 前置节点struct listNode *prev;// 后置节点struct listNode *next;// 节点的值void *value;} listNode;typedef struct list {// 表头节点listNode *head;// 表尾节点listNode *tail;// 节点值复制函数void *(*dup)(void *ptr);// 节点值释放函数void (*free)(void *ptr);// 节点值对比函数int (*match)(void *ptr, void *key);// 链表所包含的节点数量unsigned long len;} list;

常用操作:

  • rpush: listAddNodeHead —O(1)
  • lpush: listAddNodeTail —O(1)
  • push:listInsertNode —O(1)
  • index : listIndex —O(N)
  • pop:ListFirst/listLast —O(1)
  • llen:listLength —O(N)

3.字典

字典在底层是由哈希表实现的,所以我们从哈希表开始入手。

(1)哈希表

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

(2)哈希节点

typedef struct dictEntry {void *key;union {void *val;uint64_t u64;int64_t s64;} v;// 指向下个哈希表节点,形成链表struct dictEntry *next;

(3)字典

typedef struct dict {// 类型特定函数dictType *type;// 私有数据void *privdata;// 哈希表dictht ht[2];// rehash 索引// 当 rehash 不在进行时,值为 -1int rehashidx; /* rehashing not in progress if rehashidx == -1 */// 目前正在运行的安全迭代器的数量int iterators; /* number of iterators currently running */} dict;

(4)字典特定函数

/** 字典类型特定函数*/
typedef struct dictType {// 计算哈希值的函数unsigned int (*hashFunction)(const void *key);// 复制键的函数void *(*keyDup)(void *privdata, const void *key);// 复制值的函数void *(*valDup)(void *privdata, const void *obj);// 对比键的函数int (*keyCompare)(void *privdata, const void *key1, const void *key2);// 销毁键的函数void (*keyDestructor)(void *privdata, void *key);// 销毁值的函数void (*valDestructor)(void *privdata, void *obj);} dictType;

总结:字典这种数据结构看起来十分复杂,其实十分简单,只要看过Java的HashMap的源代码都应该很容易懂。

注意:
1. 哈希表有一个数据结构,unsigned long sizemask;有什么用呢,就是让本来的 “哈希节点的key % size” 计算出索引变成 “哈希节点的key & sizemask”,位运算更加高效,当然前提是哈希节点是2的x次幂。
2. rehash也是跟Java相似,为什么dict的ht[2]有两个哈希表呢,原来dict[0]是原来的哈希表,dict[1]是扩容后的哈希表。

常用操作:

  • Hset: dictAdd/dictReplace —-O(1)
  • Hget: dictFetchValue—O(1)
  • Randomkey:dictGetRandomKey—O(1)
  • Hdel/del: dictDelete—O(1)

4.整数集合

整数集合是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,Redis就会使用整数集合作为集合键的底层实现。

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

常用操作:

  • sadd:intsetAdd—O(1)
  • smembers:intsetGetO(1)—O(N)
  • srem:intsetRemove—O(N)
  • slen:intsetlen —O(1)

5.压缩列表

压缩列表是列表键和hash键的底层实现之一。当一个列表键只包含少量列表项,并且每个列表项要么就是小整数值,要么就是长度比较短的字符串,那么redis就会使用压缩列表来做列表键的底层实现。

zlbytes代表整个压缩列表占用的内存字节数。
zltail代表压缩列表起始地址到尾节点的偏移量。
zllen节点数量
entry 节点
zlend 0xFF标记压缩列表末端。

常用操作:

  • Push/hset:ziplistPush/ziplistInsert 平均O(N), 最坏O(N2)
  • Llen/hlen:ziplislen平均O(N), 最坏O(N2)
  • Hget:ziplistGet —-O(1)
  • Index:ziplistIndex—-O(N)
  • Hdel/pop:ZiplistDelete—平均O(N), 最坏O(N2)
  • 遍历:ziplistPrev/ziplistNext—-O(1)

6. 对象

字符串对象

字符串对象的编码可以是int,raw,embstr
如果是整数值,则编码是int,如果是小于32字节的字符串,则编码是embstr,如果是大于32字节的字符串,则编码是raw。

下面是他们的对象结构:

embstr和raw的区别是 raw编码调用了两次内存分配函数来分配redisObject结构和sdshdr结构,而embstr只需要调用一次分配一段连续的空间。

列表对象

列表对象的编码可以是ziplist或者linkedlist。

当列表对象可以同时满足一下两个条件时,列表对象使用ziplist编码:
- 列表保存的所有字符串元素的长度都小于64字节;
- 列表对象保存的元素数量小于512个。

不能满足这两个条件的都是用LinkedList编码。

下面就是这个对象的两种编码的结构:

每个StringObject实际上就是一个sdshdr。

哈希对象

哈希对象的编码可以是ziplist或者是hashtable。

当哈希对象同时满足以下两个条件时,哈希对象使用ziplist对象:
- 哈希对象保存的所有键和值的字符串长度都小于64个字节;
- 哈希对象保存的键值对数量小于512个

不能满足这两个条件的哈希对象需要使用hashtable编码。

下面就是这个对象的两种编码的结构:

集合对象

集合对象的编码可以是intset和hashtable

当集合对象同时满足以下条件时,对象使用intset编码:
- 集合对象保存的所有元素都是整数值
- 集合对象保存的元素数量不超过512个

不能满足这两个条件的集合对象需要使用hashtable编码。

下面就是这个对象的两种编码的结构:

有序集合对象

有序集合对象的编码可以是ziplist和skiplist

当集合对象同时满足以下条件时,对象使用intset编码:
- 有序集合保存的元素数量小于128个
- 有序集合保存的所有元素成员的长度都小于64字节

不能满足这两个条件的集合对象需要使用skiplist编码。

下面就是这个对象的两种编码的结构:

ziplist编码的有序集合对象其实跟集合对象的差不多,区别是集合元素按分值从小到大进行排序。

7.对象的引用计数

因为C语言并不具备自动内存回收功能,所以redis对象系统构建了一个引用计数refcount技术来实现内存回收机制,通过这一机制,程序可以通过跟踪对象的引用计数信息,在适当的时候自动释放对象进行内存回收。

  对象的引用计数信息会随着对象的使用状态而不断变化:

  • 在创建一个新对象时,引用计数的值会被初始化为1;
  • 当对象被一个新程序使用时,它的引用计数值会被增1
  • 当对象不再被一个程序使用时,它的引用计数会减1
  • 当对象的引用计数为0时,对象所占用的内存会被释放。

redis学习之数据结构与对象(一)相关推荐

  1. 【Redis笔记】数据结构和对象:字典

    字典:是保存键值对的抽象数据结构. 在字典中,一个键(Key)可以和一个值(value)进行关联(键映射为值),这些关联的键和值就成键值对. 字典中的每个键是独一无二的,程序可以通过键来查找值,或者通 ...

  2. 【Redis笔记】数据结构与对象:链表

    链表在Redis中的应用: 列表键的底层实现之一是链表: 发布与订阅,慢查询,监视器等功能也用到了链表: Redis服务器本身使用链表保存多个客户端的状态信息: 使用链表来构建客户端输出缓冲区: 链表 ...

  3. Redis实战(2)-数据结构之字符串String实战之存储对象

    概述:本系列博文所涉及的相关内容来源于debug亲自录制的实战课程:缓存中间件Redis技术入门与应用场景实战(SpringBoot2.x + 抢红包系统设计与实战),感兴趣的小伙伴可以点击自行前往学 ...

  4. 十二张图带你了解 Redis 的数据结构和对象系统

    来自公众号:程序员历小冰 Redis是一个开源的 key-value 存储系统,它使用六种底层数据结构构建了包含字符串对象.列表对象.哈希对象.集合对象和有序集合对象的对象系统.今天我们就通过12张图 ...

  5. 十二张图详解Redis的数据结构和对象系统

    回顾:大数据平台技术栈 (ps:可点击查看),今天就来说说其中的Redis! 本文来自:张狗蛋的技术之路 Redis是一个开源的 key-value 存储系统,它使用六种底层数据结构构建了包含字符串对 ...

  6. redis(2)--数据结构与对象

    简单动态字符串 (SDS)simple dynamic string 定义 struct sdshdr {// 记录 buf 数组中**已使用**字节的数量 // 等于 SDS 所保存字符串的长度 i ...

  7. 【Redis-09】面试题之Redis数据结构与对象-RedisObject(下篇)

     承接上篇[Redis-08]面试题之Redis数据结构与对象-RedisObject(上篇) 8. type-字符串string 8.1 字符串的三种encoding编码(int + embstr ...

  8. Redis 的数据结构和对象系统 侵立删

    Redis是一个开源的 key-value 存储系统,它使用六种底层数据结构构建了包含字符串对象.列表对象.哈希对象.集合对象和有序集合对象的对象系统.今天我们就通过12张图来全面了解一下它的数据结构 ...

  9. redis之数据结构与对象篇(终章)

    欢迎阅读大魔王的睡前私语系列,这是Redis第四篇文章 压缩列表 压缩列表是列表键和哈希键的底层实现之一.当一个列表键只包含少量列表项,并且每个列表项要么是小整数值,要么是长度比较短的字符串,那么Re ...

最新文章

  1. SmsManager#sendTextMessage的BUG
  2. python 回文链表
  3. BASIC-13 数列排序
  4. lisp eval apply_SICP远古魔法-LISP概览(1-2)
  5. 35岁的互联网人出路在哪?
  6. javascript数组对象
  7. pyinstaller 打包出现问题
  8. 翁恺java答案第五周_[JAVA]翁恺老师零基础学java语言第五周素数例题中continue的困惑...
  9. 使用SQL查询所有数据库名和表名
  10. altium Designer布等长线、蛇形线
  11. 电大计算机绘图三锥图形,电大机械制图课程教学辅导
  12. polyval polyvalm
  13. PS4 5.05安装Linux系统,PS4主机刷机教程以及游戏安装教程,到5.05 4.55 4.05等系统
  14. 【转】欧姆龙FINS通讯命令实例详解
  15. Image Pro Plus6进行荧光分析与荧光照片合成学习笔记
  16. Java学习---控制流程与方法
  17. QR码国家标准(图片和表格后续会更新)
  18. 人机情绪互通:新的机器学习模型可以预测人类情绪
  19. 深入了解 Swarm:去中心化存储和通信系统
  20. Windows XPE 安装

热门文章

  1. Duilib教程-控件练习
  2. 【玩转cocos2d-x之三十一】弱联网与服务器的通讯
  3. 私有化仓库的 GO 模块使用实践
  4. 什么是缓存?为什么要使用Redis?
  5. Error:java: 无效的标记 -version 编译错误的解决办法
  6. 搞定 Go 语言,不会这些可不行
  7. 使用VMware VSphere WebService SDK进行开发 (三)——获取主机(HostSystem)的基本信息
  8. 音视频技术开发周刊 | 238
  9. LiveVideoStackCon2019北京 八月再聚
  10. 2018:WebRTC开发五大趋势