Redis入门到放弃系列-redis数据类型

Redis数据类型?

Redis 提供一些常用的数据类型:Strings、Lists、Sets、Sorted sets、Hashes、Arrays、Bitmap、Streams

Strings(字符串)

Redis中的字符串类型是一比较简单的值类型,和Memcached的数据类型是一样的。
Redis中的key都字符串结构,我们在使用string类型时,其实就是将字符串(key)映射到另一个字符(value).
常用作一些字符串的业务内容缓存;当然,也可以将其它Object业务对像序列化为字符串之后保存。
字符串类型的常用操作命令:

set get mset mget incr

数据结构:

struct sdshdr{
    //记录buf数组中已使用字节的数量
    int len;
    //记录buf数组中未使用的数量
    int free;
    //字节数组,用于保存字符串
    char buf[];
}

注:Redis在内部存储string过程中为了提高性能,做了很多优化。并不是所有的string都是用sds数据结构保存。

数据结构 条件
整数 字符串长度小于21且能够转化为整数的字符串
EmbeddedString 字符串长度小于39的字符串(REDIS_ENCODING_EMBSTR_SIZE_LIMIT)
SDS 其它情况,使用sds进行存储

Lists(列表)

Redis中的列表类型是简单的字符串列表,按照插入顺序排序,可以快速在列表头部或尾部插入元素。该类型类似Java中的LinkedList实现。
Redis Lists使用场景:热点数据列表、还可用作简单的生产-消费队列
Lists的常用操作命令:

rpush/lpush lrange rpop/lpop brpop/blpop

数据结构:

typedef struct listNode{
    //前置节点
    struct listNode *prev;
    //后置节点
    struct listNode *next;
    //节点的值
    struct value;
}

在这里插入图片描述
在这里插入图片描述

Sets(集合)

Redis中的Set是无序字符串集合,集合是通过哈希表实现的,提供了求交集、并集、差集等操作。
集合的常用操作命令:

sadd/smembers sinter spop sunionstore

在这里插入图片描述

Sorted sets(有序集合)

Redis中的有序集合是无序集合与哈希的混合结构,并且不允许有重复的成员。有序集合中的每个元素都与一个float值的score关联。
有序集合中的元素与元素的score的大小一一对应。
常用操作命令:

zadd zrange zrevrange zrangebyscore

数据结构:

typedef struct zskiplistNode{
    //后退指针
    struct zskiplistNode *backward;
    //分值
    double score;
    //成员对象
    robj *obj;
    //层
    struct zskiplistLever{
        //前进指针
        struct zskiplistNode *forward;
        //跨度
        unsigned int span;
    }lever[];
}
    
typedef struct zskiplist{
    //表头节点跟表尾结点
    struct zskiplistNode *header, *tail;
    //表中节点的数量
    unsigned long length;
    //表中层数最大的节点的层数
    int lever;
}

跳跃表,基于多指针有序链实现,可以看作多个有序链表。
与红黑树等平衡树相比,跳跃表具有以下优点:

  • 插入速度非常快速,因为不需要进行旋转等操作来维持平衡性。
  • 更容易实现。
  • 支持无锁操作。

在这里插入图片描述

Hashes(字典)

Redis中的Hash类型是一种键值对集合(field->value),比较适合存放对象。
字典的常用操作命令:

hset/hget hmget/hmset

数据结构:

dictht是一个散列表结构,使用拉链法保存哈希冲突的dictEntry。

typedef struct dictht{
    dictEntry **table; //哈希表数组
    unsigned long size;  //哈希表大小
    unsigned long sizemask; //哈希表大小掩码,用于计算索引值
    unsigned long used; //该哈希表已有节点的数量
}
typedef struct dictEntry{
    //键
    void *key;
    //值
    union{
        void *val;
        uint64_tu64;
        int64_ts64;
    }
    struct dictEntry *next;
}

Redis的字典dict中包含两个哈希表dictht,这是为了方便进行rehash操作。在扩容时,将其中一个dictht上的键值对rehash到另一个dictht上面,完成之后释放空间并交换两个dictht的角色。

typedef struct dict {
    dictType *type;
    void *privdata;
    dictht ht[2];
    long rehashidx; /* rehashing not in progress if rehashidx == -1 */
    unsigned long iterators; /* number of iterators currently running */
} dict;

rehash操作并不是一次性完成、而是采用渐进式方式,目的是为了避免一次性执行过多的rehash操作给服务器带来负担。
渐进式rehash通过记录dict的rehashidx完成,它从0开始,然后没执行一次rehash例如在一次 rehash 中,要把 dict[0] rehash 到 dict[1],这一次会把 dict[0] 上 table[rehashidx] 的键值对 rehash 到 dict[1] 上,dict[0] 的 table[rehashidx] 指向 null,并令 rehashidx++。
在 rehash 期间,每次对字典执行添加、删除、查找或者更新操作时,都会执行一次渐进式 rehash。
采用渐进式rehash会导致字典中的数据分散在两个dictht中,因此对字典的操作也会在两个哈希表上进行。
例如查找时,先从ht[0]查找,没有再查找ht[1],添加时直接添加到ht[1]中。

在这里插入图片描述

Bitmap(位图)

Redis中的Bitmap不是具体的数据类型,其实就是byte数组,用二进制表示,只有0和1,最大优点之一,存储信息时提供极高的空间节省。
Bitmap实际上是在String类型上定义了一组位操作,最大长为为512M
常用操作命令:setbit/getbit bitop bitcount bitpos
在这里插入图片描述

posted @ 2021-03-27 17:40  IT码农-三叔  阅读(58)  评论(0)    收藏  举报