String

是什么?

String就是字符串,它是Redis中最基本的数据对象,最大为512MB

基本操作

image-20230302100137549

写操作

SET

语法:SET key value

功能:设置一个key的值为特定的value,成功则返回OK。

String:对象的创建或者更新都是该命令。

1
2
127.0.0.1:6379>SET str cat
OK

SETNX

语法:SETNX key value

功能:用于在指定的ky不存在时,为key设置指定的值,返回值0表示「key存在」不做操作,1表示设置成功。

如果对存在的Key,调用SETNX:

1
2
127.0.0.1:6379>SETNX str fish 
(integer)0

对不存在的key,调用SETNX:

1
2
127.0.0.1:6379>SETNX strmart fish
(integer)1

DEL

语法:DEL key[key]

功能:删除对象,返回值为删除成功了几行。

1
2
127.0.0.1:6379>DEL str
(integer)1

读操作

GET

语法:GET key

功能:查询某个key,存在就返回对应的value,如果不存在返回nil。

1
2
3
4
127.0.0.1:6379>get str
"cat"
127.0.0.1:6379>get strmart
(nil)

MGET

语法:NGET key [key…]

功能:一次查询多个key,如果某个key不存在,对应位置返回nil。

1
2
3
127.0.0.1:6379>MGET str strmart 
1)"cat"
2)(nil)

底层实现

三种编码

String有三种编码方式:

image-20230311142709483

INT编码:这个很好理解,就是存一个整型,可以用long表示的整数就以这种编码存储;

EMBSTR编码:如果字符串小于等于阈值字节,使用EMBSTR编码(连续内存);

RAW编码:字符串大于阈值字节,则用RAW编码(不连续内存)。

阈值字节在3.2版本之前是39字节,在3.2版本之后是44字节

由于sdshdr中**储存长度(len)分配了多少内存(alloc)**这两个字段属性从占「4字节」变为占「1字节」导致的剩余空间变大

随着我们的操作,编码可能会转换:

INT->RAW:当存的内容不再是整数,或者大小超过了Iong的时候;

EMBSTR->RAW:任何操作之后EMBSTR都会变成RAW,原因前面有解释。

sdshdr

EMBSTR编码和RAW编码由redisObjectsdshdr这两部份构成,它解决了C语言中字符串的三个问题:

  1. 每次计算字符串长度的复杂度为O(N);
  2. 对字符串进行追加,需要重新分配内存;
  3. 非二进制安全。

image-20230311143758514

从SDS的结构,我们很容易看出SDS是如何对症下药解决问题的:

  1. 增加长度字段len,快速返回长度;
  2. 增加空余空间(alloc-len),为后续追加数据留余地;
  3. 不再以’\0’作为判断标准,二进制安全。

len小于1M的情况下,alloc是Ien的一倍,即预留len大小的空间;

len大于1M的情况下,alloc是1M+len,即预留1M大小的空间。

LIST

是什么?

Redis List是一组连接起来的字符串集合,List最大元素个数是2^32^ -1。

每个ziplist都有一个 32位无符号整数 来表示它包含的元素个数,所以每个ziplist最多可以包含 2^32^ -1个元素。

基本操作

image-20230311151925857

写操作

LPUSH

语法:LPUSH key value [value …]

功能:从头部增加元素,返回值为List中元素的总数。

1
2
3
4
5
127.0.0.1:6379> LPUSH listbz s1 s2 s3
(integer) 3

127.0.0.1:6379> LPUSH listbz s4
(integer) 4

RPUSH

语法:RPUSH key value [value …]

功能:从尾部增加元素,返回值为List中元素的总数。

1
2
127.0.0.1:6379> RPUSH listbz s5
(integer) 5

LPOP

语法:LPOP key

功能:(头部)移出并获取列表的第一个元素。

1
2
127.0.0.1:6379> LPOP listbz
"s4"

RPOP

语法:RPOP key

功能:(尾部)移出并获取列表的最后一个元素。

1
2
127.0.0.1:6379> RPOP listbz
"s5"

DEL

语法:DEL key [key …]

功能:删除对象,返回值为删除成功了几行。

1
2
127.0.0.1:6379> DEL listbz
(integer) 1

读操作

我们使用如下数据,构造集合用于读操作的学习:

LLEN

语法:LLEN key

