前置内容

启动Redis
[root@localhost src]# cd /usr/local/redis-6.2.6/src 进入redis文件夹的src目录里
[root@localhost src]# ./redis-server ../redis.conf
[root@localhost src]# ./redis-cli 启动进程
查看线程
ps -fe | grep redis
结束进程
cd /…/redis-6.2.6/src redis安装地方
./redis-cli 进入redis
关闭redis服务:shutdown
退出客户端:exit
查看服务端口
netstat -lanp | grep 6379

Redis开发文档
https://www.redis.com.cn/tutorial.html
通过这个网站学习各类的存储方式
https://db-engines.com/en/articles

一、Redis中的List类型

列表(list)类型是用来存储多个有序的字符串,列表中的每个字符串称为元素(element),一个列表最多可以存储232-1个元素。 在Redis中,可以对列表两端插入(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。 列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景。
image.png
双向索引,如果取list中的全部数据,取值开始和结束是 0 -1

LPUSH key element [element …]

开头L是代表左边的意思
redis LPUSH 用于将一个或多个值插入到列表key 的头部。
如果 key 不存在,那么在进行 push 操作前会创建一个空列表。
如果 key 对应的值不是 list 类型,那么会返回一个错误。
可以使用一个命令把多个元素 push 进入列表,只需在命令末尾加上多个指定的参数。
元素按在参数中出现的顺序,从左到右依次插入到 list 的头部。
所以对于这个命令例子 LPUSH mylist a b c,返回的列表是 c 为第一个元素, b 为第二个元素, a 为第三个元素。
返回值
整数: 执行push操作后列表的长度。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> lpush k1 a b c d e f
(integer) 6

RPUSH key element [element …]

开头R是代表右边的意思
RPUSH 向存存储在 key 中的列表的尾部插入所有指定的值。如果 key 不存在,那么会创建一个空的列表然后再进行 push 操作。 当 key 保存的不是列表,那么会返回一个错误。
可以使用RPUSH命令把多个元素插入队列,只需要在命令后面指定多个参数。元素是从左到右按序从列表尾部插入。 比如命令 RPUSH mylist a b c 会返回一个列表,其第一个元素是 a ,第二个元素是 b ,第三个元素是 c。
返回值
整数: 执行 push 操作后的列表长度。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> rpush k2 a b c d e f
(integer) 6

LPOP key

开头L是代表左边的意思
Redis LPOP 命令用于删除并返回存储在 key 中的列表的第一个元素。
返回值
多行字符串: 列表的首元素,key 不存在的时候返回 nil 。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> lpop k1
“f”
127.0.0.1:6379> lpop k1
“e”
127.0.0.1:6379> lpop k1
“d”

RPOP key

开头R是代表右边的意思
Redis RPOP 用于移除并返回列表 key 的最后一个元素。
返回值
多行字符串: 最后一个元素的值,key 不存在时返回 nil 。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> rpop k2
“f”
127.0.0.1:6379> rpop k1
“a”

LRANGE key start stop

Redis LRANGE 用于返回列表中指定区间内的元素,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推。 你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。
注意LRANGE命令和编程语言区间函数的区别
假如你有一个包含一百个元素的列表,对该列表执行 LRANGE list 0 10 ,结果是一个包含11个元素的列表,这表明 stop 下标也在 LRANGE 命令的取值范围之内(闭区间),这和某些语言的区间函数可能不一致,比如Ruby的 Range.new 、 Array#slice 和Python的 range() 函数。
超出范围的下标
超出范围的下标值不会引起错误。
如果 start 下标比列表的最大下标 end ( LLEN list 减去 1 )还要大,那么 LRANGE 返回一个空列表。
如果 stop 下标比 end 下标还要大,Redis将 stop 的值设置为 end 。
返回值
数组: 一个列表,包含指定区间内的元素。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> LRANGE k1 0 -1
1) “c”
2) “b”
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> lpush k1 a b c d e f
(integer) 6
127.0.0.1:6379> lrange k1 0 -1
1) “f”
2) “e”
3) “d”
4) “c”
5) “b”
6) “a”
127.0.0.1:6379> rpush k2 a b c d e f
(integer) 6
127.0.0.1:6379> lrange k2 0 -1
1) “a”
2) “b”
3) “c”
4) “d”
5) “e”
6) “f”

LINDEX key index

LINDEX 返回列表 key 里索引 index 位置存储的元素。 index 下标是从 0 开始索引的,所以 0 是表示第一个元素, 1 表示第二个元素,并以此类推。 负数索引用于指定从列表尾部开始索引的元素,在这种方法下,-1 表示最后一个元素,-2 表示倒数第二个元素,并以此往前推。
当 key 值不是列表的时候,会返回错误。
返回值
多行字符串: 查询的元素,index 超出索引范围时返回 nil 。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> lrange k1 0 -1
1) “f”
2) “e”
3) “d”
4) “c”
5) “b”
6) “a”
127.0.0.1:6379> LINDEX k1 2 取出第三个数据,下标为2
“d”
127.0.0.1:6379> LINDEX k1 -1 取出最后一个数据,下标为-1
“a”

LSET key index element

Redis LSET 用于设置列表 key 中 index 位置的元素值为 element。 更多关于 index 参数的信息,详见 LINDEX
当 index 超出列表索引范围时会返回错误ERR ERR index out of range。
返回值
字符串
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> lrange k1 0 -1
1) “f”
2) “e”
3) “d”
4) “xxxxx”
5) “b”
6) “a”

LREM key count element

Redis LREM 用于从列表 key 中删除前 count 个值等于 element 的元素。 这个 count 参数通过下面几种方式影响这个操作:

  • count > 0: 从头到尾删除值为 value 的元素。
  • count < 0: 从尾到头删除值为 value 的元素。
  • count = 0: 移除所有值为 value 的元素。

