【Redis笔记-3】Redis数据类型

来源:互联网 发布:张大奕淘宝店叫啥 编辑:程序博客网 时间:2024/05/17 17:43

0 本文目录

  • 本文目录
  • 开篇明志
  • redisObject 内部实现
  • 编码和底层实现
  • 操作对象时发生了什么
  • 字符串

1 开篇明志

在前一章《【Redis笔记-2】内部数据结构》 中介绍了Redis内部的数据结构:

  • 简单动态字符串sds
  • 双端链表
  • 字典
  • 跳跃表

Redis的内存映射数据结构:

  • 整数集合
  • 压缩列表ziplist

从本章开始,将介绍数据结构是如何在redis中工作的。


2.redisObject 内部实现

Redis 并没有直接使用这些数据结构来实现键值对数据库, 而是基于这些数据结构创建了一个对象系统。

对象整体设计思路:

  • redisObject对象
  • 基于redisObject对象的类型检查
  • 基于redisObject对象的显式多态函数
  • 对redisObject进行分配、共享和销毁的机制

由于 Redis 是C开发的, 所以通过结构体来模仿对象的“多态”,void *ptr 可以指向任意数据类型。

Redis 中的每个对象都由一个 redisObject 结构表示。

redisObject的定义:

/* * Redis 对象 */typedef struct redisObject {    // 类型    unsigned type:4;    // 对齐位    unsigned notused:2;    // 编码方式    unsigned encoding:4;    // LRU 时间(相对于 server.lruclock)    unsigned lru:22;    // 引用计数    int refcount;    // 指向对象的值    void *ptr;} robj;

其中type、encoding、ptr是最重要的3个属性:

  • type:redisObject的类型,字符串、列表、集合、有序集、哈希表
类型常量 对象的名称 REDIS_STRING 字符串对象 REDIS_LIST 列表对象 REDIS_HASH 哈希对象 REDIS_SET 集合对象 REDIS_ZSET 有序集合对象
  • encoding:底层实现结构,字符串、整数、跳跃表、压缩列表等
  • ptr:实际指向保存值的数据结构

这里写图片描述

3.编码和底层实现

Examples:

  • 如果一个redisObject对象:

    • type = REDIS_LIST ,
    • encoding = REDIS_ENCODING_LINKEDLIST
      那么这个对象就是一个 Redis 列表,它的值保存在一个双端链表内,而 ptr 指针就指向这个双端链表;

  • 如果一个redisObject对象:
    • type = REDIS_HASH
    • encoding = REDIS_ENCODING_ZIPMAP
      那么这个对象就是一个 Redis 哈希表,它的值保存在一个 zipmap 里,而 ptr 指针就指向这个 zipmap 。

对象的 ptr 指针指向对象的底层实现数据结构, 而这些数据结构由对象的 encoding 属性决定。

encoding 属性记录了对象所使用的编码, 也即是说这个对象使用了什么数据结构作为对象的底层实现。

编码常量 编码所对应的底层数据结构 REDIS_ENCODING_INT long 类型的整数 REDIS_ENCODING_EMBSTR embstr 编码的简单动态字符串 REDIS_ENCODING_RAW 简单动态字符串 REDIS_ENCODING_HT 字典 REDIS_ENCODING_LINKEDLIST 双端链表 REDIS_ENCODING_ZIPLIST 压缩列表 REDIS_ENCODING_INTSET 整数集合 REDIS_ENCODING_SKIPLIST 跳跃表和字典

每种类型的对象都至少使用了两种不同的编码, 下面表格展示了每种数据类型可以使用的编码类型。

可以理解为 (一种数据结构) : (多个数据编码), 一对多的形式。

类型 编码 对象 REDIS_STRING REDIS_ENCODING_INT 使用整数值实现的字符串对象。 REDIS_STRING REDIS_ENCODING_EMBSTR 使用 embstr 编码的简单动态字符串实现的字符串对象。 REDIS_STRING REDIS_ENCODING_RAW 使用简单动态字符串实现的字符串对象。 REDIS_LIST REDIS_ENCODING_ZIPLIST 使用压缩列表实现的列表对象。 REDIS_LIST REDIS_ENCODING_LINKEDLIST 使用双端链表实现的列表对象。 REDIS_HASH REDIS_ENCODING_ZIPLIST 使用压缩列表实现的哈希对象。 REDIS_HASH REDIS_ENCODING_HT 使用字典实现的哈希对象。 REDIS_SET REDIS_ENCODING_INTSET 使用整数集合实现的集合对象。 REDIS_SET REDIS_ENCODING_HT 使用字典实现的集合对象。 REDIS_ZSET REDIS_ENCODING_ZIPLIST 使用压缩列表实现的有序集合对象。 REDIS_ZSET REDIS_ENCODING_SKIPLIST 使用跳跃表和字典实现的有序集合对象。

4.操作对象时发生了什么

  • 根据key,查看数据库中是否存在对应的redisObject,没有就返回null
  • 查看redisObject的type是否和要执行的操作相符
  • 根据redisObject的encoding属性选择对应的数据结构
  • 返回处理结果

此外,Redis还是用共享内存。通过预分配一些常见的值对象,并在多个数据结构之间共享这些对象,避免了重复分配,节约内存。同时也节省了CPU时间

如图所示:
这里写图片描述

三个列表的值分别为:

  • 列表 A : [20130101, 300, 10086]
  • 列表 B : [81, 12345678910, 999]
  • 列表 C : [100, 0, -25, 123]

最后,Redis 通过引用计数技术实现了对象共享机制, 通过让多个数据库键共享同一个对象来节约内存。 同时,如果在发现被引用数量为0时候,就可以回收了。

本部分写作时间: 12.05.2017


5.字符串

未完待续……

0 0
原创粉丝点击