redis(二)基本数据类型

一、string

string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。
string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。
string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。

redis 127.0.0.1:6379> SET runoob "菜鸟教程"
OK
redis 127.0.0.1:6379> GET runoob
"菜鸟教程"

字符串对象的编码可以是intrawembstr,为啥它有3个?还不是因为用的多,最常用了,所以作者才特别关照对它千方百计的优化。如果一个字符串保存的是整数值,并且这个值可以用long类型表示,那么字符串对象会将整数值保存在字符串对象结构的ptr属性里。并将字符串编码encoding设置为int。此处要注意,1-9999之间的数值字符串在内存中可以复用。如果保存的是一个字符串的值,并且长度大于44字节(redis3.0之前是39),那么字符串对象将使用raw编码的简单动态字符串保存这个值。如果长度小于等于44,将使用embstr编码的简单动态字符串保存这个值。
39/44这个值从哪里来的:
要先看下当字符串类型时,redisObject的结构:
在这里插入图片描述
原因是,3.0版本之前,sdshdr这个结构里len和free记录了这个SDS的长度和空余空间,是unsigned int类型的,可以保存很大的数字,但是对于很短的SDS就浪费空间了(2个unsigned占8个字节)。而Redis分配内存一般是8 16 32 64这种分配的,redisObject占16个字节,最初free和len各占4个字节,字符串buf后面还有1个\0字节。所以当buf中为39字节时,16+8+39+1=64字节。当字符数少于39都会分配64字节的长度,3.0之前的39界限从这里得来的。3.0之后发现对于一些短的这样做不太合理,于是做了一次优化,优化点主要就在len free这2个属性上,之前一个len和一个free分别占用4字节,现在分别占用1个字节,又加了一个标识位flag占用1个字节,于是从原来的8到现在的 1*2+1=3。刚好缩短了5个字节,从39变成了44。另外embstr是只读的,在它进行运算时会先转成raw类型。

二、List

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

redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> lpush runoob redis
(integer) 1
redis 127.0.0.1:6379> lpush runoob mongodb
(integer) 2
redis 127.0.0.1:6379> lpush runoob rabitmq
(integer) 3
redis 127.0.0.1:6379> lrange runoob 0 10
1) "rabitmq"
2) "mongodb"
3) "redis"
redis 127.0.0.1:6379>

列表对象的编码可以是ziplist、linkedList结构。也就是压缩列表和双向链表结构。ziplist编码的列表对象使用压缩列表作为底层实现,每个压缩列表节点保存了一个列的元素。如下:
zlbytes记录整个压缩列表占用的内存字节数,在对压缩列表进行内存重分配或计算zlend的位置时使用。zltail记录压缩列表尾节点距离压缩列表的起始地址有多少字节,通过这个偏移量,可以直接确定尾节点的位置。zllen记录压缩列表包含的节点数量,xxx/yyy/zzz表示各种节点,数量和长度不一定。zlend用于标记压缩列表的末端。
在这里插入图片描述

三、hash

Redis hash 是一个键值(key=>value)对集合。
Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> HMSET runoob field1 "Hello" field2 "World"
"OK"
redis 127.0.0.1:6379> HGET runoob field1
"Hello"
redis 127.0.0.1:6379> HGET runoob field2
"World"

实例中我们使用了 Redis HMSET, HGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value。
每个 hash 可以存储 232 -1 键值对(40多亿)。

列表对象的编码可以是ziplist、linkedList结构。也就是压缩列表和双向链表结构哈希对象的底层编码可以是ziplist或者hashtable,目前仅分析之前版本的ziplist结构的哈希。
ziplist作为哈希对象的底层实现的时候,每当有新的键值对要加入到哈希对象时,程序会先把键放到ziplist的末尾,再把值放在ziplist的末尾。因此键值总是挨在一起的,键在前,值在后。如下图所示:
在这里插入图片描述
哈希对象保存的所有键值对的键和值的字符串长度都小于64字节
哈希对象保存的键值对数量小于512
这2个值也是在配置文件中可以修改的在redis.conf

四、set

Redis 的 Set 是 string 类型的无序集合。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> sadd runoob redis
(integer) 1
redis 127.0.0.1:6379> sadd runoob mongodb
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 1
redis 127.0.0.1:6379> sadd runoob rabitmq
(integer) 0
redis 127.0.0.1:6379> smembers runoob

1) "redis"
2) "rabitmq"
3) "mongodb"

注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。

集合对象也有2种编码,分别是intset整数集合和hashtable哈希表。简单介绍一下:
intset编码的集合对象使用整数集合作为底层实现,集合对象包含的所有元素都被保存在整数集合里面。
在这里插入图片描述
另一方便,hashtable编码的集合对象使用字典作为底层实现,字典的每个键都是一个字符串对象,每个字符串对象包含了一个集合元素,而字典的值则全部被设置为null.
在这里插入图片描述
直接切入正题:编码转换,当集合对象同时满足下面2个条件,使用intset,否则使用hashtable

  1. 集合里所有元素都是整数值
  2. 集合元素个数不超过512(可配置,redis.conf)
localhost:6379> sadd numbers 1 2 3 4 5
(integer) 5
localhost:6379> object encoding numbers
"intset"
localhost:6379> sadd numbers aaa
(integer) 1
localhost:6379> object encoding numbers
"hashtable"
localhost:6379>

五、zset(sorted set:有序集合)

Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
zset的成员是唯一的,但分数(score)却可以重复。

redis 127.0.0.1:6379> DEL runoob
redis 127.0.0.1:6379> zadd runoob 0 redis
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 mongodb
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 1
redis 127.0.0.1:6379> zadd runoob 0 rabitmq
(integer) 0
redis 127.0.0.1:6379> > ZRANGEBYSCORE runoob 0 1000
1) "mongodb"
2) "rabitmq"
3) "redis"

底层编码可以是ziplist或者skiplist结构,压缩列表特性之前说过,每个元素的集合使用2个位置相邻的节点保存,在有序集合中,第一个存放的是元素本身,第二个存放的是元素的分值score。压缩列表的集合元素按分值从小到大进行排序,分值较小的元素被放置在靠近表头的位置。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值