比如, LREM list -2 “hello” 会从列表key中删除最后两个出现的 “hello”。
需要注意的是,不存在key会被当作空list处理,所以当 key 不存在的时候,这个命令会返回 0。
返回值
整数: 删除元素个数。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> lpush k3 1 a 2 b 3 a 4 c 5 a 6 d
(integer) 12
127.0.0.1:6379> lrange k3 0 -1
1) “d”
2) “6”
3) “a”
4) “5”
5) “c”
6) “4”
7) “a”
8) “3”
9) “b”
10) “2”
11) “a”
12) “1”
127.0.0.1:6379> lrem k3 2 a
(integer) 2
127.0.0.1:6379> lrange k3 0 -1
1) “d”
2) “6”
3) “5”
4) “c”
5) “4”
6) “3”
7) “b”
8) “2”
9) “a”
10) “1”

LINSERT key BEFORE|AFTER pivot element

Redis LINSERT 用于把 element 插入到列表 key 中参考值 pivot 的前面或后面。
当 key 不存在时,这个list会被看作是空list,什么都不执行。
当 key 存在,值不是列表类型时,返回错误。
返回值
整数: 执行操作后的列表长度,列表中pivot参考值不存在的时候返回 -1。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> lrange k3 0 -1
1) “d”
2) “6”
3) “5”
4) “c”
5) “4”
6) “3”
7) “b”
8) “2”
9) “a”
10) “1”
127.0.0.1:6379> linsert k3 after 6 a
(integer) 11
127.0.0.1:6379> lrange k3 0 -1
1) “d”
2) “6”
3) “a”
4) “5”
5) “c”
6) “4”
7) “3”
8) “b”
9) “2”
10) “a”
11) “1”
127.0.0.1:6379> linsert k3 before 3 a
(integer) 12
127.0.0.1:6379> lrange k3 0 -1
1) “d”
2) “6”
3) “a”
4) “5”
5) “c”
6) “4”
7) “a”
8) “3”
9) “b”
10) “2”
11) “a”
12) “1”

LLEN key

Redis LLEN 用于返回存储在 key 中的列表长度。 如果 key 不存在,则 key 被解释为一个空列表,返回 0 。 如果 key 不是列表类型,返回一个错误。
返回值
整数: 列表的长度。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> lrange k3 0 -1
1) “d”
2) “6”
3) “a”
4) “5”
5) “c”
6) “4”
7) “a”
8) “3”
9) “b”
10) “2”
11) “a”
12) “1”
127.0.0.1:6379> llen k3
(integer) 12

BLPOP key [key …] timeout

Redis BLPOP 命令移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。它是 LPOP 的阻塞版本。
当给定多个 key 参数时,按参数 key 的先后顺序依次检查各个列表,弹出第一个非空列表的头元素。

非阻塞行为

BLPOP 被调用时,如果给定 key 内至少有一个非空列表,那么弹出遇到的第一个非空列表的头元素,并和被弹出元素所属的列表的名字 key 一起,组成结果返回给调用者。
当存在多个给定 key 时, BLPOP 按给定 key 参数排列的先后顺序,依次检查各个列表。 我们假设 key list1 不存在,而 list2 和 list3 都是非空列表。考虑以下的命令:
BLPOP list1 list2 list3 0
BLPOP 一定返回一个存在于 list2 里的元素(因为它是从 list1 > list2 > list3 这个顺序查起的第一个非空列表)。

阻塞行为

如果所有给定 key 都不存在或包含空列表,那么 BLPOP 命令将阻塞连接, 直到有另一个客户端对给定的这些 key 的任意一个执行 LPUSHRPUSH 命令为止。
一旦有新的数据出现在其中一个列表里,那么这个命令会解除阻塞状态,并且返回 key 和弹出的元素值。
BLPOP 命令引起客户端阻塞并且设置了一个非零的超时参数 timeout 的时候, 若经过了指定的 timeout 仍没有出现一个针对某一特定 key 的 push 操作,则客户端会解除阻塞状态并且返回 nil 。
timeout 参数表示的是一个指定阻塞的最大秒数的整型值。当 timeout 为 0 是表示永久阻塞。

什么 key 会先被处理?是什么客户端?什么元素?优先顺序细节。

  • 当客户端为多个 key 尝试阻塞的时候,若至少存在一个 key 拥有元素,那么返回的键值对(key/element pair)就是从左到右数第一个拥有一个或多个元素的key。 在这种情况下客户端不会被阻塞。比如对于这个例子 BLPOP key1 key2 key3 key4 0,假设 key2 和 key4 都非空, 那么就会返回 key2 里的一个元素。
  • 当多个客户端为同一个 key 阻塞的时候,第一个被处理的客户端是等待最长时间的那个(即第一个因为该key而阻塞的客户端)。 一旦一个客户端解除阻塞那么它就不会保持任何优先级,当它因为下一个 BLPOP 命令而再次被阻塞的时候,会在处理完那些 被同个 key 阻塞的客户端后才处理它(即从第一个被阻塞的处理到最后一个被阻塞的)。
  • 当一个客户端同时被多个 key 阻塞时,若多个 key 的元素同时可用(可能是因为事务或者某个Lua脚本向多个list添加元素), 那么客户端会解除阻塞,并使用第一个接收到 push 操作的 key(假设它拥有足够的元素为我们的客户端服务,因为有可能存在其他客户端同样是被这个key阻塞着)。 从根本上来说,在执行完每个命令之后,Redis 会把一个所有 key 都获得数据并且至少使一个客户端阻塞了的 list 运行一次。 这个 list 按照新数据的接收时间进行整理,即是从第一个接收数据的 key 到最后一个。在处理每个 key 的时候,只要这个 key 里有元素, Redis就会对所有等待这个key的客户端按照“先进先出”(FIFO)的顺序进行服务。若这个 key 是空的,或者没有客户端在等待这个 key, 那么将会去处理下一个从之前的命令或事务或脚本中获得新数据的 key,如此等等。

    当多个元素被 push 进入一个 list 时 BLPOP 的行为

    有时候一个 list 会在同一概念的命令的情况下接收到多个元素:

  • 像 LPUSH mylist a b c 这样的可变 push 操作。

  • 在对一个向同一个 list 进行多次 push 操作的 MULTI 块执行完 EXEC 语句后。
  • 使用 Redis 2.6 或者更新的版本执行一个 Lua 脚本。

