麦克斯仇
Think different
160
文章
47127
阅读
首页
INDEX
文章
ARTICLE
关于
ABOUT
Redis命令2:五种常用数据类型操作命令
创建日期:
2021/05/14
修改日期:
2022/06/22
Redis
> 本文档整理自教程: Redis官方文档:[commands](https://redis.io/commands) 尚硅谷视频:[尚硅谷_Redis6](http://www.atguigu.com/download_detail.shtml?v=323) --- > 本文仅介绍常用命令,所有命令请参考官方文档 # String 字符串 ## 简介 - `String`是`Redis`最基本的类型,可以理解成与`Memcached`一模一样的类型,一个`key`对应一个`value`。 - `String`类型是二进制安全的。意味着`Redis`的`String`可以包含任何数据。比如`jpg`或者序列化的对象。 - 一个`Redis`中字符串`value`最多可以是***512M*** ## 数据结构 String的数据结构为简单动态字符串(`Simple Dynamic String`,缩写`SDS`)。是可以修改的字符串,内部结构实现上类似于`Java`的`ArrayList`,采用预分配冗余空间的方式来减少内存的频繁分配。  如图中所示:内部为当前字符串实际分配的空间`capacity`,一般要高于实际字符串长度`len`。当字符串长度小于`1M`时,扩容都是加倍现有的空间,如果超过`1M`,扩容时一次只会多扩`1M`的空间。需要注意的是字符串最大长度为`512M`。 ## 常用命令 ### GET key 获取值 > 自1.0.0起可用。 获取`key`的值。如果键不存在,则返回特殊值`nil`。如果存储在`key`的值不是字符串,则返回错误,因为`GET`仅处理字符串值。 > 例 ```bash 127.0.0.1:6379> GET nonexistent (nil) 127.0.0.1:6379> SET key hello OK 127.0.0.1:6379> GET key "hello" ``` #### GETEX key 获取值并设置有效时间 > 自6.2.0起可用。 获取`key`的值,并可以选择设置其过期时间。`GETEX`与`GET`相似,但是是带有附加选项的写命令。 选项:该`GETEX`命令支持一组修改其行为的选项,具体如下: - `EX seconds`:设置指定的到期时间(以秒为单位) - `PX milliseconds`:设置指定的过期时间(以毫秒为单位) - `EXAT timestamp-seconds`:设置密钥过期的指定Unix时间,以秒为单位 - `PXAT timestamp-milliseconds`:设置密钥过期的指定Unix时间(以毫秒为单位) - `PERSIST`:保留与键关联的生存时间 > 例 ```bash 127.0.0.1:6379> SET key hello OK 127.0.0.1:6379> GETEX key "hello" 127.0.0.1:6379> TTL key (integer) -1 127.0.0.1:6379> GETEX key EX 60 "hello" 127.0.0.1:6379> TTL key (integer) 60 ``` #### GETDEL key 获取键的值同时删除键 > 自6.2.0起可用。 获取`key`的值并删除当前`key`。此命令与GET相似,不同之处在于它也会在成功时删除键(当且仅当键的值类型为字符串时)。 > 例 ```bash 127.0.0.1:6379> SET key hello OK 127.0.0.1:6379> GETDEL key "hello" 127.0.0.1:6379> GET key (nil) ``` ### SET key value 设置键与值 `SET key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]` > 自1.0.0起可用。 设置`key`保存一个值。如果`key`已经保存了一个值,则无论其类型如何,都会覆盖该值。成功进行`SET`操作后,将丢弃与键关联的任何以前的时间。与键关联的任何有效时间都将被丢弃。 选项:`SET`命令支持一组修改其行为的选项,具体如下: - `EX seconds`:设置指定的到期时间(以秒为单位) - `PX milliseconds`:设置指定的过期时间(以毫秒为单位) - `EXAT timestamp-seconds`:设置密钥过期的指定Unix时间,以秒为单位 - `PXAT timestamp-milliseconds`:设置密钥过期的指定Unix时间(以毫秒为单位) - `KEEPTTL`:保留与键关联的生存时间 - `NX`:仅设置不存在的密钥 - `XX`:仅设置密钥(如果已存在) - `GET`:返回存储在`key`处的旧值;如果`key`不存在,则返回`nil` 返回值: - `OK`:如果`SET`执行正确 - 字符串:设置`GET`选项时,旧值存储在`key`处;如果`key`不存在,则为`nil` - `nil`:如果由于用户指定了`NX`或`XX`选项但不满足条件而未执行`SET`操作,或者如果用户指定了`GET`选项并且该键没有先前的值,则返回`nil` > 例 ```bash 127.0.0.1:6379> SET key hello OK 127.0.0.1:6379> GET key "hello" 127.0.0.1:6379> SET key2 hello EX 60 OK 127.0.0.1:6379> GET key2 "hello" 127.0.0.1:6379> TTL key2 (integer) 60 127.0.0.1:6379> SET key word NX (nil) 127.0.0.1:6379> SET key word XX OK 127.0.0.1:6379> GET key "word" 127.0.0.1:6379> SET key tom GET "word" 127.0.0.1:6379> GET key "tom" ``` #### SETEX key seconds value 设置键与值并设置超时时间(秒) > 自2.0.0起可用。 设置`key`的值设置超时时间(秒)。此命令等效于执行以下命令: ``` SET mykey value EXPIRE mykey seconds ``` `SETEX`是原子性的,可以通过在`MULTI / EXEC`块中使用前面两个命令来实现。它提供了一个更快的替代给定的操作序列,当Redis被用作缓存时,这个操作是非常常见的。 > 例 ```bash 127.0.0.1:6379> SETEX key 10 hello OK 127.0.0.1:6379> TTL key (integer) 10 ``` #### PSETEX key milliseconds value 设置键与值并设置超时时间(毫秒) > 自2.6.0起可用。 `PSETEX`的工作方式与`SETEX`完全相同,唯一的区别是到期时间以毫秒而不是指定秒为单位。 > 例 ```bash 127.0.0.1:6379> PSETEX key 10000 hello OK 127.0.0.1:6379> PTTL key (integer) 4397 ``` #### SETNX key value 键不存在则设置键与值 > 自1.0.0起可用。 设置`key`的值,如果`key`不存在,则等于`SET`。如果`key`已经拥有一个值,则不执行任何操作。 > 例 ```bash 127.0.0.1:6379> SETNX key hello (integer) 1 127.0.0.1:6379> SETNX key hello (integer) 0 127.0.0.1:6379> GET key "hello" ``` #### GETSET key value 获取值并设置一个新值 注:自`Redis 6.2`起,**已弃用**!请使用带有`GET`参数的`SET`命令 > 自1.0.0起可用。 以原子方式设置`key`为`value`并返回存储在`key`中的旧值。如果`key`存在但不包含字符串值,则返回错误。 > 例 ```bash 127.0.0.1:6379> SET key hello OK 127.0.0.1:6379> GETSET key world "hello" 127.0.0.1:6379> GET key "world" ``` ### APPEND key value 拼接字符串 > 自2.0.0起可用。 如果`key`已经存在并且是字符串,则此命令将`value`附加在字符串的末尾。如果`key`不存在,则会创建它并将其设置为空字符串,因此`APPEND`在这种特殊情况下将类似于`SET`。该命令返回值为整数:即追加操作后字符串的长度。 > 例 ```bash 127.0.0.1:6379> EXISTS key (integer) 0 127.0.0.1:6379> APPEND key hello (integer) 5 127.0.0.1:6379> APPEND key " world" (integer) 11 127.0.0.1:6379> GET key "hello world" ``` ### STRLEN key 获取字符串长度 > 自2.2.0起可用。 返回存储在`key`中的字符串值的长度。`key`的值为非字符串时,将返回错误。 ```bash 127.0.0.1:6379> SET key hello OK 127.0.0.1:6379> STRLEN key (integer) 5 127.0.0.1:6379> STRLEN nonexisting (integer) 0 ``` ### GETRANGE key start end 截取字符串 > 自2.4.0起可用。 返回`key`的字符串值的子字符串,由偏移量的`start`和`end`决定(都包括在内)。可以使用负偏移量来提供从字符串末尾开始的偏移量。所以-1是最后一个字符,-2是倒数第二个字符,以此类推。该函数通过将结果范围限制为字符串的实际长度来处理超出范围的请求。 > 例 ```bash 127.0.0.1:6379> SET key "This is a string" OK 127.0.0.1:6379> GETRANGE key 0 3 "This" 127.0.0.1:6379> GETRANGE key -3 -1 "ing" 127.0.0.1:6379> GETRANGE key 0 -1 "This is a string" 127.0.0.1:6379> GETRANGE key 10 100 "string" ``` ### SETRANGE key offset value 修改字符串 > 自2.2.0起可用。 从指定的偏移量开始,覆盖`key`存储的字符串的一部分,覆盖`value`的整个长度。如果偏移量大于键处字符串的当前长度,则用零字节填充字符串以使偏移量适合。不存在的键被认为是空字符串,所以这个命令将确保它保存的字符串足够大,能够在`offset`处设置`value`。该命令返回被修改后的字符串长度 > 例 ```bash 127.0.0.1:6379> SET key "Hello World" OK 127.0.0.1:6379> SETRANGE key 6 redis (integer) 11 127.0.0.1:6379> GET key "Hello redis" ``` ### INCR key 加一 | DECR key 减一 > 自1.0.0起可用。 将`key`的值的数字加`1`或减`1`。如果`key`不存在,则将其设置为`0`,然后再执行操作。如果`key`包含错误类型的值或包含不能表示为整数的字符串,则返回错误。该操作仅限于64位有符号整数。注意:这是一个字符串操作,因为Redis没有一个专用的整数类型。该操作返回递增或递减后的key的值 > 例 ```bash 127.0.0.1:6379> SET key 0 OK 127.0.0.1:6379> INCR key (integer) 1 127.0.0.1:6379> INCR key (integer) 2 127.0.0.1:6379> DECR key (integer) 1 127.0.0.1:6379> DECR key (integer) 0 127.0.0.1:6379> DECR key (integer) -1 ``` #### INCRBY key increment 加指定值 | DECRBY key decrement | 减指定值 > 自1.0.0起可用。 - `INCRBY key increment`:按增量`increment`增加存储在键上的数字 - `DECRBY key decrement`:以递减`decrement`的方式递减存储在键中的数字。 如果密钥不存在,则将其设置为0,然后再执行操作。如果键包含错误类型的值或包含不能表示为整数的字符串,则返回错误。该操作仅限于64位有符号整数。 > 例 ```bash 127.0.0.1:6379> SET key 5 OK 127.0.0.1:6379> INCRBY key 3 (integer) 8 127.0.0.1:6379> DECRBY key 10 (integer) -2 ``` ### MGET key [key ...] 批量获取值 > 自1.0.0起可用。 返回所有指定键的值。对于每个不包含字符串值或不存在的键,将返回特殊值`nil`。因此,操作永远不会失败。 > 例 ```bash 127.0.0.1:6379> SET key1 hello OK 127.0.0.1:6379> SET key2 world OK 127.0.0.1:6379> MGET key1 key2 key3 1) "hello" 2) "world" 3) (nil) ``` ### MSET key value [key value ...] 批量设置值 > 自1.0.1起可用。 将给定的键设置为其各自的值。像常规的`SET`一样,`MSET`用新值替换现有值。如果不想覆盖现有值,请参阅`MSETNX`。`MSET`是原子性的,所以所有给定的键都是一次性设置的。客户端不可能看到一些键被更新而另一些键没有改变。 > 例 ```bash 127.0.0.1:6379> MSET key1 hello key2 world OK 127.0.0.1:6379> MGET key1 key2 1) "hello" 2) "world" ``` ### MSETNX key value [key value ...] 批量设置值(仅当键不存在) > 自1.0.1起可用。 将给定的键设置为其各自的值。即使只有一个键已经存在,`MSETNX`也不会执行任何操作。因为这个语义`MSETNX`可以用来设置表示一个唯一逻辑对象的不同字段的不同键,以确保要么设置所有字段,要么根本不设置。`MSETNX`是原子性的,所以所有给定的键都是一次性设置的。客户端不可能看到一些键被更新而另一些键没有改变。 > 例 ```bash 127.0.0.1:6379> MSETNX key1 hello key2 world (integer) 1 127.0.0.1:6379> MSETNX key3 redis key2 world (integer) 0 127.0.0.1:6379> MGET key1 key2 key3 1) "hello" 2) "world" 3) (nil) ``` # List 列表 ## 简介 Redis列表是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边)。它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。  ## 数据结构 List的数据结构为快速链表quickList。首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是`ziplist`,也即是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当数据量比较多的时候才会改成`quicklist`。因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是`int`类型的数据,结构上还需要两个额外的指针`prev`和`next`。  Redis将链表和`ziplist`结合起来组成了`quicklist`。也就是将多个`ziplist`使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。 ## 常用命令 ### LRANGE key start stop 按指定范围查看列表的值 > 自1.0.0起可用。 返回存储在键的列表的指定元素。偏移量`start`和`stop`是从`0`开始的。0是列表的第一个元素(列表的头),1是下一个元素,以此类推。这些偏移量也可以是负数,表示从列表末尾开始的。例如,-1是列表的最后一个元素,-2倒数第二个,依此类推。超出范围的索引不会产生错误。如果start大于列表的末尾,则返回一个空列表。如果stop大于列表的实际末尾,则Redis会将其视为列表的最后一个元素。 > 例 ```bash 127.0.0.1:6379> RPUSH list 1 (integer) 1 127.0.0.1:6379> RPUSH list 2 (integer) 2 127.0.0.1:6379> RPUSH list 3 (integer) 3 127.0.0.1:6379> LRANGE list 0 0 1) "1" 127.0.0.1:6379> LRANGE list -3 -2 1) "1" 2) "2" 127.0.0.1:6379> LRANGE list -100 100 1) "1" 2) "2" 3) "3" 127.0.0.1:6379> LRANGE list 100 200 (empty array) ``` ### RPUSH key element [element ...] 在列表右侧插值 | LPUSH key element [element ...] 在列表左侧插值 > 自1.0.0起可用。 在`key`存储的列表头部或尾部插入所有指定的值。如果`key`不存在,则在执行推操作之前将其创建为空列表。如果`key`保存的值不是**列表**,则返回错误。只要在命令末尾指定多个参数,就可以使用一个命令调用推入多个元素。该命令返回推送操作后列表的长度。 > 例:`RPUSH` ```bash 127.0.0.1:6379> RPUSH list1 a (integer) 1 127.0.0.1:6379> RPUSH list1 b (integer) 2 127.0.0.1:6379> RPUSH list1 c (integer) 3 127.0.0.1:6379> LRANGE list1 0 -1 1) "a" 2) "b" 3) "c" 127.0.0.1:6379> RPUSH list1 d e f (integer) 6 127.0.0.1:6379> LRANGE list1 0 -1 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" 6) "f" ``` > 例:`LPUSH` ```bash 127.0.0.1:6379> LPUSH list2 a (integer) 1 127.0.0.1:6379> LPUSH list2 b (integer) 2 127.0.0.1:6379> LPUSH list2 c (integer) 3 127.0.0.1:6379> LRANGE list2 0 -1 1) "c" 2) "b" 3) "a" 127.0.0.1:6379> LPUSH list2 d e f (integer) 6 127.0.0.1:6379> LRANGE list2 0 -1 1) "f" 2) "e" 3) "d" 4) "c" 5) "b" 6) "a" ``` #### RPUSHX key element [element ...] 仅key存在时在列表右侧插值 | LPUSHX key element [element ...] 仅key存在时在列表左侧插值 > 自2.2.0起可用。 仅当key已经存在并包含列表时,才在key存储的列表尾部或头部插入指定的值。与`RPUSH`或`LPUSH`相反,当键不存在时,不执行任何操作。 > 例:`RPUSHX`(`LPUSHX`同理) ```bash 127.0.0.1:6379> RPUSHX list a (integer) 0 127.0.0.1:6379> LRANGE list 0 -1 (empty array) 127.0.0.1:6379> RPUSH list a (integer) 1 127.0.0.1:6379> RPUSHX list a (integer) 2 127.0.0.1:6379> LRANGE list 0 -1 1) "a" 2) "a" ``` ### RPOP key [count] 从列表末尾获取元素并删除 | LPOP key [count] 从列表头部获取元素并删除 > 自1.0.0起可用。`count`参数自6.2起可用 删除并返回存储在键值中的列表的最后一个或第一个元素。默认情况下,该命令从列表的末尾或开通弹出一个元素。如果提供了可选的`count`参数,则返回最多包含count个元素,具体取决于列表的长度。 > 例:`RPOP`(`LPOP`同理) ```bash 127.0.0.1:6379> RPUSH a b c d e f (integer) 5 127.0.0.1:6379> RPUSH list a b c d e f (integer) 6 127.0.0.1:6379> RPOP list "f" 127.0.0.1:6379> LRANGE list 0 -1 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" 127.0.0.1:6379> RPOP list 2 1) "e" 2) "d" 127.0.0.1:6379> LRANGE list 0 -1 1) "a" 2) "b" 3) "c" 127.0.0.1:6379> RPOP list 100 1) "c" 2) "b" 3) "a" ``` ### LLEN key 列表长度 > 自1.0.0起可用 返回存储在键的列表的长度。如果key不存在,它将被解释为一个空列表并返回0。当存储在键的值不是列表时,将返回错误。 > 例 ```bash 127.0.0.1:6379> RPUSH list a b c (integer) 3 127.0.0.1:6379> LLEN list (integer) 3 ``` ### LINDEX key index 获取指定索引的值 > 自1.0.0起可用 返回存储在键的列表中的`index`处的元素。索引是从零开始的,所以0表示第一个元素,1表示第二个元素,以此类推。负索引可用于指定从列表尾部开始的元素。这里,-1表示最后一个元素,-2表示倒数第二个元素,以此类推。 > 例 ```bash 127.0.0.1:6379> RPUSH list a b c (integer) 3 127.0.0.1:6379> LINDEX list 0 "a" 127.0.0.1:6379> LINDEX list -1 "c" ``` ### LSET key index element 修改指定索引的值 > 自1.0.0起可用 将索引处的列表元素设置为新元素。对于超出范围的索引将返回一个错误。 > 例 ```bash 127.0.0.1:6379> RPUSH list a b c (integer) 3 127.0.0.1:6379> LRANGE list 0 -1 1) "a" 2) "b" 3) "c" 127.0.0.1:6379> LSET list 1 world OK 127.0.0.1:6379> LRANGE list 0 -1 1) "a" 2) "world" 3) "c" ``` ### LREM key count element 删除指定元素 > 自1.0.0起可用 从key存储的列表中删除与element相等的元素的第一次出现次数。count参数以以下方式影响操作: - `count > 0`:删除等于从头到尾移动的元素。 - `count < 0`:删除与从尾部移动到头部相等的元素。 - `count = 0`:删除所有等于element的元素。 例如,`LREM list -2 "hello"`将删除存储在list中的列表中最后两次出现的`“hello”`。注意,不存在的键被视为空列表,因此当键不存在时,该命令将始终返回0。 > 例 ```bash 127.0.0.1:6379> RPUSH list hello hello world hello (integer) 4 127.0.0.1:6379> LREM list -2 hello (integer) 2 127.0.0.1:6379> LRANGE list 0 -1 1) "hello" 2) "world" ``` ### LTRIM key start stop 裁剪列表 > 自1.0.0起可用 修改现有列表,使其只包含指定的元素范围。`start`和`stop`都是从零开始的索引,其中0是列表的第一个元素(头部),1是下一个元素,以此类推。例如:`LTRIM foobar 0 2`将修改存储在`foobar`中的列表,以便只保留列表的前三个元素。`start`和`end`也可以是负数,表示从列表末尾开始的偏移量,其中-1是列表的最后一个元素,-2是倒数第二个元素,以此类推。超出范围的索引不会产生错误:如果`start`大于列表的末尾,或者`start > end`,结果将是一个空列表(这将导致键被删除)。如果`end`大于列表的末尾,Redis会将其视为列表的最后一个元素。 > 例 ```bash 127.0.0.1:6379> RPUSH list a b c (integer) 3 127.0.0.1:6379> LTRIM list 1 -1 OK 127.0.0.1:6379> LRANGE list 0 -1 1) "b" 2) "c" ``` ### RPOPLPUSH source destination 从source列表右边吐出一个值,插到destination列表左边 根据Redis 6.2.0,`RPOPLPUSH`被视为已弃用。请在新代码中使用`LMOVE`。 > 自1.2.0起可用。 原子式地返回并删除存储在源端的列表的最后一个元素,并将该元素存储在目标端的列表的第一个元素。例如:`source`包含列表`a,b,c`,`destination`包含列表`x,y,z`。执行`RPOPLPUSH`的结果是,`source`变为`a,b`,`destination`变为`c,x,y,z`。如果`source`不存在,则返回值`nil`,不执行任何操作。如果源和目标相同,则该操作相当于从列表中删除最后一个元素并将其作为列表的第一个元素压入,因此可以认为它是一个列表旋转命令。 > 例 ```bash 127.0.0.1:6379> RPUSH list1 a b c (integer) 3 127.0.0.1:6379> RPUSH list2 1 2 3 (integer) 3 127.0.0.1:6379> RPOPLPUSH list1 list2 "c" 127.0.0.1:6379> LRANGE list1 0 -1 1) "a" 2) "b" 127.0.0.1:6379> LRANGE list2 0 -1 1) "c" 2) "1" 3) "2" 4) "3" ``` ### LMOVE source destination LEFT|RIGHT LEFT|RIGHT 从`source`移动元素值`destination` > 自6.2.0起可用。 原子式地返回并删除存储在`source`的列表的第一个/最后一个元素(取决于参数),并将元素存储在`destination`的列表的第一个/最后一个元素(取决于参数)。如果`source`不存在,则返回值`nil`,不执行任何操作。如果`source`和`destination`相同,则该操作相当于从列表中删除第一个/最后一个元素,并将其作为列表的第一个/最后一个元素推入。 > 例 ```bash 127.0.0.1:6379> RPUSH list1 a b c (integer) 3 127.0.0.1:6379> RPUSH list2 1 2 3 (integer) 3 127.0.0.1:6379> LMOVE list1 list2 RIGHT RIGHT "c" 127.0.0.1:6379> LRANGE list1 0 -1 1) "a" 2) "b" 127.0.0.1:6379> LRANGE list2 0 -1 1) "1" 2) "2" 3) "3" 4) "c" ``` ### LINSERT key BEFORE|AFTER pivot element 插入元素 > 自2.2.0起可用。 在指定键的列表中的指定值之前或之后的插入元素。当key不存在时,它被认为是一个空列表,不执行任何操作。如果key存在但不包含列表值,则返回错误。该操作返回插入操作后的列表长度,或未找到`pivot`时返回`-1`。 > 例 ```bash 127.0.0.1:6379> RPUSH list a b c (integer) 3 127.0.0.1:6379> LINSERT list AFTER b 123 (integer) 4 127.0.0.1:6379> LRANGE list 0 -1 1) "a" 2) "b" 3) "123" 4) "c" ``` > 例:若有多个`pivot`元素,仅从列表头开始匹配第一个 ``` 127.0.0.1:6379> RPUSH list a b a c (integer) 4 127.0.0.1:6379> LINSERT list AFTER a 123 (integer) 5 127.0.0.1:6379> LRANGE list 0 -1 1) "a" 2) "123" 3) "b" 4) "a" 5) "c" ``` # Set 集合 ## 简介 Redis的`set`对外提供的功能与`list`类似,是一个列表的功能,特殊之处在于`set`是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,`set`是一个很好的选择,并且`set`提供了判断某个成员是否在一个`set`集合内的重要接口,这个也是`list`所不能提供的。Redis的`set`是`string`类型的无序集合。它底层其实是一个`value`为`null`的`hash`表,所以添加,删除,查找的复杂度都是`O(1)`。 ## 数据结构 `set`数据结构是`dict`字典,字典是用哈希表实现的。Java中`HashSet`的内部实现使用的是`HashMap`,所有的`value`都指向同一个对象。Redis的`set`结构也是一样,它的内部也使用`hash`结构,所有的`value`都指向同一个内部值。 ## 常用命令 ### SADD key member [member ...] 添加元素到集合中 > 自1.0.0起可用。自2.4起,可添加多个元素 将指定的成员添加到存储在键的集合中。已经是该集合成员的指定成员将被忽略。如果key不存在,则在添加指定成员之前创建一个新集合。当存储在键的值不是一个集合时,将返回一个错误。返回值为添加到集合中的元素数,不包括集合中已经存在的所有元素。 > 例 ```bash 127.0.0.1:6379> SADD set a (integer) 1 127.0.0.1:6379> SMEMBERS set 1) "a" 127.0.0.1:6379> SADD set b c d (integer) 3 127.0.0.1:6379> SMEMBERS set 1) "b" 2) "a" 3) "d" 4) "c" 127.0.0.1:6379> SADD set b d e f (integer) 2 127.0.0.1:6379> SMEMBERS set 1) "b" 2) "f" 3) "c" 4) "a" 5) "e" 6) "d" ``` ### SCARD key 集合大小 > 自1.0.0起可用。 返回集合的元素个数。 > 例 ```bash 127.0.0.1:6379> SADD set a b c (integer) 3 127.0.0.1:6379> SCARD set (integer) 3 ``` ### SMEMBERS key 列出集合中的元素 > 自1.0.0起可用。 返回存储在键的set值的所有成员。这与运行带有一个参数键的`SINTER`具有相同的效果。 > 例 ```bash 127.0.0.1:6379> SADD set a b c (integer) 3 127.0.0.1:6379> SMEMBERS set 1) "b" 2) "a" 4) "c" ``` ### SISMEMBER key member 存在指定的元素 > 自1.0.0起可用。 如果`member`是存储在键值的集合的成员,则返回`1`,否则返回`0`。 > 例 ```bash 127.0.0.1:6379> SADD set a (integer) 1 127.0.0.1:6379> SISMEMBER set a (integer) 1 127.0.0.1:6379> SISMEMBER set b (integer) 0 ``` #### SMISMEMBER key member [member ...] 存在指定的多个元素 > 自6.2.0起可用。 返回每个元素是否在集合内。对于每个元素,如果元素在集合内则返回`1`,如果元素不在集合内或键不存在则返回`0`。 > 例 ```bash 127.0.0.1:6379> SADD set a (integer) 1 127.0.0.1:6379> SMISMEMBER set a b 1) (integer) 1 2) (integer) 0 ``` ### SRANDMEMBER key [count] 随机取出一个或多个元素 > 自1.0.0起可用。自2.6.0起添加`count`参数。 - 当只使用key参数调用时,从集合中随机返回一个随机元素。 - 如果提供的`count`参数为正数,则随机返回不超过集合最大个数的`count`个元素,且没有重复元素。 - 如果提供的`count`参数为负数,则随机返回`count`个元素且允许多次返回相同的元素。 > 例 ```bash 127.0.0.1:6379> SADD set a b c d e (integer) 5 127.0.0.1:6379> SRANDMEMBER set "e" 127.0.0.1:6379> SRANDMEMBER set 3 1) "a" 2) "e" 3) "d" 127.0.0.1:6379> SRANDMEMBER set 8 1) "b" 2) "c" 3) "a" 4) "d" 5) "e" 127.0.0.1:6379> SRANDMEMBER set -3 1) "b" 2) "a" 3) "d" 127.0.0.1:6379> SRANDMEMBER set -8 1) "e" 2) "c" 3) "c" 4) "b" 5) "e" 6) "e" 7) "a" 8) "c" ``` #### SPOP key [count] 随机取出一个或多个元素并删除 > 自1.0.0起可用。自3.2起添加`count`参数。 从集合中随机移除并返回一个或多个成员。此操作类似于`SRANDMEMBER`。默认情况下,该命令从集合中弹出一个成员。当提供可选的`count`参数时,将返回不超过集合最大个数的`count`个成员。 > 例 ```bash 127.0.0.1:6379> SADD set a b c d e (integer) 5 127.0.0.1:6379> SPOP set "e" 127.0.0.1:6379> SPOP set 2 1) "b" 2) "a" 127.0.0.1:6379> SPOP set 5 1) "d" 2) "c" ``` ### SREM key member [member ...] 删除指定元素 > 自1.0.0起可用。 从集合中删除指定的成员,并返回成功删除的成员数,不属于该集合的指定成员将被忽略。如果`key`不存在,则将其视为空集,并返回`0`。当存储在键的值不是一个集合时,将返回一个错误。 > 例 ```bash 127.0.0.1:6379> SADD set a b c (integer) 3 127.0.0.1:6379> SREM set a c e (integer) 2 127.0.0.1:6379> SMEMBERS set 1) "b" ``` ### SMOVE source destination member 移动指定元素 > 自1.0.0起可用。 将指定元素从`source`集合移动到`destination`集合。这个操作是原子性的。在每个给定时刻,元素都将显示为其他客户端的源或目标成员。如果`source`集合不存在或不包含指定的元素,则不执行任何操作并返回`0`。当指定的元素已经存在于`destination`集合中时,它只会从`source`集合中移除。 > 例 ```bash 127.0.0.1:6379> SADD set1 a b c (integer) 3 127.0.0.1:6379> SMOVE set1 set2 a (integer) 1 127.0.0.1:6379> SMEMBERS set1 1) "b" 2) "c" 127.0.0.1:6379> SMEMBERS set2 1) "a" 127.0.0.1:6379> SMOVE set1 set2 d (integer) 0 ``` ### 交集 | 并集 | 差集 #### SINTER key [key ...] 交集 > 自1.0.0起可用。 返回所有给定集合的交集。不存在的键被认为是空集。如果其中一个键是空集,那么结果集也是空的(因为集合与空集的交集总是产生一个空集)。 > 例 ```bash 127.0.0.1:6379> SADD set1 a b c (integer) 3 127.0.0.1:6379> SADD set2 a d f (integer) 3 127.0.0.1:6379> SINTER set1 set2 1) "a" 127.0.0.1:6379> SINTER set1 set3 (empty array) ``` #### SUNION key [key ...] 并集 > 自1.0.0起可用。 返回所有给定集合的并集。不存在的键被认为是空集。 > 例 ```bash 127.0.0.1:6379> SADD set1 a b c (integer) 3 127.0.0.1:6379> SADD set2 a d f (integer) 3 127.0.0.1:6379> SUNION set1 set2 1) "a" 2) "b" 3) "f" 4) "c" 5) "d" 127.0.0.1:6379> SUNION set1 set3 1) "a" 2) "b" 3) "c" ``` #### SDIFF key [key ...] 差集 > 自1.0.0起可用。 返回所有给定集合的差集。不存在的键被认为是空集。 > 例 ```bash 127.0.0.1:6379> SADD set1 a b c (integer) 3 127.0.0.1:6379> SADD set2 a d f (integer) 3 127.0.0.1:6379> SDIFF set1 set2 1) "b" 2) "c" 127.0.0.1:6379> SDIFF set2 set1 1) "d" 2) "f" 127.0.0.1:6379> SDIFF set1 set3 1) "a" 2) "b" 3) "c" ``` #### SINTERSTORE destination key [key ...] | SUNIONSTORE destination key [key ...] | SDIFFSTORE destination key [key ...] 计算交并差集并存入目标集合 > 自1.0.0起可用。 这三个命令等于上文中对应的三个命令,但是它不是返回结果集,而是将结果集即存储在目标集合中,并返回结果集的元素数量。如果目标已经存在,它将被覆盖(注意是覆盖,不是添加)。 > 例 ```bash 127.0.0.1:6379> SADD set1 a b c (integer) 3 127.0.0.1:6379> SADD set2 a d f (integer) 3 127.0.0.1:6379> SINTERSTORE dset set1 set2 (integer) 1 127.0.0.1:6379> SMEMBERS dset 1) "a" 127.0.0.1:6379> SUNIONSTORE dset set1 set2 (integer) 5 127.0.0.1:6379> SMEMBERS dset 1) "a" 2) "b" 3) "f" 4) "c" 5) "d" 127.0.0.1:6379> SDIFFSTORE dset set1 set2 (integer) 2 127.0.0.1:6379> SMEMBERS dset 1) "b" 2) "c" ``` # Hash 哈希散列 ## 简介 `Redis`的`hash`是一个键值对集合。`Redis`的`hash`是一个`string`类型的`field`和`value`的映射表,`hash`特别适合用于存储对象。类似`Java`里面的`HashMap<String,Object>` ### Object对象的多种存储方式介绍 > 说明: 有如下`Object`对象,需要存储到Redis中 ```java User tom1 = new User(); tom.setId(1); tom.setName("Tom"); tom.setAge(18); ``` > 方式1:序列化 将`tom1`作为键,将对象序列化作为值,并使用`SET`命令存储。  产生问题:每次修改需要先取出反序列化,修改后再序列化并存储,开销较大 > 方式2:合并字段 将`tom1`和字段合并为键,并字段的值作为值,使用`SET`存储。  产生问题:部分数据冗余 > 方式3:散列 将`tom1`作为键,将`name`等作为字段,将字段的值作为值,使用`HSET`存储  通过`key + field`就可以操作对应属性数据,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。 ## 数据结构 `Hash`类型对应的数据结构是两种:`ziplist`(压缩列表),`hashtable`(哈希表)。当`field-value`长度较短且个数较少时,使用`ziplist`,否则使用`hashtable`。 ## 常用命令 ### HSET key field value [field value ...] 给哈希散列添加字段和值 > 自2.0.0起可用。 将哈希散列中的字段设置为`value`。如果哈希散列不存在,则创建一个包含哈希散列的新键。如果字段已经存在于哈希散列中,则将覆盖该字段。从`Redis 4.0.0`开始,`HSET`是可变的,允许多个`field/value`。该操作返回添加的字段数。 > 例 ```bash 127.0.0.1:6379> HSET user name tom age 18 (integer) 2 127.0.0.1:6379> HGET user name "tom" 127.0.0.1:6379> HGET user age "18" ``` > 注:`HMSET key field value [field value ...]`已弃用,被`HSET`代替 #### HSETNX key field value 给哈希散列添加字段和值(仅字段不存在) 仅当字段不存在时,将哈希散列的字段设置值。如果哈希散列不存在,则创建一个包含哈希散列的新键。如果该字段已经存在,则该操作无效。操作成功返回1,失败返回0 > 例 ```bash 127.0.0.1:6379> HSETNX user name tom (integer) 1 127.0.0.1:6379> HSETNX user name tom (integer) 0 127.0.0.1:6379> HGET user name "tom" ``` ### HGET key field 获取哈希散列的指定字段的值 > 自2.0.0起可用。 返回与哈希散列中的字段相关联的值。当字段不在哈希散列中或哈希散列不存在时返回`nil`。 > 例 ```bash 127.0.0.1:6379> HSET user name tom age 18 (integer) 2 127.0.0.1:6379> HGET user name "tom" 127.0.0.1:6379> HGET user address (nil) ``` #### HMGET key field [field ...] 获取哈希散列的多个字段的值 > 自2.0.0起可用。 返回哈希散列中指定字段的值。对于哈希散列中不存在该字段,将返回一个`nil`值。因为不存在的键被视为空哈希散列,所以针对不存在的哈希散列运行`HMGET`将返回一个空值列表。 > 例 ```bash 127.0.0.1:6379> HSET user name tom age 18 (integer) 2 127.0.0.1:6379> HMGET user name age address 1) "tom" 2) "18" 3) (nil) 127.0.0.1:6379> HMGET employee name age address 1) (nil) 2) (nil) 3) (nil) ``` #### HGETALL key 获取哈希散列的所有字段与值 > 自2.0.0起可用。 返回哈希散列的所有字段和值。在返回值中,每个字段名后面都跟着它的值,因此返回的长度是哈希散列大小的两倍。 > 例 ```bash 127.0.0.1:6379> HSET user name tom age 18 (integer) 2 127.0.0.1:6379> HGETALL user 1) "name" 2) "tom" 3) "age" 4) "18" ``` ### HEXISTS key field 哈希散列是否存在指定字段 > 自2.0.0起可用。 如果字段是哈希散列中的现有字段,则返回`1`,否则返回`0`。 > 例 ```bash 127.0.0.1:6379> HSET user name tom (integer) 1 127.0.0.1:6379> HEXISTS user name (integer) 1 127.0.0.1:6379> HEXISTS user age (integer) 0 ``` ### HDEL key field [field ...] 删除指定哈希散列的指定字段 > 自2.0.0起可用。自2.4起接受多个字段参数。 从哈希散列中删除指定的字段,并返回成功删除的字段数。此散列中不存在的指定字段将被忽略。如果哈希散列不存在,则将其视为空哈希散列,此命令返回0。 > 例 ```bash 127.0.0.1:6379> HSET user name tom age 18 address shanghai (integer) 3 127.0.0.1:6379> HDEL user name age (integer) 2 127.0.0.1:6379> HGETALL user 1) "address" 2) "shanghai" ``` ### HLEN key 哈希散列的长度 > 自2.0.0起可用。 返回哈希散列中包含的字段数。哈希散列不存在时返回0。 > 例 ```bash 127.0.0.1:6379> HSET user name tom age 18 address shanghai (integer) 3 127.0.0.1:6379> HLEN user (integer) 3 127.0.0.1:6379> HLEN employee (integer) 0 ``` ### HSTRLEN key field 哈希散列的字段的长度 > 自3.2.0起可用。 返回哈希散列的字段的值的字符串长度。如果该哈希散列或字段不存在,则返回0。 > 例 ```bash 127.0.0.1:6379> HSET user name tom (integer) 3 127.0.0.1:6379> HSTRLEN user name (integer) 3 ``` ### HKEYS key 哈希散列的所有字段 | HVALS key 哈希散列的所有值 > 自2.0.0起可用。 返回哈希散列中的所有字段名或所有值。 > 例 ```bash 127.0.0.1:6379> HSET user name tom age 18 address shanghai (integer) 3 127.0.0.1:6379> HKEYS user 1) "name" 2) "age" 3) "address" 127.0.0.1:6379> HVALS user 1) "tom" 2) "18" 3) "shanghai" ``` ### HINCRBY key field increment 增减哈希散列中指定字段的值 > 自2.0.0起可用。 以增量的方式递增哈希散列的字段中的数字。如果哈希散列不存在,则创建一个包含散列的新哈希散列。如果字段不存在,则在执行操作前将值设置为0。`HINCRBY`支持的值范围仅限于64位有符号整数。 > 例 ```bash 127.0.0.1:6379> HSET user money 10 (integer) 1 127.0.0.1:6379> HINCRBY user money 5 (integer) 15 127.0.0.1:6379> HINCRBY user money -20 (integer) -5 127.0.0.1:6379> HINCRBY user age 18 (integer) 18 127.0.0.1:6379> HGETALL user 1) "money" 2) "-5" 3) "age" 4) "18" ``` # Zset 有序集合(Sorted Sets) ## 简介 Redis的有序集合`zset`与普通集合`set`非常相似,是一个没有重复元素的字符串集合。不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复的。因为元素是有序的,所以可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。访问有序集合的中间元素也是非常快的,因此能够使用有序集合作为一个没有重复成员的智能列表。 ## 数据结构 `Sorted Set (Zset)`是`Redis`提供的一个非常特别的数据结构,一方面它等价于`Java`的数据结构`Map<String, Double>`,可以给每一个元素`value`赋予一个权重`score`,另一方面它又类似于`TreeSet`,内部的元素会按照权重`score`进行排序,可以得到每个元素的名次,还可以通过`score`的范围来获取元素的列表。 `zset`底层使用了两个数据结构 1. `hash`:`hash`的作用就是关联元素`value`和权重`score`,保障元素`value`的唯一性,可以通过元素`value`找到相应的`score`值。 2. `跳跃表`:`跳跃表`的目的在于给元素`value`排序,根据`score`的范围获取元素列表。 ### 跳跃表 #### 简介 有序集合在生活中比较常见,例如根据成绩对学生排名,根据得分对玩家排名等。对于有序集合的底层实现,可以用数组、平衡树、链表等。数组不便元素的插入、删除;平衡树或红黑树虽然效率高但结构复杂;链表查询需要遍历所有效率低。`Redis`采用的是跳跃表。跳跃表效率堪比红黑树,实现却比红黑树简单。 #### 实例 *对比有序链表和跳跃表,从链表中查询出51* > 有序列表  要查找值为51的元素,需要从第一个元素开始依次查找、比较才能找到。共需要6次比较。 > 跳跃表  1. 从第2层开始,1节点比51节点小,向后比较。21节点比51节点小,继续向后比较,后面就是NULL了,所以从21节点向下到第1层 2. 在第1层,41节点比51节点小,继续向后,61节点比51节点大,所以从41向下 3. 在第0层,51节点为要查找的节点,节点被找到,共查找4次。 从此可以看出跳跃表比有序链表效率要高 ## 常用命令 ### ZADD key score member 将一个或多个member及source添加到排序集合中 `ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member ...]` > 自1.2.0起可用。 自2.4起,接受多个元素。 自3.0.2起,增加了XX,NX,CH和INCR选项。 自6.2起,添加了GT和LT选项。 将具有指定分数的所有指定成员添加到排序集合。可以指定多个`score / member`对。如果指定的成员已经是排序集合的成员,则更新`score`并将元素重新插入到正确的位置,以确保正确的排序。如果key不存在,将创建一个新的排序集合,其中指定的成员作为唯一的成员,就像排序集为空一样。如果键存在,但不是排序集合,则返回错误。分数值应该是双精度浮点数的字符串表示形式。`+inf`和`-inf`值也是有效值。 `ZADD`支持一个选项列表,在键名之后和第一个`score`参数之前指定。选项有: - `XX`:只更新已经存在的元素。没有添加元素。 - `NX`:不要更新已经存在的元素。总是添加新元素。 - `LT`:只有当新分数小于当前分数时才更新现有的元素。这个标志并不阻止添加新元素。 - `GT`:只有当新分数大于当前分数时才更新现有的元素。这个标志并不阻止添加新元素。 - `CH`:将返回值从添加的新元素数量修改为更改的总元素数量(CH是changed的缩写)。改变的元素是指添加的新元素和已经存在并更新了分数的元素。因此,在命令行中指定的具有与过去相同分数的元素将不被计算。注意:通常`ZADD`的返回值只计算添加的新元素的数量。 - `INCR`:当指定此选项时,`ZADD`的行为类似于`ZINCRBY`。在此模式中只能指定一个分数元素对。 注:`GT`、`LT`和`NX`选项是互斥的。 > 例 ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZRANGE zset 0 -1 WITHSCORES 1) "english" 2) "60" 3) "chinese" 4) "80" 5) "maths" 6) "90" ``` ### ZRANGE key min max 返回排序集合中的指定范围的元素 `ZRANGE key min max [BYSCORE|BYLEX] [REV] [LIMIT offset count] [WITHSCORES]` > 自1.2.0起可用。 返回存储在<key>的排序集合中指定的元素范围。`ZRANGE`可以执行不同类型的范围查询:按索引(排名)、按分数或按字典序。 - 常见行为和选项: - 元素的顺序从最低到最高。得分相同的元素按字典顺序排列。 - 可选的`REV`参数颠倒了顺序,因此元素按从最高到最低的分数排序,而分数关系则通过反向字典序来解析。 - 可选的`LIMIT`参数可用于从匹配的元素中获取子范围(类似于SELECT LIMIT offset, count在SQL中)。负数<count>返回<偏移量>中的所有元素。请记住,如果<偏移量>的偏移量较大,则需要遍历<偏移量>的元素,然后才能返回返回的元素,这可能会增加O(N)的时间复杂度。 - 可选的`WITHSCORES`参数用返回的元素的分数补充命令的应答。返回的列表包含`value1,score1,…,valueN,scoreN`代替`value1,…,valueN`。客户端库可以自由返回更合适的数据类型(建议:包含(value, score)数组/元组的数组)。 - 索引范围: - 缺省情况下,执行索引范围查询。<min>和<max>参数表示从零开始的索引,其中0是第一个元素,1是下一个元素,以此类推。这些参数指定了一个包含范围,因此,例如,ZRANGE myzset 0 1将返回排序集合的第一个和第二个元素。 - 索引也可以是负数,表示从排序集的末尾开始的偏移量,其中-1是排序集的最后一个元素,-2是倒数第二个元素,以此类推。 - 超出范围的索引不会产生错误。 - 如果<min>大于排序集合的结束索引或<max>,则返回一个空列表。 - 如果<max>大于排序集合的结束索引,Redis将使用排序集合的最后一个元素。 - 分数范围 - 当提供BYSCORE选项时,该命令的行为类似于ZRANGEBYSCORE,并返回分值等于或介于<min>和<max>之间的排序集合中的元素范围。 - <min>和<max>可以是-inf和+inf,分别表示负无穷和正无穷。这意味着不需要知道排序集合中的最高或最低分数才能获得从某个分数开始的或到某个分数为止的所有元素。 - 默认情况下,<min>和<max>指定的评分间隔是封闭的(包括在内)。可以通过在分数前加上字符`(`/`)`来指定开放间隔(不包括)。 - 辞典范围 - 当使用BYLEX选项时,该命令的行为类似于ZRANGEBYLEX,并返回排序集合中<min>和<max>字典序封闭范围间隔之间的元素范围。 - 请注意,字典顺序依赖于所有得分相同的元素。当元素有不同的分数时,应答是未指定的。 - 有效的<min>和<max>必须以(或[开头,以便分别指定范围间隔是exclusive还是inclusive。 - 特殊值+或- <min>和<max>分别表示正的和负的无限字符串,所以例如命令ZRANGEBYLEX myzset - +保证返回排序集合中的所有元素,前提是所有元素的得分相同。 注:以下命令在`Redis 6.2.0`被弃用,均被`ZRANGE`替代 - ZREVRANGE key start stop [WITHSCORES] - ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] - ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count] - ZRANGEBYLEX key min max [LIMIT offset count] - ZREVRANGEBYLEX key max min [LIMIT offset count] > 例 ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZRANGE zset 0 -1 1) "english" 2) "chinese" 3) "maths" 127.0.0.1:6379> ZRANGE zset 0 -1 WITHSCORES 1) "english" 2) "60" 3) "chinese" 4) "80" 5) "maths" 6) "90" ``` #### ZRANGESTORE dst src min max 查找排序集合中的指定范围的元素并存入目标排序集合 `ZRANGESTORE dst src min max [BYSCORE|BYLEX] [REV] [LIMIT offset count]` > 自6.2.0起可用。 此命令类似于`ZRANGE`,但是将结果存储在`<dst>`目标键中。 > 例 ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZRANGESTORE zset2 zset 1 -2 (integer) 1 127.0.0.1:6379> ZRANGE zset2 0 -1 1) "chinese" ``` ### ZCARD key 返回排序集合的元素数量 > 自1.2.0起可用。 返回存储在的排序集的排序集基数(元素数)key。 > 例 ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZCARD zset (integer) 3 ``` ### ZCOUNT key min max 统计指定范围内的元素数量 > 自2.0.0起可用。 返回排序集合中键值在`min`和`max`之间的元素数。min和max参数具有与`ZRANGE`描述的相同的语义。 > 例 ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZCOUNT zset -inf +inf (integer) 3 ``` ### ZSCORE key member 返回排序集中key的分数 > 自1.2.0起可用。 返回排序集合中成员的得分。如果成员不存在于排序集合中,或者键不存在,则返回nil。 > 例 ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZSCORE zset chinese "80" 127.0.0.1:6379> ZMSCORE zset chinese maths history 1) "80" 2) "90" 3) (nil) ``` #### ZMSCORE key member [member ...] 返回排序集中key的分数(多个key) > 自6.2.0起可用。 返回排序集合中多个成员和其相关联的分数。对于排序集合中不存在的每个成员,将返回一个nil值。 > 例 ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZMSCORE zset chinese maths history 1) "80" 2) "90" 3) (nil) ``` ### ZRANK key member | ZREVRANK key member 正序或倒序排名 > 自2.0.0起可用。 返回排序集合中的成员的排名,分数按从低到高或从高到低的顺序排序。排名(或索引)是从0开始,这意味着得分最低或最高的成员排名为0。 > 例 ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZRANK zset maths (integer) 2 127.0.0.1:6379> ZREVRANK zset maths (integer) 0 ``` ### ZINCRBY key increment member 给指定元素增减分数 > 自1.2.0起可用。 按增量递增排序集合中的成员的得分,并返回成员的新分数(双精度浮点数),表示为字符串。如果成员在排序集合中不存在,则将其添加为增量作为其分数(就像其以前的分数是0.0)。如果key不存在,则创建一个新的排序集合,其中指定的成员作为其唯一成员。如果键存在但不是排序集合,则返回错误。分数值应该是数字值的字符串表示形式,并接受双精度浮点数。可以提供一个负值来减少分数。 > 例 ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZINCRBY zset 12.5 chinese "92.5" ``` ### ZREM key member [member ...] 删除元素 > 自1.2.0起可用。自2.4起接受多个元素。 从排序集合中删除指定成员,并返回移除的成员数,不存在的成员将被忽略。如果键存在但不是排序集合,则返回错误。 > 例 ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZREM zset chinese history (integer) 1 127.0.0.1:6379> ZRANGE zset 0 -1 1) "english" 2) "maths" ``` ### ZPOPMAX key [count] | ZPOPMIN key [count] 删除并返回多个分数最大或最小的元素 > 自5.0.0起可用。 删除并返回排序集合中得分最高或最低的成员。当未指定时,count的默认值是1。指定一个大于排序集合总数量的数值将不会产生错误。当返回多个元素时,得分最高或最低的元素将是第一个,然后是得分较低或较高的元素。 > 例:ZPOPMAX ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZPOPMAX zset 3 1) "maths" 2) "90" 3) "chinese" 4) "80" 5) "english" 6) "60" ``` > 例:ZPOPMIN ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 english (integer) 3 127.0.0.1:6379> ZPOPMIN zset 3 1) "english" 2) "60" 3) "chinese" 4) "80" 5) "maths" 6) "90" ``` ### ZRANDMEMBER key [count [WITHSCORES]] 随机返回元素 > 自6.2.0起可用。 当仅使用key参数调用时,从排序集合中返回一个随机元素。如果提供的count参数为正数,则返回一个包含不同元素的数组。数组的长度可以是count,也可以是排序集合的基数(ZCARD),两者以较低者为准。如果以负数计数调用,则行为会改变,并且允许命令多次返回相同的元素。可选的WITHSCORES修饰符更改应答,使其包含从排序集合中随机选择的元素的各自分数。 > 例: ```bash 127.0.0.1:6379> ZADD zset 80 chinese 90 maths 60 englis (integer) 3 127.0.0.1:6379> ZRANDMEMBER zset 2 1) "chinese" 2) "englis" 127.0.0.1:6379> ZRANDMEMBER zset 5 WITHSCORES 1) "maths" 2) "90" 3) "chinese" 4) "80" 5) "englis" 6) "60" 127.0.0.1:6379> ZRANDMEMBER zset -1 WITHSCORES 1) "chinese" 2) "80" 127.0.0.1:6379> ZRANDMEMBER zset -5 WITHSCORES 1) "chinese" 2) "80" 3) "chinese" 4) "80" 5) "chinese" 6) "80" 7) "englis" 8) "60" 9) "englis" 10) "60" ``` # 补充:原子性 所谓**原子操作**是指:**不会被线程调度机制打断的操作**; 这种操作一旦开始,就一直运行到结束,中间不会有任何`context switch`(切换到另一个线程)。 1. 在单线程中,能够在单条指令中完成的操作都可以认为是“原子操作”,因为中断只能发生于指令之间。 2. 在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。 Redis单命令的原子性主要得益于Redis的单线程。
4
全部评论