Redis五大基本结构

Redis 支持的数据类型

在这里插入图片描述

Redis 五大数据类型

String(字符串)

适用场景:缓存业务信息,且只是根据 key 直接获取缓存 value,不需要排序,去重等功能。

String 是 Redis 种最简单的数据结构,但是却是大家日常使用频率最高的数据结构,它使用简单,并且扩展性非常强,我们可以设置普通的字符串,也可以设置json,存取速度也是最快的。

字符串存储的底层结构其实就是字符数组。

这个字符串是动态的,是可以修改的。内部采用预分配冗余空间的方式来减少内存的频繁分配。

当存储的字符大小 <= 1M ,都是翻倍扩容。

如果存储的字符串大小 >1M ,则每次之扩容1M空间。

示例操作

//复制 test 为 wanji
127.0.0.1:6379[4]> set test wanji
OK
// 获取 test 的 value 值
127.0.0.1:6379[4]> get test
"wanji"
//查看这个数据库下所有的key
127.0.0.1:6379[4]> keys *
1) "test"
//删除 test
127.0.0.1:6379[4]> del test
(integer) 1
127.0.0.1:6379[4]> keys *
(empty array)
//一次性设置多个值 mset value key value key
127.0.0.1:6379[4]> mset hello world java best
OK
//获取多个值
127.0.0.1:6379[4]> mget hello java
1) "world"
2) "best"

127.0.0.1:6379[4]> set sex 18
OK
//key值自增
127.0.0.1:6379[4]> incr sex
(integer) 19

127.0.0.1:6379[4]> get sex
"19"
//key值自减
127.0.0.1:6379[4]> decr sex
(integer) 18

127.0.0.1:6379[4]> get sex
"18"
//key值自增指定步长
127.0.0.1:6379[4]> incrby sex 2
(integer) 20

127.0.0.1:6379[4]> get sex
"20"
//key值自减指定步长
127.0.0.1:6379[4]> decrby sex 2
(integer) 18

ttl

如果键有设置过期时间,当键过期或者被删除了,TTL 命令返回-2,当键没有设置过期时间,表示是永久的,TTL 命令 返回 -1

127.0.0.1:6379[4]> ttl test
(integer) -1
/*设置 test
注意:注意,假如 test 已存在,那么该语句会更新 test 的 value 为 wanji,并且过期时间设置为 10 秒
*/
127.0.0.1:6379[4]> expire test 10
(integer) 1
127.0.0.1:6379[4]> setex test 10 wanji
OK
//查看 test 还有多久过期
127.0.0.1:6379[4]> ttl test
(integer) -2
//如果 test 存在,就不赋
127.0.0.1:6379[4]> setnx test bob
(integer) 1
127.0.0.1:6379[4]> get test
"bob"
//计算 value 值长
127.0.0.1:6379[4]> strlen test
(integer) 3

在这里插入图片描述

字符串内部实现——int编码&raw编码&embstr编码

在这里插入图片描述

在这里插入图片描述

3种encoding:什么情况下,选择哪种encoding?

  • int

    设置为 long 类型表示的整数,那么 encoding 是 int。

    127.0.0.1:6379[2]> set num 20
    OK
    127.0.0.1:6379[2]> get num
    "20"
    127.0.0.1:6379[2]> object encoding num
    "int"
    
  • embstr

    当我们保存的值小于40的时候,则使用是embstr

    专门用户保存短字符串的一种编码方式。优点:快

    raw 调用两次的内存分配函数来分别创建redisObject,sdshdr。

    embstr 通过一次内存分配函数来分配一块连续的空间,包含着redisObject,sdshdr。所以执行速度快。

    embstr 没有提供修改函数,所以只读的。我们对它进行修改的化,首先转换成raw,在执行修改,然后结束。

    127.0.0.1:6379[2]> set name wanji
    OK
    127.0.0.1:6379[2]> object encoding name
    "embstr"
    127.0.0.1:6379[2]> append name WanJiRedis
    (integer) 15
    127.0.0.1:6379[2]> object encoding name
    "raw"
    
  • raw

    127.0.0.1:6379[2]> set num 201215121002020220220020202022020230303030303
    OK
    127.0.0.1:6379[2]> get num
    "201215121002020220220020202022020230303030303"
    127.0.0.1:6379[2]> object encoding num
    "raw"
    
  • 编码转换规则

    如果将原本保存的整数值转换为字符串值,那么字符串对象的编码也将从 int