当多个元素被 push 进入一个被客户端阻塞着的 list 的时候,Redis 2.4 和 Redis 2.6 或者更新的版本所采取行为是不一样的。
对于 Redis 2.6 来说,所采取的行为是先执行多个 push 命令,然后在执行了这个命令之后再去服务被阻塞的客户端。看看下面命令顺序。
Client A: BLPOP foo 0
Client B: LPUSH foo a b c

在 MULTI / EXEC 事务中的 BLPOP

BLPOP 可以用于流水线(pipeline,发送多个命令并且批量读取回复),特别是当它是流水线里的最后一个命令的时候,这种设定更加有意义。
在一个 MULTI / EXEC 块里面使用 BLPOP 并没有很大意义,因为它要求整个服务器被阻塞以保证块执行时的原子性,这就阻止了其他客户端执行一个 push 操作。 因此,一个在 MULTI / EXEC 里面的 BLPOP 命令会在 list 为空的时候返回一个 nil 值,这跟超时(timeout)的时候发生的一样。
如果你喜欢科幻小说,那么想象一下时间是以无限的速度在 MULTI / EXEC 块中流逝……
返回值
数组:

  • 如果列表为空或超时,返回一个 nil。
  • 返回一个含有两个元素的列表,第一个元素是被弹出元素所属的 key ,第二个元素是被弹出元素的值。

——————————————————————————分割线——————————————————————————
开启三个客户端,连接同一个Redis
image.png
image.png
image.png
虚拟机3执行后,第一个虚拟机退出堵塞状态,第二个虚拟机没有退出堵塞状态
image.png
image.png

image.png
虚拟机3再执行后,第二个虚拟机退出堵塞状态
image.png
image.png
这说明list是单播队列的

LTRIM key start stop

Redis LTRIM 用于修剪(trim)一个已存在的 list,这样 list 就会只包含指定范围的指定元素。start 和 stop 都是由0开始计数的, 这里的 0 是列表里的第一个元素(表头),1 是第二个元素,以此类推。
例如: LTRIM foobar 0 2 将会对存储在 foobar 的列表进行修剪,只保留列表里的前3个元素。
start 和 end 也可以用负数来表示与表尾的偏移量,比如 -1 表示列表里的最后一个元素, -2 表示倒数第二个,等等。
超过范围的下标并不会产生错误:如果 start 超过列表尾部,或者 start > end,结果会是列表变成空表(即该 key 会被移除)。 如果 end 超过列表尾部,Redis 会将其当作列表的最后一个元素。
LTRIM 的一个常见用法是和 LPUSH / RPUSH 一起使用。 例如:
LPUSH mylist someelement
LTRIM mylist 0 99
这对命令会将一个新的元素 push 进列表里,并保证该列表不会增长到超过100个元素。
这是很有用的,比如当用 Redis 来存储日志。 需要特别注意的是,当用这种方式来使用 LTRIM 的时候,操作的复杂度是 O(1) , 因为平均情况下,每次只有一个元素会被移除。
返回值
字符串
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> lpush k1 a b c d e f g aa bb cc dd ee ff
(integer) 13
127.0.0.1:6379> lrange k1 0 -1
1) “ff”
2) “ee”
3) “dd”
4) “cc”
5) “bb”
6) “aa”
7) “g”
8) “f”
9) “e”
10) “d”
11) “c”
12) “b”
13) “a”
127.0.0.1:6379> ltrim k1 0 -1 这里删除的是第一个之前和最后一个之前,所以没数据删除
OK
127.0.0.1:6379> lrange k1 0 -1
1) “ff”
2) “ee”
3) “dd”
4) “cc”
5) “bb”
6) “aa”
7) “g”
8) “f”
9) “e”
10) “d”
11) “c”
12) “b”
13) “a”
127.0.0.1:6379> ltrim k1 2 -2 这里删除下标为2之前数据,-2之前的数据
OK
127.0.0.1:6379> lrange k1 0 -1
1) “dd”
2) “cc”
3) “bb”
4) “aa”
5) “g”
6) “f”
7) “e”
8) “d”
9) “c”
10) “b”

LPUSHX key element [element …]

Redis LPUSHX 在当 key 存在并且存储着一个 list 类型值的时候,向值 list 的头部插入 value。 与 LPUSH 相反,当 key 不存在的时候不会进行任何操作。
返回值
整数: 执行push操作后列表list的长度。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> lpush k1 world
(integer) 1
127.0.0.1:6379> lpushx k1 hello
(integer) 2
127.0.0.1:6379> lrange k1 0 -1
1) “hello”
2) “world”
127.0.0.1:6379> lpushx k2 hello k2是不存在
(integer) 0
127.0.0.1:6379> lrange k2 0 -1
(empty array)

RPOPLPUSH source destination