功能:查看List的长度,即List中元素的总数。

1
2
127.0.0.1:6379> LLEN listbz
(integer) 3

LRANGE

语法:LRANGE key start stop

功能:查看start到stop为角标的元素。

1
2
3
127.0.0.1:6379> LRANGE listbz 0 1
1) "s3"
2) "s2"

start、stop如果为负数,表示倒数第几个元素:

1
2
3
127.0.0.1:6379> LRANGE listbz -2 -1
1) "s2"
2) "s1"

底层实现

3.2版本之前,List对象有两种编码方式,一种ZIPLIST(紧凑内存),另一种是LINKEDLIST。

image-20230311155210647

当满足如下条件时,用ZIPLIST编码:

  1. 列表对象保存的所有字符串对象长度都小于64字节
  2. 列表对象元素个数少于512个

ZIPLIST

SET

是什么?

Redis的Set是一个不重复无序的字符串集合。

基本操作

image-20230311212452027

写操作

SADD

语法:SADD key member [member。。]

功能:添加元素,返回值为成功添加了几个元素

1
2
127.0.0.1:6379> SADD setniuniu aa bb cc
(integer) 3

SREM

语法:SREM key member [member …]

功能:删除元素,返回值为成功删除了几个元素

1
2
127.0.0.1:6379> SREM setniuniu aa
(integer) 1

读操作

SISMEMBER

语法:SISMEMBER key member

功能:查询元素是否存在

1
2
3
4
127.0.0.1:6379> SISMEMBER setbz aa
(integer) 1 // 存在
127.0.0.1:6379> SISMEMBER setbz ff
(integer) 0 // 不存在

SCARD

语法:SCARD key

功能:查询集合元素个数

1
2
127.0.0.1:6379> SCARD setbz
(integer) 5

SMEMBERS

语法:SMEMBERS key

功能:查看集合的所有元素。

1
2
3
4
5
6
127.0.0.1:6379> SMEMBERS setbz
1) "aa"
2) "bb"
3) "11"
4) "cc"
5) "22"

SSCAN

语法:SSCAN key cursor [MATCH pattern] [COUNT count]

功能:查看集合元素,可以理解为指定游标进行查询,可以指定个数,默认个数为10

SCAN增量式迭代命令并不保证每次执行都返回某个给定数量的元素,甚至可能会返回零个元素, 但只要命令返回的游标不是0,应用程序就不应该将迭代视作结束。

例子1:从0号位置开始查询,默认10个

1
2
3
4
5
6
7
127.0.0.1:6379> SSCAN setniuniu 0
1) "0"
2) 1) "aa"
2) "bb"
3) "11"
4) "22"
5) "cc"

例子2:使用MATCH模糊查询

1
2
3
4
5
6
127.0.0.1:6379> SSCAN setniuniu 0 MATCH 1*
1) "0"
2) 1) "11"
127.0.0.1:6379> SSCAN setniuniu 0 MATCH *2
1) "0"
2) 1) "22"

MATCH支持通配符,*2代表任意以2结尾的数据

SINTER

语法:SINTER key [key …]

功能:返回在第一个集合里,同时在后面所有集合都存在的元素。(第一个集合为准的并集)

1
2
3
127.0.0.1:6379> SINTER setniuniu setmart
1) "bb"
2) "aa"

SUNION

语法:SUNION key [key …]

功能:返回所有集合的并集,集合个数大于等于2

1
2
3
4
5
6
7
127.0.0.1:6379> SUNION setmart setniuniu
1) "ff"
2) "aa"
3) "bb"
4) "11"
5) "cc"
6) "22"

SDIFF

语法:SDIFF key [key …]

功能:返回第一个集合有,且在后续集合中不存在的元素,集合个数大于等于2,注意,是以第一个集合和后面比,看第一个集合多了哪些元素

1
2
3
4
127.0.0.1:6379> SDIFF setniuniu setmart
1) "cc"
2) "22"
3) "11"

底层实现

当满足以下条件时使用INTSET编码:

  1. 集群元素都是整数
  2. 元素数量不超过512个

否则用HASHTABLE编码。

优缺点:

  • INTSET排列比较紧凑,内存占用少,但是查询时需要二分查找。

  • HASHTABLE查询一个元素的性能很高,能O(1)时间就能找到一个元素是否存在。