• redis 系列9 对象类型(字符串,哈希,列表,集合,有序集合)与数据结构关系


    一.概述

      在前面章节中,主要了解了 Redis用到的主要数据结构,包括:简单动态字符串、链表(双端链表)、字典、跳跃表、 整数集合、压缩列表(后面再了解)。Redis没有直接使用这些数据结构来实现键值对数据库,而是基于这些数据结构创建一个对象系统,这个系统对象包括:字符串对象、列表对象、哈希对象(散列)、集合对象、有序集合对象这五种类型,每种类型对象都用到了至少一种前面所介绍的数据结构。

      通过这五种不同类型的对象,可以针对不同的使用场景, 在Redis 内部会为对象设置不同的数据结构实现,从而优化对象在不同场景下的使用效率。下面先直观看下关系图(五种对象与type与encoding编码与ptr底层数据结构),然后再来详细介绍它们之间的关系。

            

    二. 对象类型与编码(五种类型的对象)

      Redis中的每个对象都由一个RedisObject结构表示,该结构中和保存数据有关的三个属性分别是type属性、encoding属性、ptr属性。

     typeof struct redisObject{
                //类型
                unsigned type:4;
                //编码
                unsigned encoding:4;
                //指向底层实现数据结构的指针
                void *ptr;
    
                //...
            }robj;

      2.1  type类型

      对象的type属性记录了对象的类型,对于键来说它总是一个字符串对象,而值可以是五种类型,这五种类型如下表格:

    type取值的类型常量

    五种对象的名称

    Type命令输出

    Redis_string

    字符串对象

    string

    Redis_list

    列表对象

    list

    Redis_hash

    哈希对象

    hash

    Redis_set

    集合对象

    set

    Redis_zset

    有序集合对象

    zset

      例1: 下面使用type命令,该命令返回结果为数据库键对应的值对象类型,而不是键对象的类型。

    -- 值为字符串对象
    127.0.0.1:6379> set msg "hello world"
    OK
    127.0.0.1:6379> type msg
    string
    
    -- 值为列表对象
    127.0.0.1:6379> rpush number 1 3 5 
    (integer) 3
    127.0.0.1:6379> type number
    list
    
    -- 值为哈希对象    
    127.0.0.1:6379> hmset profile name tom age 25 career programmer
    OK
    127.0.0.1:6379> type profile
    hash
    
    -- 值为集合对象
    127.0.0.1:6379> sadd fruit apple banana cherry
    (integer) 3
    127.0.0.1:6379> type fruit
    set
    
    -- 值为有序集合对象
    127.0.0.1:6379> zadd price 8.50 apple 3.30 banana
    (integer) 2
    127.0.0.1:6379> type price
    zset    

      2.2 编码和底层实现(encoding, ptr)

        对象的ptr指针指向对象的底层实现数据结构,而这些数据结构由对象的encoding属性决定,encoding记录了对象所使用的编码。使用object encoding命令查看不同编码的输出。表格如下:

        (1) 底层数据结构与encoding编码的对应关系:

    底层数据结构

    encoding编码常量取值

    object encoding 输出

    整数

    Redis_encoding_int

    int

    Embstr编码的SDS字符串(长字符值)

    Redis_encoding_embstr

    embstr

    SDS字符串

    Redis_encoding_raw

    raw

    字典

    Redis_encoding_ht

    hashtable

    链表

    Redis_encoding_linkedlist

    linkedlist

    压缩列表

    Redis_encoding_ziplist

    ziplist

    整数集合

    Redis_encoding_intset

    intset

    跳跃表和字典

    Redis_encoding_skiplist

    skiplist

        (2) 五种对象类型与encoding编码的对应关系

    五种对象类型常量

    对应encoding编码常量

    对象说明

    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

    使用跳跃表和字典实现的有序集合对象

        例2: 下面使用object encoding命令,该命令查看一个数据库键的值对象的编码:

    127.0.0.1:6379> set msg "hello wrold"
    OK
    127.0.0.1:6379> object encoding msg
    "embstr"
    
    127.0.0.1:6379> set story "long long long long long long long long long ..."
    OK
    127.0.0.1:6379> object encoding story
    "raw"
    127.0.0.1:6379> sadd num 1 3 4
    (integer) 0
    127.0.0.1:6379> object encoding num
    "intset"
    
    127.0.0.1:6379> sadd num 1 3 4 "one"
    (integer) 1
    127.0.0.1:6379> object encoding num
    "hashtable"
    
    127.0.0.1:6379> zadd fruit-price 5.0 banana 6.5 cherry 8.0 apple
    (integer) 0
    127.0.0.1:6379> object encoding fruit-price
    "ziplist"
    
    127.0.0.1:6379> rpush integers "1" "2" "3" "4" "5" "6" "7" "8" "9" "10"
    (integer) 20
    127.0.0.1:6379> object encoding integers
    "quicklist"

       

      总结:通过encoding属性来设定对象所使用的编码,而不是为特定类型的对象关联一种固定的编码,极大提升了redis的灵活性和效率。例如:上面演示的zadd fruit-price 添加列表元素,redis使用压缩列表作为列表对象的底层实现,因为压缩列表比链表更节约内存,并且在元素数量较少时,在内存中以连续块方式保存的压缩列表比链表可以更快被载入到缓存中。但随着列表对象元素越来越多时,这种压缩优势就会消失,此时对象就会将底层实现从压缩列表转向链表。 其它类型的对象也会通过使用多种不同的编码来进行类似的优化。

        使用对象key通过Type命令查看value值的对象类型,通过object encoding命令查看value值的底层数据结构。

  • 相关阅读:
    GitLab用户权限管理
    类似vant中的tab实现
    Gitgitee/github/gitlab账号分离
    Vim操作
    partition by 用法
    crontab执行feat_gen.sh时,报错找不到pyspark
    SQL同一个字段出现null和0值,有何区别,原因是什么?left join导致null值出现,case when导致0值出现
    linux 定时任务crontab的用法
    卡方检验
    ROC与AUC
  • 原文地址:https://www.cnblogs.com/MrHSR/p/9952653.html
Copyright © 2020-2023  润新知