用于原子地从列表 source 中移除并返回最后一个元素,然后把这个元素插入为列表destination 的第一个元素。
例如: 假设 source 列表成员为 a,b,c,列表 destination 成员为 x,y,z。
执行 RPOPLPUSH source destination 的结果是列表 source 成员为a,b ,列表 destination 成员为c,x,y,z。
如果列表 source 不存在,返回 nil ,什么也不执行。
如果列表 source 和destination 相同,相当于从列表的一端删除元素,在放入列表的另一端,所以可以当做一个列表循环命令。
LMOVE 用来替换废弃的指令 RPOPLPUSH,相当于执行LMOVE RIGHT LEFT。
从 Redis 6.2.0起, RPOPLPUSH 被废弃,使用 LMOVE 替代。 new code.
返回值
多行字符串: 移除并又插入的元素。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> rpush k1 a
(integer) 1
127.0.0.1:6379> rpush k1 b
(integer) 2
127.0.0.1:6379> rpush k1 c
(integer) 3
127.0.0.1:6379> rpoplpush k1 k2
“c”
127.0.0.1:6379> lrange k1 0 -1
1) “a”
2) “b”
127.0.0.1:6379> lrange k2 0 -1
1) “c”

RPUSHX key element [element …]

RPUSHX将值 value 插入到列表 key 的表尾, 当且仅当 key 存在并且是一个列表。 和 RPUSH命令相反, 当 key 不存在时,RPUSHX 命令什么也不做。
返回值
整数: RPUSHX 命令执行之后列表的长度。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> rpush k3 a
(integer) 1
127.0.0.1:6379> rpushx k3 b
(integer) 2
127.0.0.1:6379> rpushx k4 a
(integer) 0
127.0.0.1:6379> lrange k3 0 -1
1) “a”
2) “b”
127.0.0.1:6379> lrange k4 0 -1
(empty array)

总结

image.png
栈:(先进先出)
使用 lpush、lpop 的时候,在对list做栈的使用。

二、Redis中的Hash类型

HSET key field value [field value …]

Redis Hset 命令用于为存储在 key 中的哈希表的 field 字段赋值 value 。
如果哈希表不存在,一个新的哈希表被创建并进行 HSET 操作。
如果字段(field)已经存在于哈希表中,旧值将被覆盖。
从 Redis 4.0 起,HSET 可以一次设置一个或多个 field/value 对。
返回值
整数: 被修改或增加的 field 个数。

HGET key field

Redis HGET 命令用于返回哈希表中指定字段 field 的值。
返回值
多行字符串: 返回给定字段的值。如果给定的字段或 key 不存在时,返回 nil 。

HMSET key field value [field value …]

Redis HMSET 命令用于同时将多个 field-value (字段-值)对设置到哈希表中。
此命令会覆盖哈希表中已存在的字段。
如果哈希表不存在,会创建一个空哈希表,并执行 HMSET 操作。
Redis 4.0.0起,HMSET 被废弃,请使用 HSET 代替。
返回值
字符串

HMGET key field [field …]

Redis HMGET 命令用于返回哈希表中,一个或多个给定字段(field)的值。
如果指定的字段(field)不存在于哈希表或者 key 不存在,那么返回一个 nil 值。
返回值
数组: 返回要查询的field对应值的列表,值的顺序field在命令中出现的顺序排列。

HKEYS key

HKEYS 返回存储在 key 中哈希表的所有域。
空哈希表/key不存在: redis> EXISTS fake_key (integer) 0<br />redis> HKEYS fake_key (empty list or set)
返回值
数组: 包含哈希表中所有域的表。当 key 不存在时,返回空表。

HVALS key

Redis HVALS 命令返回哈希表所有域(field)的值。
返回值
数组: 返回哈希表中所有域(field)值的列表。 当 key 不存在时,返回空表。 not exist.

HGETALL key

Redis HGETALL 命令用于返回存储在 key 中的哈希表中所有的域和值。
在返回值里,紧跟每个域(field name)之后是域的值(value),所以返回值的长度是哈希表大小的两倍。
返回值
数组: 以列表形式返回哈希表的字段及字段值。 若 key 不存在,返回空列表。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> hset sean name zzl
(integer) 1
127.0.0.1:6379> hmset sean age 18 address bj
OK
127.0.0.1:6379> hget sean name
“zzl”
127.0.0.1:6379> hget sean age
“18”
127.0.0.1:6379> hmget sean name age
1) “zzl”
2) “18”
127.0.0.1:6379> hkeys sean
1) “name”
2) “age”
3) “address”
127.0.0.1:6379> hvals sean
1) “zzl”
2) “18”
3) “bj”
127.0.0.1:6379> hgetall sean
1) “name”
2) “zzl”
3) “age”
4) “18”
5) “address”
6) “bj”

HINCRBYFLOAT key field increment

为哈希表 key 中的域 field 加上浮点数增量 increment 。
如果哈希表中没有域 field ,那么 INCRBYFLOAT 会先将域 field 的值设为 0 ,然后再执行加法操作。
如果键 key 不存在,那么 INCRBYFLOAT 会先创建一个哈希表,再创建域 field ,最后再执行加法操作。
当以下任意一个条件发生时,返回一个错误:

  • 域 field 的值不是字符串类型(因为 redis 中的数字和浮点数都以字符串的形式保存,所以它们都属于字符串类型)
  • 域 field 当前的值或给定的增量 increment 不能解释(parse)为双精度浮点数(double precision floating point number)

命令的详细功能和 INCRBYFLOAT命令类似,请查看 INCRBYFLOAT命令获取更多相关信息。
返回值
多行字符串: 执行加法操作之后 field 域的值
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> hincrbyfloat sean age 0.5
“18.5”
127.0.0.1:6379> hget sean age
“18.5”
127.0.0.1:6379> hincrbyfloat sean age 0.5
“19”

HINCRBY key field increment