127.0.0.1:6379[2]> set num 1234
OK
127.0.0.1:6379[2]> OBJECT encoding num
"int"
127.0.0.1:6379[2]> APPEND num a
(integer) 5
127.0.0.1:6379[2]> get num
"1234a"
127.0.0.1:6379[2]> OBJECT encoding num
"raw"
List(列表)
  • 适用场景:消息队列。

  • 它的特点就是内部元素有序、重复,并且插入和删除很快O(1),但是查找却很慢O(n)。功能支持队列和栈操作。

  • Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)

    一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。

示例操作

//左侧插入
lpush msg_queue msg1 msg2 msg3
//右侧插入
rpush msg_queue msg1 msg2 msg3
//左侧弹出
lpop msg_queue
//右侧弹出
rpop msg_queue
//查看列表长度
llen msg_queue
//查看列表中某个index的值  下标从0开始,要注意的是:由于这个操作是要遍历列表,所以index越大,效率越差。
lindex msg_queue 2
//查看msg_queue里面所有元素
lrange msg_queue 0 -1

在这里插入图片描述

列表操作
在这里插入图片描述

内部实现

列表对象的编码支持 ziplist 和 linkedlist 两种

ziplist

ziplist 编码列表对象,采用压缩列表实现。每个列表节点保存一个列表中的元素。

127.0.0.1:6379> RPUSH testlist a b c
(integer) 3

在这里插入图片描述

linkedlist

linkedlist编码列表对象,采用双向链表作为底层实现,每个列表节点保存一个列表中的元素。

在这里插入图片描述

编码转换规则

  • 同时满足一下两个条件时,是ziplist类型,否则为linkedlist类型

  • 条件1:列表中所有元素长度都小于66字节。

  • 条件2:列表中元素的个数小于512个。

Set(集合)

概述

  • 适用场景:存储有去重需求的数据,比如:针对一篇文章用户进行点赞操作。
  • 它的特点是内部元素无序且不重复。它的内部实现相当于一个特殊的字典,字典中所有的value指都为NULL。

具体操作

//添加元素到集合中
127.0.0.1:6379> sadd likeset Bob Tom Jreey
(integer) 3
//查看集合中的所有元素	输出顺序是乱序的
127.0.0.1:6379> smembers likeset
1) "Jreey"
2) "Bob"
3) "Tom"
//但是如果添加的是纯数字  输出顺序是有序的
127.0.0.1:6379> sadd numbers 2 5 6 7 1 9 8 3
(integer) 8
127.0.0.1:6379> smembers numbers
1) "1"
2) "2"
3) "3"
4) "5"
5) "6"
6) "7"
7) "8"
8) "9"
//查询 Tom 是否在集合中
127.0.0.1:6379> sismember likeset Tom
(integer) 1
//查询集合的长度
127.0.0.1:6379> scard likeset
(integer) 3
//取出集合中的一个元素
127.0.0.1:6379> spop likeset
"Tom"
//删除
127.0.0.1:6379> del likeset
(integer) 1

内部实现

  • 集合对象的编码可以是intsethashtable

intset(证书集合)

  • intset编码集合对象使用整数集合作为底层实现,集合对象包含的所有元素都被保存在整数集合里面。

    127.0.0.1:6379> SADD number 1 2 3 4
    (integer) 4
    127.0.0.1:6379> OBJECT encoding number
    "intset"
    

    数据结构如下:

在这里插入图片描述

hashtable

  • 底层字典作为底层实现,每个键都是一个字符串对象,每个字符串对象包含了一个集合元素,而字典的值则全部被设置为NULL。

    数据结构如下:

在这里插入图片描述

编码转换规则

  • 当创建集合类型时,如果集合的元素个数小于512个,且元素都为整数是内部编码为intset ,采用intset为内部编码保存,如果元素和元素值不满足intset内部编码条件,则采用hashtable内部编码保存。
Zset(有序集合)

概述

  • 适用场景:存储有去重且有序的数据,比如:学生的高考成绩。
  • 它的内部采用“跳跃列表”实现。根据score进行排序。

