4、集合键
Redis 的集合以无序的方式储存多个各不相同的元素。
4.1添加元素
SADD key element [element ...]
如果已经存在,则忽略,命令返回新添加到集合的元素数量。
redis> SADD friends "peter"
(integer) 1
redis> SADD friends "jack" "tom" "john"
(integer) 3
redis> SADD friends "may" "tom"
(integer) 1
4.2移除元素
SREM key element [element ...]
移除集合中一个或者多个元素,如果不存在集合中,则忽略。
redis> SREM friends "peter"
(integer) 1
redis> SREM friends "tom" "john"
(integer) 2
4.3检查给定元素是否存在集合中
SISMEMBER key element
如果存在,返回1,不存在返回0。
redis> SISMEMBER friends "peter"
(integer) 1
redis> SISMEMBER friends "li lei"
(integer) 0
redis> SISMEMBER NOT-EXISTS-KEY "element"
(integer) 0
4.4返回集合的大小
SCARD key
redis> SCARD friends
(integer) 6
redis> SREM friends "peter" "jack" "tom"
(integer) 3
redis> SCARD friends
(integer) 3
4.5返回集合所包含的所有元素
SMEMBERS key
redis> SMEMBERS friends
1) "jack"
2) "peter"
3) "may"
4) "tom"
5) "john"
6) "ben"
当集合的基数较大时,执行这个命令有可能会造成服务器阻塞,可以迭代集合中的元素。
4.6从集合中随机的弹出一个元素
SPOP key
redis> SADD friends "peter" "jack" "tom" "john" "may" "ben"
(integer) 6
redis> SPOP friends
"may"
redis> SMEMBERS friends
1) "tom"
2) "john"
3) "jack"
4) "peter"
5) "ben"
4.6从集合中随机的返回一个元素。
SRANDMEMBER key [count]
redis> SRANDMEMBER friends #随机的返回一个元素
"ben"
redis> SRANDMEMBER friends 3 # 从集合中随机的返回三个无重复的元素
1) "john"
2) "jack"
3) "peter"
redis> SRANDMEMBER friends -3 #从集合中随机的返回三个有可能重复的元素
1) "may"
2) "peter"
3) "may"
4.7计算集合
4.7.1SDIFF key [key ...] 计算所有给定集合的差集,
redis> SADD number1 "123" "456" "789"
(integer) 3
redis> SADD number2 "123" "456" "999"
(integer) 3
redis> SDIFF number1 number2
1) "789"
4.7.2 SDIFFSTORE destkey key [key ...] 计算所有给定集合的差集,并将结果储存在destkey
4.7.3 SINTER key [key ...] 计算所有给定集合的交集,并返回结果
redis> SADD number1 "123" "456" "789"
(integer) 3
redis> SADD number2 "123" "456" "887"
(integer) 3
redis> SINTER number1 number2
1) "123"
2) "456"
4.7.4 SINTERSTORE destkey key [key ...] 计算所有给定集合的交集,并将结果储存在destkey
4.7.5 SUNION key [key ...] 计算所有给定集合的并集,并返回结果
redis> SADD number1 "123" "456" "789"
(integer) 3
redis> SADD number2 "123" "456" "887"
(integer) 3
redis> SUNION number1 number2
1) "123"
2) "456"
3) "789"
4) "887"
4.7.6 SUNIONSTORE destkey key [key ...] 计算所有给定集合的并集,并将结果储存在destkey
4.8有序集合
有序集合和集合一样,都可以包含任意数量的、各不相同的元素( element),不同于集合的是,有序集
合的每个元素都关联着一个浮点数格式的分值(score),并且有序集合会按照分值,以从小到大的顺序
来排列有序集合中的各个元素。
虽然有序集合中的每个元素都必须是各不相同的,但元素的分值并没有这一限制,换句话来说,两个不
同元素的分值可以是相同的。
4.8.1 添加元素 ZADD key score element [[score element] [score element] ...]
按照给定的分值和元素,将任意数量的元素添加到有序集合里面,命令的返回值为成功添加的元素数
量。
redis> ZADD fruits-price 3.2 香蕉
1
redis> ZADD fruits-price 2.0 西瓜
1
redis> ZADD fruits-price 4.0 番石榴 7.0 梨 6.8 芒果
3
4.8.2 删除元素 ZREM key element [element ...]
从有序集合中删除指定的元素,以及这些元素关联的分值,命令返回被成功删除的元素数量。
redis> ZADD fruits-price …
5
redis> ZREM fruits-price 番石榴 梨 芒果
3
redis> ZREM fruits-price 西瓜
1
4.8.3 返回元素的分值
ZSCORE key element
返回有序集合中,指定元素的分值。
redis> ZSCORE fruits-price 西瓜
2
redis> ZSCORE fruits-price 香蕉
3.2000000000000002
redis> ZSCORE fruits-price 芒果
6.7999999999999998
4.8.4 增加或减少元素的分值
ZINCRBY key increment element
为有序集合指定元素的分值加上增量 increment ,命令返回执行操作之后,元素的分值。
没有相应的 ZDECRBY 命令,但可以通过将 increment 设置为负数来减少分值。
redis> ZINCRBY fruits-price 1.5 西瓜
3.5
redis> ZINCRBY fruits-price -0.8 香蕉
2.4000000000000004
4.8.5 返回有序集合的基数
ZCARD key
4.8.6 返回元素的排名(rank)ZRANK key element
返回指定元素在有序集合中的排名,其中排名按照元素的分值从小到大计算。
排名以 0 开始。
4.8.7 返回元素的逆序排名 ZREVRANK key member
返回成员在有序集合中的逆序排名,其中排名按照元素的分值从大到小计算。
排名以 0 开始。
4.8.8获取指定索引范围内的升序元素
ZRANGE key start stop [WITHSCORES]
返回有序集合在按照分值从小到大排列元素(升序排列) 的情况下,索引 start 至索引 stop 范围之内的所
有元素。
两个索引都可以是正数或者负数。当给定 WITHSCORES 选项时,命令会将元素和分值一并返回。
4.8.9 获取指定索引范围内的降序元素
ZREVRANGE key start stop [WITHSCORES]
返回有序集合在按照分值从大到小排列元素(降序排列) 的情况下,索引 start 至索引 stop 范围之内的所
有元素。
两个索引都可以是正数或者负数。当给定 WITHSCORES 选项时,命令会把元素和分值一并返回。
4.8.10 获取指定分值范围内的升序元素
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
返回有序集合在按照分值升序排列元素的情况下,分值在 min 和 max 范围之内的所有元素。
给定 WITHSCORES 选项时,元素和分值会一并返回。给定 LIMIT 选项时,可以通过 offset 参数指定返
回的结果集要跳过多少个元素,而 count 参数则用于指定返回的元素数量。
4.8.11 获取指定分值范围内的降序元素
ZREVRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
返回有序集合在按照分值降序排列元素的情况下,分值在 min 和 max 范围之内的所有元素。
给定 WITHSCORES 选项时,元素和分值会一并返回。给定 LIMIT 选项,可以通过 offset 参数指定返回
的结果集要跳过多少个元素,而 count 参数则用于指定返回的元素数量。
4.8.12 计算给定分值范围内的元素数量
ZCOUNT key min max
返回有序集合在升序排列元素的情况下,分值在 min 和 max 范围内的元素数量。
4.8.13 移除指定排名范围内的升序排列元素
ZREMRANGEBYRANK key start stop
移除有序集合中,元素按升序进行排列的情况下,指定排名范围内的所有元素。
4.8.14 移除指定分值范围内的升序排列元素
ZREMRANGEBYSCORE key min max
移除有序集合中,分值范围介于 min 和 max 之内的所有元素。
4.8.15 计算并集 ZUNIONSTORE destkey numkeys key [key ...]
4.8.16 计算交集 ZINTERSTORE destkey numkeys key [key ...]
5 HyperLogLog
使用常量空间估算大量元素的基数。
HyperLogLog 可以接受多个元素作为输入,并给出输入元素的基数估算值:
• 基数:集合中不同元素的数量。比如 {'apple', 'banana', 'cherry', 'banana', 'apple'} 的基数就是 3 。
• 估算值:算法给出的基数并不是精确的,可能会比实际稍微多一些或者稍微少一些,但会控制在合
理的范围之内。
HyperLogLog 的优点是,即使输入元素的数量或者体积非常非常大,计算基数所需的空间总是固定
的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基
数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以
HyperLogLog 不能像集合那样,返回输入的各个元素。
5.1将元素添加至 HyperLogLog
PFADD key element [element ...]
将任意数量的元素添加到指定的 HyperLogLog 里面。
这个命令可能会对 HyperLogLog 进行修改,以便反映新的基数估算值,如果 HyperLogLog 的基数估算
值在命令执行之后出现了变化, 那么命令返回 1 , 否则返回 0 。
命令的复杂度为 O(N) ,N 为被添加元素的数量。
5.2 返回给定 HyperLogLog 的基数估算值
PFCOUNT key [key ...]
当只给定一个 HyperLogLog 时,命令返回给定 HyperLogLog 的基数估算值。
当给定多个 HyperLogLog 时,命令会先对给定的 HyperLogLog 进行并集计算,得出一个合并后的
HyperLogLog ,然后返回这个合并 HyperLogLog 的基数估算值作为命令的结果(合并得出的
HyperLogLog 不会被储存,使用之后就会被删掉)。
当命令作用于单个 HyperLogLog 时, 复杂度为 O(1) , 并且具有非常低的平均常数时间。
当命令作用于多个 HyperLogLog 时, 复杂度为 O(N) ,并且常数时间也比处理单个 HyperLogLog 时要
大得多。
5.3 合并多个 HyperLogLog
PFMERGE destkey sourcekey [sourcekey ...]
将多个 HyperLogLog 合并为一个 HyperLogLog ,合并后的 HyperLogLog 的基数估算值是通过对所有
给定 HyperLogLog 进行并集计算得出的。
命令的复杂度为 O(N) , 其中 N 为被合并的 HyperLogLog 数量, 不过这个命令的常数复杂度比较高。
二、数据库
redis是一个键值对数据库服务器,当我们调用命令时,创建一个键值对的时候,这个键值对会被放到redis的某个数据库里面。
1、查看键的类型
TYPE key
返回键储存的值的类型。复杂度为O(1)。
返回值 值的类型
none 键不存在
string 字符串或者HyperLogLog(HLL是二进制值)
hash 散列
list 列表
set 集合
zset 有序集合
2、删除键
DEL KEY[KEY ...]
删除给定的任意多个键,不存在的键会被忽略,命令返回成功删除的键数量。
3、检查键是否存在
EXIST key
检查给定的键是否存在于数据库,存在返回1,不存在返回0.
4、修改键的名字
RENAME key newkey 将键的名字从key改为newkey,如果newkey存在,那么覆盖,键key不存在,或者key和newkey同名时,返回错误。
RENAMENX key newkey 如果键newkey不存在,那么将键key改名为newkey;如果newkey已经村镇,那么不做动作。
5、sort命令
在redis里面,只有列表和有序集合是以有序的方式来存储值的:
列表按照值被推入的顺序来储存值
有序集合按照元素的分值来排序元素。
SORT key [BY pattern] [LIMIT offset count] [GET pattern[GET pattern ...]] [ASC|DESC] [ALPHA] [SORE sestination]
如果不指定顺序,默认按照升序排序。
ALPHA:可以让srot命令按照字典顺序排序,只对文字进行排序。
6、随机的获取某个键
RANDOMKEY
7、返回数据库中与给定模式相匹配的键
KEYS pattern
返回当前数据库中,所有匹配给定模式pattern的键
渐进地遍历整个数据库
因为KEYS命令会一次性地遍历整个数据库来获取所有与给定模式相匹配的键,所以随着数据库包含的键值对越来越多,这个命令的执行速度也会越来越慢,而对一个非常大的数据库执行keys命令,将导致服务器被阻塞一段时间。
为了解决这个问题,redis从2.8.0版本开始提供SCAN命令,这个命令可以以渐进的方式,分多次遍历整个数据库,并返回匹配给定模式的键。
keys和scan命令的对比
8、获取数据库大小
DBSIZE
9、清空当前数据库
FLUSHDB
10、切换数据库
redis服务器默认情况下会创建16个数据库,分别是0号数据库到15号数据库,客户端一般默认使用0号数据库,但用户可以通过调用 select num命令来切换到num号数据库。每个数据库都是独立的,一个数据库里面的键值对不会对另一个影响。
11、清空所有数据库
flushall
三、附加功能
1、键过期功能
让 Redis 在指定的时间自动删除特定的键。
1.1设置生存时间
EXPIRE key seconds 将键 key 的生存时间设置为指定的秒数。
PEXPIRE key milliseconds 将键 key 的生存时间设置为指定的毫秒数。
如果给定的键不存在,那么 EXPIRE 和 PEXPIRE 将返回 0 ,表示设置失败;如果命令返回 1 ,那么表
示设置成功。
当一个键被设置了生存时间之后,它的生存时间将会随着时间的流逝而减少:时间过去一毫秒,键的生
存时间就减少一毫秒;时间过去一秒钟,键的生存时间就减少一秒钟;以此类推。
当一个键的生存时间被减少至低于 0 时,Redis 就会自动将这个键删除掉。
1.2设置过期时间
EXPIREAT key timestamp 将键 key 的过期时间设置为指定的秒级 UNIX 时间戳。
PEXPIREAT key milliseconds-timestamp 将键 key 的过期时间设置为指定的毫秒级 UNIX 时间戳。
如果给定的键不存在,那么 EXPIREAT 和 PEXPIREAT 将返回 0 ,表示设置失败;如果命令返回 1 ,
那么表示设置成功。
对于被设置了过期时间的键来说,当键的过期时间小于当前时间的时候,Redis 就会自动地删除该键。
1.3返回键的剩余生存时间
在为一个键设置过期时间或者生存时间之后,用户可以使用 TTL 命令或者 PTTL 命令查看这个键的剩
余生存时间,以此来获知键还有多久才会被 Redis 删除:
TTL key 以秒为单位,返回键的剩余生存时间
PTTL key 以毫秒为单位,返回键的剩余生存时间
返回值 意义
-2 键不存在。
-1 键存在,但没有设置过期时间或者生存时间。
>= 0 键的剩余生存时间。
1.4 移除键的过期时间或生存时间
PERSIST key
移除为键 key 设置的过期时间或生存时间,使得它不会被 Redis 自动删除。
移除成功时命令返回 1 ;如果命令没有设置过期时间或生存时间,那么命令返回 0 。
2、发布与订阅:
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:
2.1订阅频道
SUBSCRIBE channel [channel ...]
订阅给定的一个或多个频道。
2.2订阅模式
PSUBSCRIBE pattern [pattern ...]
订阅一个或多个模式, pattern 参数可以包含 glob 风格的匹配符,比如:
• news::* 模式可以匹配 news::bussiness 、 news::it 、 news::sports::football 等频道;
• news::[ie]t 模式可以匹配 news::it 频道或者 news::et 频道;
• news::?t 模式可以匹配 news::it 、 news::et 、 news::at 等频道;
2.3退订频道和退订模式
UNSUBSCRIBE [channel [channel ...]] 退订指定的频道。如果执行时没有指定任何频道,那么退订已订阅的所有频道。
PUNSUBSCRIBE [pattern [pattern ...]] 退订指定的模式。如果执行时没有指定任何模式,那么退订已订阅的所有模式。
2.4查看被订阅的频道
PUBSUB CHANNELS [pattern] 列出目前至少有一个订阅者的频道。如果给定了可选的 pattern 参数,那么只列出与模式相匹配的频道。
2.5查看频道的订阅者数量
PUBSUB NUMSUB [channel-1 ... channel-N] 返回给定频道的订阅者数量。
2.6查看被订阅模式的数量
PUBSUB NUMPAT 返回服务器目前被订阅的模式数量。
3.流水线:
在一般情况下,用户每执行一个 Redis 命令,客户端和服务器都需要进行一次通信:客户端向服务器发送命令请求,而服务器则会将执行命令所得的命令回复返回给客户端。
在大多数情况下, 执行命令时的绝大部分时间都耗费在了发送命令和接收回复的过程上,因此减少客户端与服务器之间的通信次数,可以有效地提高程序的执行效率。
流水线可以将多条命令打包一起发送,并且在一次回复中接收所有被执行命令的结果,使用这个功能可以有效地提升程序在执行多条命令时的效率。
4.事务
Redis 的事务功能允许用户将多个命令包裹起来,然后一次性地、按顺序地执行被包裹的所有命令。
在事务执行的过程中,服务器不会中断事务而改去执行其他命令请求,只有在事务包裹的所有命令都被执行完毕之后,服务器才会去处理其他命令请求。
MULTI 开始一个新的事务。
MULTI
开始一个事务。
在这个命令执行之后,客户端发送的所有针对数据库或者数据库键的命令都不会被立即执行,而是被放
入到一个事务队列里面,并返回 QUEUED 表示命令已入队。
redis> MULTI # 开始一个事务
OK
redis> SET msg "hello world" # 将这个 SET 命令放入事务队列
QUEUED
redis> EXPIRE msg 10086 # 将这个 SET 命令放入事务队列
QUEUED
DISCARD 放弃事务。
取消事务,放弃执行事务队列中的所有命令。复杂度为 O(1)。
redis> MULTI
OK
redis> SET msg "hello world"
QUEUED
redis> EXPIRE msg 10086
QUEUED
redis> DISCARD # 事务已被取消
OK
redis> SET msg "hello world"
OK
EXEC 执行事务中的所有命令。
按照命令被入队到事务队列中的顺序,执行事务队列中的所有命令。
命令的复杂度为队列中所有命令的复杂度之和。
命令的返回值是一个列表,列表里包含了事务队列中所有被执行命令的返回值。
redis> MULTI
OK
redis> SET msg "hello world"
QUEUED
redis> EXPIRE msg 10086
QUEUED
redis> EXEC
1) OK # SET 命令的返回值
2) (integer) 1 # EXPIRE 命令的返回值
WATCH 命令
为了消除 ZDECRBY 实现中的竞争条件, 我们需要用到 Redis 提供的 WATCH 命令, 这个命令需要在
开始一个事务之前执行, 它接受任意多个键作为参数, 并对输入的键进行监视:
WATCH key [key ...]
如果被监视的键在事务提交之前(也即是 EXEC 命令执行之前), 已经被其他客户端抢先修改了, 那么
服务器将拒绝执行客户端提交的事务, 并返回 nil 作为事务的回复:
5、脚本
Redis 脚本使用 Lua 解释器来执行脚本。执行脚本的常用命令为
EVAL
。
通过调用redis.call()函数或者redis.pcall()函数。redis.call()如果脚本出错会返回出错的名字,而redis.pcall()函数如果出错,则会返回错误信息。
热河Lua脚本,只要被EVAL命令执行过一次,就会被储存到服务器的脚本缓存里面,用户只要通过EVALSHA命令,指定被缓存脚本的SHA1值,就可以在不发送脚本的情况下,再次执行脚本。
EVAL script numkeys key
[
key
...]
arg
[
arg
...]
:
执行脚本
Evalsha 命令根据给定的 sha1 校验码,执行缓存在服务器中的脚本。
SCRIPT Exists 命令:表示脚本是否已经被加入到脚本缓存里面,是的话返回1,不是的话返回0;
SCRIPT LOAD script:将脚本储存到脚本缓存里面,等待将来的EVALSHA使用。
SCRIPT FLUSH:清楚脚本缓存存储的所有脚本;
SCRIPT KILL:杀死运行超时的脚本。如果脚本已经执行过写入操作,那么还需要使用SHUTDOWN NOSAVE命令来强制服务器不保存数据,以免错误的数据被保存到数据库里面。