为哈希表 key 中的域 field 的值加上增量 increment 。
增量也可以为负数,相当于对给定域进行减法操作。
如果 key 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。
如果域 field 不存在,那么在执行命令前,域的值被初始化为 0 。
对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误 ERR ERR hash value is not an integer。
本操作的值被限制在 64 位(bit)有符号数字表示之内。
返回值
整数: 执行 HINCRBY 命令之后,哈希表 key 中域 field 的值。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> hincrby sean age -1
(integer) 18
127.0.0.1:6379> hget sean age
“18”

三、Redis中的Set类型

SADD key member [member …]

Redis Sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略。
假如集合 key 不存在,则创建一个只包含被添加的元素作为成员的集合。
当集合 key 不是集合类型时,返回一个错误。
注意:在 Redis2.4 版本以前, SADD 只接受单个成员值。
返回值
整数: 返回新成功添加到集合里元素的数量,不包括已经存在于集合中的元素。

SMEMBERS key

Redis SISMEMBER 命令返回存储在 key 中的集合的所有的成员。 不存在的集合被视为空集合。
SISMEMBER 与运行带有一个参数 key 的 SINTER 有同样的效果。
返回值
数组: 集合中的所有成员。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> sadd k1 tom sean peter ooxx tom xxoo
(integer) 5
127.0.0.1:6379> smembers k1
1) “sean”
2) “ooxx”
3) “peter”
4) “xxoo”
5) “tom”

SREM key member [member …]

SREM 用于在集合中删除指定的元素。如果指定的元素不是集合成员则被忽略。
如果集合 key 不存在则被视为一个空的集合,该命令返回0。
如果key的类型不是一个集合,则返回 ERR WRONGTYPE Operation against a key holding the wrong kind of value 错误。
返回值
整数: 被删除元素个数,不含不存在的元素。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> srem k1 ooxx xxoo
(integer) 2
127.0.0.1:6379> smembers k1
1) “peter”
2) “tom”
3) “sean”

SINTER key [key …]

SINTER 返回所有给定集合的成员交集。例如:

  1. key1 = {a,b,c,d}
  2. key2 = {c}
  3. key3 = {a,c,e}
  4. SINTER key1 key2 key3 = {c}

对于不存在的 key 可以认为是空集合。
如果给定的key中有一个空集合,那么结果集一定是空集合。
返回值
数组: 结果集成员个数。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> sadd k2 1 2 3 4 5
(integer) 5
127.0.0.1:6379> sadd k3 4 5 6 7 8 1
(integer) 6
127.0.0.1:6379> smembers k2
1) “1”
2) “2”
3) “3”
4) “4”
5) “5”
127.0.0.1:6379> smembers k3
1) “1”
2) “4”
3) “5”
4) “6”
5) “7”
6) “8”
127.0.0.1:6379> sinter k2 k3
1) “1”
2) “4”
3) “5”

SINTERSTORE destination key [key …]

SINTERSTORE 命令与 SINTER 命令类似,不同的是它并不是直接返回结果集,而是将结果保存在 destination 集合中。
如果 destination 集合存在, 则会被覆盖。
返回值
整数: 结果集中成员数量。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> sinterstore dest k2 k3
(integer) 3
127.0.0.1:6379> smembers dest
1) “1”
2) “4”
3) “5”

SUNION key [key …]

SUNION 命令用于返回所有给定集合的并集。例如:

  1. key1 = {a,b,c,d}
  2. key2 = {c}
  3. key3 = {a,c,e}
  4. SUNION key1 key2 key3 = {a,b,c,d,e}

对于不存在 key 被当做空集合处理。
返回值
数组: 结果集中成员数量
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> sadd k2 1 2 3 4 5
(integer) 5
127.0.0.1:6379> sadd k3 4 5 6 7 8 1
(integer) 6
127.0.0.1:6379> sunion k2 k3
1) “1”
2) “2”
3) “3”
4) “4”
5) “5”
6) “6”
7) “7”
8) “8”

SUNIONSTORE destination key [key …]

SUNIONSTORE 命令的功能类似于 SUNION,不同的是不反回结果集,而是存储在 destination 中。
如果 destination 已经存在,则被覆盖。
返回值
整数: 结果集中的成员数量。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> sadd k1 a b c d e
(integer) 5
127.0.0.1:6379> sadd k2 c d e
(integer) 3
127.0.0.1:6379> sunionstore k3 k1 k2
(integer) 5
127.0.0.1:6379> smembers k3
1) “c”
2) “a”
3) “e”
4) “d”
5) “b”

SRANDMEMBER key [count]

Redis SRANDMEMBER 命令仅使用key 参数,那么随机返回集合key 中的一个随机元素。
Redis 2.6开始,可以接受 count 参数,如果count是整数且小于元素的个数,返回含有 count 个不同的元素的数组,如果count是个整数且大于集合中元素的个数时,返回整个集合的所有元素,当count是负数,则会返回一个包含count的绝对值的个数元素的数组,如果count的绝对值大于元素的个数,则返回的结果集里会出现一个元素出现多次的情况.
仅提供key参数时,该命令作用类似于SPOP命令,不同的是SPOP命令会将被选择的随机元素从集合中移除,而SRANDMEMBER 仅仅是返回该随记元素,而不对原集合做任何操作。
返回值
多行字符串: 不使用count 参数的情况下该命令返回随机的元素,如果key不存在则返回nil。 数组: 使用count参数,则返回一个随机的元素数组,如果key不存在则返回一个空的数组。
传递count参数时的行为规范
当传递了一个值为正数的count参数,返回的元素就好像从集合中移除了每个选中的元素一样(就像在宾果游戏中提取数字一样)。但是元素不会从集合中移除。所以基本上:

  • 不会返回重复的元素。
  • 如果count参数的值大于集合内的元素数量,此命令将会仅返回整个集合,没有额外的元素。