具体操作

  • 添加元素到sat_score中 注意,111 wanji会覆盖 134 wanji(注意删除原来存在的key)

    zadd score 134 wanji 122 bob 156 john 111 wanji
    
  • 查看hh的score值

    zscore score wanji
    
  • 正序输出 输出从下标0到下标-1(即倒数第一个)中的所有元素从小到大

    zrange score 0 -1
    zrangebyscore score -inf +inf  
    # 与上面输出效果一样,输出score>=负无穷,score<=正无穷的所有元素
    
  • 倒序输出

    zrevrange score 0 -1
    
  • 查看sat_score中的元素个数

    zcard score 注意,是按照正序排序输出的,从0开始
    
  • 获得sat_score中score>=2 且 score<=5的元素,正序排列

    zrangebyscore score 111 123
    zrangebyscore score 0 -1  会返回empty array,而并不是展示所有列表。因为score>=0 且score<=-1 是不存在的
    zrangebyscore score (111 122   半括号,表示小于。不加半括号,表示小于等于
    zrangebyscore score -inf 122   inf代表infinite:无穷的,-inf代表负无穷 +inf代表正无穷
    
  • 获得sat_score中 score<=5 且score>=2的元素,倒序排列

    zrevrangebyscore score 123 111
    
  • 删除sat_score中的元素haha

    zrem score wanji
    

内部实现:

  • 有序集合编码的内部实现可以是ziplistskiplist

ziplist

  • ziplist使用压缩列表作为底层实现,第一个节点保存元素的成员(member),而第二个节点则保存元素的分值(score)。压缩列表内的集合元素按分值从小到大进行排序。

    127.0.0.1:6379> zadd sat_score 134 hi 122 bob 156 john
    (integer) 3
    127.0.0.1:6379> OBJECT encoding sat_score
    "ziplist"
    

    数据结构如下:

在这里插入图片描述

当ziplist作为zset的底层存储结构时候,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的成员,第二个元素保存元素的分值。

skiplist

  • skiplist编码的有序集合采用zset结构作为底层实现,一个zset同时包含一个字典和一个跳跃表。

    redis.h
    /*
     * redis对象
     */
    typedef struct zset {
        // 字典(用来做缓存)
        dict *dict;
        // 跳跃表(排序结构)
        zskiplist *zsl;
    } zset;
    

在这里插入图片描述

Hash(字典)

概述

  • 适用场景:存储无序字典的数据,比如:适合存储对象类型。比如存储猪肉价格。
  • 它的内部采用数组+链表的结构,类似java里的HashMap。
  • hash的key值只能是字符串。将对象存储为hash结构可以针对需要来获取部分数据,而不是将整个对象获取。减少网络资源浪费。
  • rehash采用了渐进式的策略。

具体操作

  • 添加元素到 pig 中

    hset pig leg "26rmb/kg"
    hset pig ear "30rmb/kg"
    hset pig tongue "40rmb/kg"
    hset pig trotters "60rmb/kg"
    
  • 查询pig中猪耳朵的价格

    hget pig ear
    
  • 批量添加

    hmset boys_weight mark 126g bob 99 john 179 tom 155
    
  • 批量获取元素

    hmget boys_weight mark john
    
  • 获得pig中元素个数

    hlen pig
    
  • 查询pig中所有元素

    hgetall pig
    

内部实现

  • 哈希对象编码支持ziplisthashtable两种。

ziplist

  • ziplist编码底层使用压缩列表实现,当有新的键值对要加入到哈希对象时,会先将key值从队尾推入压缩列表中,再将这个key对应的value值从队尾推入压缩列表中;所以,同一键值对的两个节点总是紧挨在一起的,key在前value在后

    127.0.0.1:6379> hset hello name wanji
    (integer) 1
    127.0.0.1:6379> hset hello age 20
    (integer) 1
    127.0.0.1:6379> hset hello sex male
    (integer) 1
    127.0.0.1:6379> hgetall hello
    1) "name"
    2) "wanji"
    3) "age"
    4) "20"
    5) "sex"
    6) "male"
    127.0.0.1:6379> OBJECT encoding hello
    "ziplist"
    

    数据结构如下:

在这里插入图片描述

hashtable

在这里插入图片描述

编码转换规则

  • 同时满足两个条件时是ziplist编码类型,否则为hashtable编码类型

    条件1:哈希对象中所有键值对中,key和value的长度均小于46字节。
    条件2:哈希对象中键值对的个数小于512个。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值