相反,当count参数的值为负数时,此命令的行为将发生改变,并且提取操作就像在每次提取后,重新将取出的元素放回包里一样,因此,可能返回重复的元素,以及总是会返回我们请求的数量的元素,因为我们可以一次又一次地重复相同的元素,除了当集合为空(或者不存在key)的时候,将总是会返回一个空数组。
返回元素的分布
当集合中的元素数量很少时,返回元素分布远不够完美,这是因为我们使用了一个近似随机元素函数,它并不能保证良好的分布。
所使用的算法(在dict.c中实现)对哈希表桶进行采样以找到非空桶。一旦找到非空桶,由于我们在哈希表的实现中使用了链接法,因此会检查桶中的元素数量,并且选出一个随机元素。
这意味着,如果你在整个哈希表中有两个非空桶,其中一个有三个元素,另一个只有一个元素,那么其桶中单独存在的元素将以更高的概率返回。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> sadd k1 tom ooxx xoxo xxoo oxox oxxo xoox
(integer) 7
127.0.0.1:6379> srandmember k1 3
1) “oxox”
2) “xoox”
3) “tom”
127.0.0.1:6379> srandmember k1 3
1) “oxxo”
2) “xxoo”
3) “xoox”
127.0.0.1:6379> srandmember k1 3
1) “oxox”
2) “ooxx”
3) “xoox”
127.0.0.1:6379> srandmember k1 3
1) “oxxo”
2) “xxoo”
3) “ooxx”
127.0.0.1:6379> srandmember k1 -3
1) “oxox”
2) “xoxo”
3) “oxxo”
127.0.0.1:6379> srandmember k1 -3
1) “xoox”
2) “oxxo”
3) “ooxx”
127.0.0.1:6379> srandmember k1 -3
1) “oxxo”
2) “oxxo”
3) “oxxo”

SPOP key [count]

Redis SPOP 命令用于从集合 key中删除并返回一个或多个随机元素。
这个命令和 SRANDMEMBER 相似, SRANDMEMBER 只返回随机成员但是不删除这些返回的成员。
参数 count 从 Redis 3.2 起可用。
返回值
多行字符串: 被删除的元素,当key不存在时返回nil。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> spop k1
“ooxx”
127.0.0.1:6379> spop k1
“oxxo”
127.0.0.1:6379> spop k1
“xoox”
127.0.0.1:6379> spop k1
“oxox”
127.0.0.1:6379> spop k1
“xoxo”
127.0.0.1:6379> spop k1
“tom”
127.0.0.1:6379> spop k1
“xxoo”
127.0.0.1:6379> spop k1
(nil)
127.0.0.1:6379> spop k1
(nil)

SDIFF key [key …]

Redis SDIFF 命令返回第一个集合与其他集合之间的差异,也可以认为说第一个集合中独有的元素。不存在的集合 key 将视为空集。
返回值
数组: list with members of the resulting set.
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> sadd k1 a b c d
(integer) 4
127.0.0.1:6379> sadd k2 c
(integer) 1
127.0.0.1:6379> sadd k3 a e
(integer) 2
127.0.0.1:6379> sdiff k1 k2 k3
1) “d”
2) “b”

SSCAN key cursor [MATCH pattern] [COUNT count]

Redis SSCAN 命令用于遍历集合中键的元素,SSCAN 继承自SCAN。
redis SSCAN 命令基本语法如下:

  • cursor - 游标。
  • pattern - 匹配的模式。
  • count - 指定从数据集里返回多少元素,默认值为 10 。

返回值
数组列表。
——————————————————————————分割线——————————————————————————
127.0.0.1:6379> sadd k1 zhangsan
(integer) 1
127.0.0.1:6379> sadd k1 lisi
(integer) 1
127.0.0.1:6379> sadd k1 duhaitao
(integer) 1
127.0.0.1:6379> sadd k1 wangfeng
(integer) 1
127.0.0.1:6379> sscan k1 0 match R
1) “0”
2) (empty array)
127.0.0.1:6379> sscan k1 0 match z

1) “0”
2) 1) “zhangsan”

SMOVE source destination member

Redis SMOVE 命令用于从集合source 中移动成员member 到集合 destination。 这个操作是原子操作。 在任何时刻,member 只会存在于source 和destination 其中之一。
如果集合source 不存在,或者要移动的成员不是集合source 的成员,什么也不执行并返回 0 。
否则,其它情况下,从集合source 中删除成员并添加到集合 destination。
如果要移动的元素在集合 destination中已经存在,那么只是从集合source中删除该成员。
如果 source 或destination 不是集合类型则返回错误。
返回值
整数:

  • 1 移动元素成功。
  • 0 如果要移动的 element 不是source 的成员,什么也不执行。

    ——————————————————————————分割线——————————————————————————
    127.0.0.1:6379> sadd myset a b
    (integer) 2
    127.0.0.1:6379> sadd myptherset c
    (integer) 1
    127.0.0.1:6379> smove myset myptherset b
    (integer) 1
    127.0.0.1:6379> smembers myset
    1) “a”
    127.0.0.1:6379> smembers myptherset
    1) “c”
    2) “b”

    总结

    image.png

    四、Redis中的SortedSet(集合)类型

    ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member …]

    Redis ZADD 命令用于将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
    如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入这个 member 元素,来保证该 member 在正确的位置上。
    如果有序集合 key 不存在,则创建一个空的有序集并执行 ZADD 操作。
    当 key 存在但不是有序集类型时,返回一个错误。
    score 值可以是整数值或双精度浮点数,score 可为正也可以为负。
    对有序集的更多介绍请参见 sorted set
    注意: 在 Redis 2.4 版本以前, ZADD 每次只能添加一个元素。

    ZADD 参数

    ZADD 支持参数,参数位于 key 名字和第一个 score 参数之间:

  • XX: 仅更新存在的成员,不添加新成员。

  • NX: 不更新存在的成员。只添加新成员。
  • LT: 更新新的分值比当前分值小的成员,不存在则新增。
  • GT: 更新新的分值比当前分值大的成员,不存在则新增。
  • CH: 返回变更成员的数量。变更的成员是指 新增成员score值更新的成员,命令指明的和之前score值相同的成员不计在内。 注意: 在通常情况下,ZADD返回值只计算新添加成员的数量。
  • INCR: ZADD 使用该参数与 ZINCRBY 功能一样。一次只能操作一个score-element对。

注意: GT, LTNX 三者互斥不能同时使用。

scores 有效值范围

Redis 有序集合的分数使用双精度64位浮点数表示。在Redis所支持的平台上,称为IEEE 754 floating point number,它能包括的整数范围是-(2^53) 到 +(2^53)。或者说是-9007199254740992 到 9007199254740992。更大的整数在内部用指数形式表示,所以,如果为分数设置一个非常大的整数,你得到的是一个近似的十进制数。

Sorted sets 101

有序集合按照分数以递增的方式进行排序。相同的成员(member)只存在一次,有序集合不允许存在重复的成员。 分数可以通过ZADD命令进行更新或者也可以通过ZINCRBY命令递增来修改之前的值,相应的他们的排序位置也会随着分数变化而改变。
获取一个成员当前的分数可以使用 ZSCORE 命令,也可以用它来验证成员是否存在。
更多关于有序集合的信息请参考 sorted sets.

相同分数的成员

有序集合里面的成员是不能重复的都是唯一的,但是,不同成员间有可能有相同的分数。当多个成员有相同的分数时,他们将是按字典排序(ordered lexicographically)(仍由分数作为第一排序条件,然后,相同分数的成员按照字典序排序)。
字典顺序排序用的是二进制,它比较的是字符串的字节数组。
如果用户将所有元素设置相同分数(例如0),有序集合里面的所有元素将按照字典顺序进行排序,范围查询元素可以使用 ZRANGEBYLEX 命令(注:范围查询分数可以使用 ZRANGEBYSCORE 命令)
返回值
整数:

  • 被成功添加的新成员的数量,不包括那些被更新分数的、已经存在的成员。

如果使用 INCR 选项,则返回 多行字符串:

  • 以字符串形式表示的 member 的 score 值(双精度浮点数)。(双精度浮点数) , 执行失败返回 nil (当使用 XX 或 NX 选项)。

    ZRANGE key start stop [WITHSCORES]

    Redis ZRANGE 命令返回有序集中,指定区间内的成员,其中成员的按分数值递增(从小到大)来排序,具有相同分数值的成员按字典序(lexicographical order )来排列。
    如果你需要成员按值递减(从大到小)来排列,请使用 ZREVRANGE命令。
    下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。
    你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。
    start 和 stop 都是包含在内的区间,因此例如 ZRANGE myzset 0 1 将会返回有序集合的第一个和第二个元素。
    超出范围的索引不会产生错误。 如果 start 参数的值大于有序集合中的最大索引,或者 start > stop ,将会返回一个空列表。 如果 stop 的值大于有序集合的末尾,Redis 会将其视为有序集合的最后一个元素。
    可以传递 WITHSCORES 选项,以便将元素的分数与元素一起返回。这样返回的列表将包含 value1,score1,…,valueN,scoreN ,而不是 value1,…,valueN 。 客户端类库可以自由地返回更合适的数据类型(建议:具有值和得分的数组或元组)。
    返回值
    数组: 给定范围内的元素列表(如果指定了WITHSCORES选项,将同时返回它们的得分)。
    ——————————————————————————分割线——————————————————————————
    添加多个元素
    127.0.0.1:6379> zadd k1 8 apple 2 banana 3 orange
    (integer) 3
    127.0.0.1:6379> zrange k1 0 -1
    1) “banana”
    2) “orange”
    3) “apple”
    127.0.0.1:6379> zrange k1 0 -1 withscores
    1) “banana”
    2) “2”
    3) “orange”
    4) “3”
    5) “apple”
    6) “8”

    ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]

    Redis ZRANGEBYSCORE 返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
    具有相同 score 值的成员按字典序(lexicographical order)来排列(该属性是有序集提供的,不需要额外的计算)。
    可选的 LIMIT 参数指定返回结果的数量及区间(就像SQL中的 SELECT LIMIT offset, count ),注意当 offset 很大时,定位 offset 的操作可能需要遍历整个有序集,此过程最坏复杂度为 O(N) 时间。
    可选的 WITHSCORES 参数决定结果集是单单返回有序集的成员,还是将有序集成员及其 score 值一起返回。 该选项自 Redis 2.0 版本起可用。

    互斥区间与无穷大

    min 和 max 可以是 -inf 和 +inf ,这样一来,你就可以在不知道有序集的最低和最高 score 值的情况下,获取所有成员。
    默认情况下,区间的取值使用闭区间 (小于等于或大于等于),你也可以通过给参数前增加 ( 符号来使用可选的开区间 (小于或大于)。
    返回值
    数组: 指定区间内的有序集成员的列表(带有 score 值(可选))。
    ——————————————————————————分割线——————————————————————————
    127.0.0.1:6379> zrangebyscore k1 3 8
    1) “orange”
    2) “apple”

    ZREVRANGE key start stop [WITHSCORES]

    Redis ZREVRANGE 命令返回有序集key中,指定区间内的成员。其中成员的位置按score值递减(从高到低)来排列。
    具有相同score值的成员按字典序的反序排列。 除了成员排序相反外,ZREVRANGE命令的其他方面和ZRANGE命令一样。
    返回值
    数组: 指定范围的元素列表(可选是否含有分数)。
    ——————————————————————————分割线——————————————————————————
    127.0.0.1:6379> zrange k1 0 1
    1) “banana”
    2) “orange”
    127.0.0.1:6379> zrevrange k1 0 1
    1) “apple”
    2) “orange”
    127.0.0.1:6379> zrange k1 -2 -1
    1) “orange”
    2) “apple”

    ZSCORE key member

    Redis zscore 命令用于返回有序集 key.中成员 member 的分数。
    如果有续集中 不存在 member ,或者 key 不存在,返回 nil 。
    返回值
    多行字符串: 成员的分数。(双精度浮点数,字符串格式)
    ——————————————————————————分割线——————————————————————————
    127.0.0.1:6379> zscore k1 apple
    “8”

    ZRANK key member

    RedisZRANK 命令返回有序集key中成员member的排名,其中有序集成员按score值从低到高排列。
    排名从0开始,也就是说,score值最低的成员排名为0。
    使用ZREVRANK命令可以获得成员按score值递增(从高到低)排列的排名。
    返回值

  • 如果member是有序集key的成员,整数: member 的排名。

  • 如果member不是有序集key的成员, 或 key 不存在,多行字符串: nil。

    ——————————————————————————分割线——————————————————————————
    127.0.0.1:6379> zrank k1 apple
    (integer) 2

    ZINCRBY key increment member

    ZINCRBY 为有序集 key 的成员 member 的 score 值加上增量 increment 。
    当 key 不存在,或 member 不是 key 的成员时, ZINCRBY key increment member 等同于 ZADD key increment member 。
    当 key 不是有序集类型时,返回”ERR WRONGTYPE Operation against a key holding the wrong kind of value”。
    score 值可以是字符串形式表示的整数值或双精度浮点数。
    可以通过传递一个负数值 increment ,让 score 减去相应的值,比如 ZINCRBY key -2 member ,就是让 member 的 score 值减去 2 。
    返回值
    多行字符串: 以字符串形式表示的 member 成员的新 score 值(双精度浮点数)。
    ——————————————————————————分割线——————————————————————————
    127.0.0.1:6379> zrange k1 0 -1
    1) “banana”
    2) “orange”
    3) “apple”
    127.0.0.1:6379> zrange k1 0 -1 withscores
    1) “banana”
    2) “2”
    3) “orange”
    4) “3”
    5) “apple”
    6) “8”
    127.0.0.1:6379> zincrby k1 2.5 banana
    “4.5”
    127.0.0.1:6379> zrange k1 0 -1
    1) “orange”
    2) “banana”
    3) “apple”
    127.0.0.1:6379> zrange k1 0 -1 withscores
    1) “orange”
    2) “3”
    3) “banana”
    4) “4.5”
    5) “apple”
    6) “8”

    ZUNIONSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE SUM|MIN|MAX]

    Redis ZUNIONSTORE 用于计算给定的numkeys个有序集合的并集,并且把结果放到destination中。
    在给定要计算的key和其它参数之前,必须先给定key个数(numkeys)。
    默认情况下,结果集中某个成员的score值是所有给定集中该成员score值之和。
    使用WEIGHTS选项,你可以为每个给定的有序集指定一个乘法因子,意思就是,每个给定有序集的所有成员的score值在传递给聚合函数之前都要先乘以该因子。如果WEIGHTS没有给定,默认是 1。
    使用AGGREGATE选项,你可以指定并集的结果集的聚合方式。默认使用的参数SUM,可以将所有集合中某个成员的score值之和作为结果集中该成员的score值。如果使用参数MIN或者MAX,结果集就是所有集合中该元素最小或最大score。
    如果destination存在,会被覆盖。
    返回值
    整数: 结果集destination中成员的数量。
    ——————————————————————————分割线——————————————————————————
    127.0.0.1:6379> zadd k1 80 tom 60 sean 70 baby
    (integer) 3
    127.0.0.1:6379> zadd k2 60 tom 100 sean 40 zhangsan
    (integer) 3
    127.0.0.1:6379> zunionstore unkey 2 k1 k2
    (integer) 4
    127.0.0.1:6379> zrange unkey 0 -1 withscores
    1) “zhangsan”
    2) “40”
    3) “baby”
    4) “70”
    5) “tom”
    6) “140”
    7) “sean”
    8) “160”
    127.0.0.1:6379> zunionstore unkey1 2 k1 k2 weights 1 0.5
    (integer) 4
    127.0.0.1:6379> zrange unkey1 0 -1 withscores
    1) “zhangsan”
    2) “20” 400.5
    3) “baby”
    4) “70” 70
    1
    5) “sean”
    6) “110” 60+1000.5
    7) “tom”
    8) “110” 80+60
    0.5
    127.0.0.1:6379> zunionstore unkey1 2 k1 k2 aggregate max
    (integer) 4
    127.0.0.1:6379> zrange unkey1 0 -1
    1) “zhangsan”
    2) “baby”
    3) “tom”
    4) “sean”
    127.0.0.1:6379> zrange unkey1 0 -1 withscores
    1) “zhangsan”
    2) “40”
    3) “baby”
    4) “70”
    5) “tom”
    6) “80”
    7) “sean”
    8) “100”

    总结

    物理内存存储数据时,左小右大。不随着命令发生变化
    集合操作,并集、交集。注意点:权重/聚合指令

排序是怎么实现的增删改查的速度

当一个数(11)进行插入时,从最顶层往底层进行值比较,插入到最后一层时,会随机造层
image.png