Redis数据类型
Redis基础
- 1. Redis前置命令知识
- 1.1 基本全局命令
- KEYS
- EXISTS
- DEL
- EXPIRE
- TTL
- TYPE
- 2. String 字符串
- 2.1 字符串数据类型
- 2.2 内部编码
- 2.3 常见命令
- SET
- GET
- MGET
- MSET
- SETNX
- INCR INCRBY
- DECR DECRBY
- INCRBYFLOAT
- APPEND
- GETRANGE
- SETRANGE
- STRLEN
- 2.4 典型使用场景
- 3. Hash 哈希
- 3.1 基本命令
- HSET
- HGET
- HEXISTS
- HDEL
- HKEYS
- HVALS
- HGETALL
- HMGET
- HLEN
- HSETNX
- HINCRBY HINCRBYFLOAT
- HSTRLEN
- 3.2 内部编码
- 3.3 使用场景
- List列表
- 命令
- LPUSH、LPUSHX、RPUSH、RPUSHX
- LRANGE
- LPOP RPOP
- LINDEX
- LINSERT
- LLEN
- 阻塞版命令 blpop brpop
- 4.2 内部编码
- 4.3 使用场景
- 5. Set集合
- 5.1 基本命令
- SADD
- SMEMBERS
- SISMEMBER
- SCARD
- SPOP
- SMOVE
- SREM
- 交集(inter)、并集(union)、差集(diff)
- 5.2 内部编码
- 5.3使用场景
- 6.Zset有序集合
- 基本命令
- ZADD
- ZCARD
- ZCOUNT
- ZRANGE
- ZREVANGE
- ZRANGEBYSCORE
- ZPOPMAX BZPOPMAX
- ZPOPMIN BZPOPMIN
- ZRANK ZREVRANK
- ZSCORE
- ZREM
- ZREMRANGBYRANK
- ZREMRANGEBYSCORE
- ZINCRBY
- ZINTERSTORE
- ZUNIONSTORE
- 6.2内部编码
- 6.3 使用场景
- 7.SCAN 渐进式遍历
1. Redis前置命令知识
1)Redis 的命令有上百个,如果纯靠死记硬背比较困难,但是如果理解 Redis 的一些机制,会发现这些命令有很强的通用性。
2)Redis不是万金油,有些数据结构和命令必须在特定场景下使用,一旦使用不当可能对 Redis 本身或者应用本身造成致命伤害。
1.1 基本全局命令
KEYS
KEYS pattern
返回值:匹配pattern的所有key
时间复杂度O(n)
支持如下匹配样式:
EXISTS
EXISTS key [key …]
返回值:key存在的个数
时间复杂度O(1)
DEL
DEL key [key …]
返回值:删除掉key的个数
时间复杂度O(1)
EXPIRE
为指定的key添加秒级的过期时间
EXPIRE key seconds
返回值:1表示设置成功、0表示设置失败
时间复杂度O(1)
TTL
获取指定key的过期时间,秒级
TTL key
返回值:剩余过期时间。-1表示没有关联过期时间,-2表示key不存在
时间复杂度O(1)
TYPE
返回key对应的数据类型
TYPE key
返回值:none, string, list, set, zset, hash, stream
2. String 字符串
2.1 字符串数据类型
我们说的数据类型一般说的都是value。
2.2 内部编码
Redis会根据当前值的类型和长度动态决定使用哪个内部实现,字符串类型的编码有三种格式:
- int: 8个字节的长整形。
- embstr:<=39个字节的字符串
- raw:>39个字节的字符串
例如:
2.3 常见命令
SET
将string类型的value设置到key中。若key存在则覆盖,无论原来什么类型,并且之前如果有TTL也会失效
语法:SET key value [expiration EX seconds | PX milliseconds] [NX | XX]
时间复杂度: O(1)
选项的用处:
expiration EX seconds | PX milliseconds 使用秒或者毫秒作为过期时间
NX:只在key不存在时才设置,如果key之前存在,设置不执行/
XX:只在key存在时才设置,如果key不存在,则设置不执行
返回值:成功返回OK,NX或者XX条件不满足,返回nil。
redis> EXISTS mykey
(integer) 0
redis> SET mykey "Hello"
OK
redis> GET mykey
"Hello"
redis> SET mykey "World" NX
(nil)
redis> DEL mykey
(integer) 1
redis> EXISTS mykey
(integer) 0
redis> SET mykey "World" XX
(nil)
redis> GET mykey
(nil)
redis> SET mykey "World" NX
OK
redis> GET mykey
"World"
redis> SET mykey "Will expire in 10s" EX 10
OK
redis> GET mykey
"Will expire in 10s"
redis> GET mykey # 10秒之后
(nil)
GET
获取key对应的value。如果key不存在,返回nil。如果value的类型不是string,报错。
GET key
时间复杂度:O(1)
返回值:key对应的value,或者nil当key不存在
redis> GET nonexisting
(nil)
redis> SET mykey "Hello"
"OK"
redis> GET mykey
"Hello"
redis> DEL mykey
(integer) 1
redis> EXISTS mykey
(integer) 0
redis> HSET mykey name Bob
(integer) 1
redis> GET mykey
(error) WRONGTYPE Operation against a key holding the wrong kind of value
MGET
一次性获取多个key的值。如果对应的key不存在或者对应的数据类型不是string,返回nil。
MGET key [key …]
时间复杂度:O(N)N是key的数量
返回值:对应value的列表
redis> SET key1 "Hello"
"OK"
redis> SET key2 "World"
"OK"
redis> MGET key1 key2 nonexisting
1) "Hello"
2) "World"
3) (nil)
MSET
一次性设置多个key值
MSET key value [ key value …]
时间复杂度:O(N)N是key的数量
返回值:永远是OK
redis> MSET key1 "Hello" key2 "World"
"OK"
redis> GET key1
"Hello"
redis> GET key2
"World"
注意:虽然批量操作是执行N次,但是它在网络传输中,中传输一次命令。
SETNX
只在key不存在的情况下才设置key-value
SETNX key value
时间复杂度:O(1)
返回值:1表示设置成功。0表示没设置。
redis> SETNX mykey "Hello"
(integer) 1
redis> SETNX mykey "World"
(integer) 0
redis> GET mykey
"Hello"
INCR INCRBY
将key对应的syring表示的数字加一。如果key不存在,则视为key对应的value是0.如果key对应的string不是一个整型或者超过了64位符号整形,则报错。
INCR key
INCRBY key decrement
时间复杂度:O(1)
integer 类型的加完后的数值。
redis> EXISTS mykey
(integer) 0
redis> INCR mykey
(integer) 1
redis> SET mykey "10"
"OK"
redis> INCR mykey
(integer) 11
redis> SET mykey "234293482390480948029348230948"
"OK"
redis> INCR mykey
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
"OK"
redis> INCR mykey
(error) value is not an integer or out of range`
DECR DECRBY
将key对应的string表示的数字减1。如果key不存在,则视为key对应的value是0.如果key对应的string不是一个整型,或者超范围了,则报错。
DECR key
DECRBY key decrement
时间复杂度:O(1)
返回值:integer类型的减完后的数值。
redis> EXISTS mykey
(integer) 0
redis> DECR mykey
(integer) -1
redis> SET mykey "10"
"OK"
redis> DECR mykey
(integer) 9
redis> SET mykey "234293482390480948029348230948"
"OK"
redis> DECR mykey
(error) value is not an integer or out of range
redis> SET mykey 'not a number'
"OK"
redis> DECR mykey
(error) value is not an integer or out of range
INCRBYFLOAT
将key对应的string表示的浮点数加上对应的值。如果key不存在,则视为key对应的value是0.如果key对应的不是string,或者不是一个浮点数,则报错。允许采用科学计数法表示浮点数
INCRBYFLOAT key increment
时间复杂度:O(1)
返回值:加/减完后的数值。
示例:
redis> SET mykey 10.50
"OK"
redis> INCRBYFLOAT mykey 0.1
"10.6"
redis> INCRBYFLOAT mykey -5
"5.6"
redis> SET mykey 5.0e3
"OK"
redis> INCRBYFLOAT mykey 2.0e2
"5200"
APPEND
如果key已经存在并且是一个string,命令会将value追加到原有的string的后边。如果key不存在,效果等于SET命令。
APPEND key value
时间复杂度:O(1),字符串长度较短为O(1)
返回值:追加完成后string的长度。
redis> EXISTS mykey
(integer) 0
redis> APPEND mykey "Hello"
(integer) 5
redis> GET mykey
"Hello"
redis> APPEND mykey " World"
(integer) 11
redis> GET mykey
"Hello World"
GETRANGE
返回key对应的string子串,由start和end确定(左闭又闭)。-1代表倒数第一个字符,-2代表倒数第二个。超过范围的偏移量会根据string的长度调整成正确的值。
GETRANGE key start end
时间复杂度O(N), N为区间长度
返回值:string类型的子串
redis> SET mykey "This is a string"
"OK"
redis> GETRANGE mykey 0 3
"This"
redis> GETRANGE mykey -3 -1
"ing"
redis> GETRANGE mykey 0 -1
"This is a string"
、
SETRANGE
覆盖字符串的一部分,从指定的偏移开始
SETRANGE key offset value
时间复杂度:O(N),N为value长度
返回值:替换后的string长度
redis> SET key1 "Hello World"
"OK"
redis> SETRANGE key1 6 "Redis"
(integer) 11
redis> GET key1
"Hello Redis"
STRLEN
获取指定key的string长度,当value不是string时,报错。
STRLEN key
时间复杂度:O(1)
返回值:string长度。当key不存在时,返回0.
redis> SET mykey "Hello world"
"OK"
redis> STRLEN mykey
(integer) 11
redis> STRLEN nonexisting
(integer) 0
2.4 典型使用场景
缓存功能、视频播放计数功能、共享会话、手机验证码
3. Hash 哈希
字符串和hash的区别。
3.1 基本命令
HSET
设置hash中指定的字段(field)的值(value)。
HSET key field value [field value …]
时间复杂度:O(1~N)
返回值:添加字段的个数
redis> HSET myhash field1 "Hello"
(integer) 1
redis> HGET myhash field1
"Hello"
HGET
获取hash中指定字段的值
HGET key field
O(1)
返回值:字段对应的值或者nil
redis> HSET myhash field1 "foo"
(integer) 1
redis> HGET myhash field1
"foo"
redis> HGET myhash field2
(nil)
HEXISTS
判断hash中是否有指定的字段
HEXISTS key field
O(1)
返回值:1表示存在,0表示不存在。
redis> HSET myhash field1 "foo"
(integer) 1
redis> HEXISTS myhash field1
(integer) 1
redis> HEXISTS myhash field2
(integer) 0
HDEL
删除hash中指定字段。
HDEL key filed [field …]
O(1~N)
返回值:本次操作删除的字段个数
redis> HSET myhash field1 "foo"
(integer) 1
redis> HDEL myhash field1
(integer) 1
redis> HDEL myhash field2
(integer) 0
HKEYS
获取hash中的所有字段。
HKEYS key
O(N)
返回值:字段列表
redis> HSET myhash field1 "Hello"
(integer) 1
redis> HSET myhash field2 "World"
(integer) 1
redis> HKEYS myhash
1) "field1"
2) "field2"
HVALS
获取hash中的所有值
HVALS key
时间复杂度:O(N)
返回值:所有的值
redis> HSET myhash field1 "Hello"
(integer) 1
redis> HSET myhash field2 "World"
(integer) 1
redis> HVALS myhash
1) "Hello"
2) "World"
HGETALL
获取hash中所有字段以及对应的值
HGETALL key
O(N),N为field的个数
返回值:字段和对应的值
redis> HSET myhash field1 "Hello"
(integer) 1
redis> HSET myhash field2 "World"
(integer) 1
redis> HGETALL myhash
1) "field1"
2) "Hello"
3) "field2"
4) "World"
HMGET
一次性获取hash中多个字段的值
HMGET key field [field]
O(1~N)
返回值:字段对应的值或者nil。
redis> HSET myhash field1 "Hello"
(integer) 1
redis> HSET myhash field2 "World"
(integer) 1
redis> HMGET myhash field1 field2 nofield
1) "Hello"
2) "World"
3) (nil)
HLEN
获取hash中的所有字段的个数
HLEN key
O(1)
返回值:字段个数
redis> HSET myhash field1 "Hello"
(integer) 1
redis> HSET myhash field2 "World"
(integer) 1
redis> HLEN myhash
(integer) 2
HSETNX
在字段不存在的情况下,设置hash中的字段和值。
HSETNX key field value
返回值:1表示成功,0表示失败。
redis> HSETNX myhash field "Hello"
(integer) 1
redis> HSETNX myhash field "World"
(integer) 0
redis> HGET myhash field
"Hello"
HINCRBY HINCRBYFLOAT
将hash中字段对应的数值添加指定的值
HINCRBY key field increment
返回值:该字段变化后的值。
redis> HSET myhash field 5
(integer) 1
redis> HINCRBY myhash field 1
(integer) 6
redis> HINCRBY myhash field -1
(integer) 5
redis> HINCRBY myhash field -10
(integer) -5浮点数版本
redis> HSET mykey field 10.50
(integer) 1
redis> HINCRBYFLOAT mykey field 0.1
"10.6"
redis> HINCRBYFLOAT mykey field -5
"5.6"
redis> HSET mykey field 5.0e3
(integer) 0
redis> HINCRBYFLOAT mykey field 2.0e2
"5200"
HSTRLEN
计算value的字符串长度
HSTRLEN key field
3.2 内部编码
- ziplist(压缩列表):当hash类型元素个数小于hash-max-zip-list配置(默认512)、同时所有的值都小于hash-max-ziplist-value配置(默认64字节)时,使用ziplist作为哈希内部实现。实现多个元素连续存储,节省内存。
- hashtable(哈希表):当哈希类型无法满足ziplist条件时,使用hashtable。此时ziplist读写效率会下降,但hashtable的读写时间复杂度为O(1)
3.3 使用场景
关系型数据表保存⽤⼾信息,表的结构比string类型只管,比json格式的也很方便,json适合整体。
List列表
列表类型时用来存储多个有序的字符串,如下图所示,abcde五个元素从左到右组成了一个有序的列表,列表中的每个字符串成为元素(element),一个列表最多可以存储2^32-1个元素。在Redis可以对列表两端push和pop,还可以获取指定范围的元素列表、获取指定索引下标的元素等。
列表两端插入删除操作:
列表获取、删除操作:
列表特点:
第一、列表中的元素时有序的,支持随机和返回获取。
第二、区分获取和删除的区别。
第三、列表中元素可以重复
命令
LPUSH、LPUSHX、RPUSH、RPUSHX
LPUSH将⼀个或者多个元素从左侧放⼊(头插)到 list 中。带X后缀时如果key存在则插入,否则直接返回0。
LPUSH key element [element …]
返回值:插入后list的长度
redis> LPUSH mylist "world"
(integer) 1
redis> LPUSH mylist "hello"
(integer) 2
redis> LRANGE mylist 0 -1
1) "hello"
2) "world"
LRANGE
获取从start到end区间的所有元素,左闭右闭
LRANGE key start stop
时间复杂度:O(N)
返回值:指定区间的元素
redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3
redis> LRANGE mylist 0 0
1) "one"
redis> LRANGE mylist -3 2
1) "one"
2) "two"
3) "three"
redis> LRANGE mylist -100 100
1) "one"
2) "two"
3) "three"
redis> LRANGE mylist 5 10
(empty array)
LPOP RPOP
头删和尾删
LPOP key
时间复杂度为O(1)
返回值:取出的元素或者nil
redis> RPUSH mylist "one" "two" "three" "four" "five"
(integer) 5
redis> RPOP mylist
"five"
redis> LRANGE mylist 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
LINDEX
获取左数第index位置的元素
LINDEX key index
时间复杂度:O(N)
返回值:取出的元素或者 nil。
LINSERT
在指定位置插入元素
LINSERT key <BEFORE|AFTER> pivot element
时间复杂度:O(N)
返回值:插入后list长度
redis> RPUSH mylist "Hello"
(integer) 1
redis> RPUSH mylist "World"
(integer) 2
redis> LINSERT mylist BEFORE "World" "There"
(integer) 3
redis> LRANGE mylist 0 -1
1) "Hello"
2) "There"
3) "World"
LLEN
获取list长度
LLEN key
时间复杂度:O(1)
返回值:list 的⻓度。
redis> LPUSH mylist "World"
(integer) 1
redis> LPUSH mylist "Hello"
(integer) 2
redis> LLEN mylist
(integer) 2
阻塞版命令 blpop brpop
- 在列表中右元素的情况下,lpop和blpop是一致的,立即返回结果。但是如果列表为空,非阻塞版本会理解返回nul,但阻塞版本会根据timeout阻塞一点时间,期间Redis可以执行其他命令,但要求执行该命令的客户端会表现为阻塞状态。
- 命令中如果设置了多个键,那么会从左向右遍历键。一旦有一个键对应的列表中可以弹出元素,命令立即返回。
- 如果多个客户端同时对一个键执行pop,则最先执行命令的客户端会得到弹出的元素。
BLPOP key [key …] timeout
时间复杂度:O(1)
返回值:取出的元素或者nil
redis> EXISTS list1 list2
(integer) 0
redis> RPUSH list1 a b c
(integer) 3
redis> BLPOP list1 list2 0
1) "list1"
2) "a"
4.2 内部编码
- ziplist:压缩列表同hash
- linkedlist(链表):当列表类型无法满足ziplist时,会使用列表。
4.3 使用场景
消息队列
5. Set集合
集合类型是保存多个字符串类型的元素的,但和列表类型不同的是,集合中的元素是不重、无序的。一个集合中可以存储2^32-1个元素。如图所示:
5.1 基本命令
SADD
将一个或者多个元素加到集合中。不能加重复的
SADD key member [member …]
O(1)
返回值:本次添加成功的元素个数。
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SADD myset "World"
(integer) 0
redis> SMEMBERS myset
1) "Hello"
2) "World"
SMEMBERS
获取一个set中的所有元素。
SMEMBERS key
O(N)
返回值:所有元素的列表
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SMEMBERS myset
1) "Hello"
2) "World"
SISMEMBER
判断一个元素在不在set中
SISMEMBER key member
O(1)
返回值:1 表⽰元素在 set 中。0 表⽰元素不在 set 中或者 key 不存在。
redis> SADD myset "one"
(integer) 1
redis> SISMEMBER myset "one"
(integer) 1
redis> SISMEMBER myset "two"
(integer) 0
SCARD
获取一个set的基数,即set中的元素个数。
SCARD key
O(1)
返回值:set内的元素个数
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SCARD myset
(integer) 2
SPOP
从set中删除并返回一个或多个元素。由于set内无序,所以取出哪个元素实际是未定义行为,既可以看作随机的。
SPOP key [count]
O(N)
返回值:取出的元素。
redis> SADD myset "one"
(integer) 1
redis> SADD myset "two"
(integer) 1
redis> SADD myset "three"
(integer) 1
redis> SPOP myset
"one"
redis> SMEMBERS myset
1) "three"
2) "two"
redis> SADD myset "four"
(integer) 1
redis> SADD myset "five"
(integer) 1
redis> SPOP myset 3
1) "three"
2) "four"
3) "two"
redis> SMEMBERS myset
1) "five"
SMOVE
将一个元素从源set取出并放入目标set中。
SMOVE source destination member
O(1)
返回值:1表示移动成功,0表示失败
redis> SADD myset "one"
(integer) 1
redis> SADD myset "two"
(integer) 1
redis> SADD myotherset "three"
(integer) 1
redis> SMOVE myset myotherset "two"
(integer) 1
redis> SMEMBERS myset
1) "one"
redis> SMEMBERS myotherset
1) "three"
2) "two"
SREM
将指定的元素从set中删除。
SREM key member [member …]
O(N)
返回值:本次操作删除的元素个数
redis> SADD myset "one"
(integer) 1
redis> SADD myset "two"
(integer) 1
redis> SADD myset "three"
(integer) 1
redis> SREM myset "one"
(integer) 1
redis> SREM myset "four"
(integer) 0
redis> SMEMBERS myset
1) "three"
2) "two"
交集(inter)、并集(union)、差集(diff)
取交集
SINTER key [key …]
复杂度O(N*M)
返回值:交集的元素
redis> SADD key1 "a"
(integer) 1
redis> SADD key1 "b"
(integer) 1
redis> SADD key1 "c"
(integer) 1
redis> SADD key2 "c"
(integer) 1
redis> SADD key2 "d"
(integer) 1
redis> SADD key2 "e"
(integer) 1
redis> SINTER key1 key2
1) "c"
获取给定set的交集中的元素并保存到目标set中。
SINTERSTORE destination key [key …]
O(N*M)
返回值:交集元素的个数
redis> SADD key1 "a"
(integer) 1
redis> SADD key1 "b"
(integer) 1
redis> SADD key1 "c"
(integer) 1
redis> SADD key2 "c"
(integer) 1
redis> SADD key2 "d"
(integer) 1
redis> SADD key2 "e"
(integer) 1
redis> SINTERSTORE key key1 key2
(integer) 1
redis> SMEMBERS key
1) "c"
取并集
SUNION key [key …]
复杂度O(N)
返回值:并集的元素
redis> SADD key1 "a"
(integer) 1
redis> SADD key1 "b"
(integer) 1
redis> SADD key1 "c"
(integer) 1
redis> SADD key2 "c"
(integer) 1
redis> SADD key2 "d"
(integer) 1
redis> SADD key2 "e"
(integer) 1
redis> SUNION key1 key2
1) "a"
2) "c"
3) "e"
4) "b"
5) "d"
将并集的元素存起来
SUNIONSTORE destination key [ key …]
O(N)
返回值:并集的元素个数
获取给定set的差集中的元素
SDIFF key [key …]
O(N)
返回值:差集的元素
redis> SADD key1 "a"
(integer) 1
redis> SADD key1 "b"
(integer) 1
redis> SADD key1 "c"
(integer) 1
redis> SADD key2 "c"
(integer) 1
redis> SADD key2 "d"
(integer) 1
redis> SADD key2 "e"
(integer) 1
redis> SDIFF key1 key2
1) "a"
2) "b"
将差集元素存起来
SDIFFSTORE destination key [key …]
O(N)
返回值:差集元素个数
5.2 内部编码
- intset(整数集合):当集合中的元素都是整数并且元素的个数小于set-max-intset-entries配置(默认512个)时,减少内存使用。
- hashtable(哈希表):当不满足intset时,便使用哈希表。
5.3使用场景
集合类型⽐较典型的使⽤场景是标签(tag)。例如 A ⽤⼾对娱乐、体育板块⽐较感兴趣,B ⽤⼾
对历史、新闻⽐较感兴趣,这些兴趣点可以被抽象为标签。有了这些数据就可以得到喜欢同⼀个标签
的⼈,以及⽤⼾的共同喜好的标签,这些数据对于增强⽤⼾体验和⽤⼾黏度都⾮常有帮助。 例如⼀个
电⼦商务⽹站会对不同标签的⽤⼾做不同的产品推荐。
6.Zset有序集合
有序集合相对于字符串、列表、哈希、集合来说会有⼀些陌⽣。它保留了集合不能有重复成员的
特点,但与集合不同的是,有序集合中的每个元素都有⼀个唯⼀的浮点类型的分数(score)与之关
联,着使得有序集合中的元素是可以维护有序性的,但这个有序不是⽤下标作为排序依据⽽是⽤这个
分数。如图 所示:
有序集合提供了获取指定分数和元素范围查找、计算成员排名等功能。
基本命令
ZADD
添加或者更新只当的元素以及关联的分数到zset中,分数应符合double类型,+inf/-inf作为正负极限也是合法的。
- XX:仅仅用于更新已经存在的元素,不会添加新元素。
- NX:仅用于添加新元素,不会更新已经存在的元素。
- CH:默认情况下,ZADD返回的是本次添加的元素个数,但指定这个选项之后,就会还包含本次更新的元素的个数。
- IINCR:此命令类似ZINCRBY效果,将元素的分数加上指定的分数。此时只能指定一个元素和分数。
ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member …]
O(log(N))
返回值:本次添加成功的元素个数
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 1 "uno"
(integer) 1
redis> ZADD myzset 2 "two" 3 "three"
(integer) 2
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "uno"
4) "1"
5) "two"
6) "2"
7) "three"
8) "3"
redis> ZADD myzset 10 one 20 two 30 three
(integer) 0
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "uno"
2) "1"
3) "one"
4) "10"
5) "two"
6) "20"
7) "three"
8) "30"
redis> ZADD myzset CH 100 one 200 two 300 three
(integer) 3
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "uno"
2) "1"
3) "one"
4) "100"
5) "two"
6) "200"
7) "three"
8) "300"
redis> ZADD myzset XX 1 one 2 two 3 three 4 four 5 five
(integer) 0
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "uno"
4) "1"
5) "two"
6) "2"
7) "three"
8) "3"
redis> ZADD myzset NX 100 one 200 two 300 three 400 four 500 five
(integer) 2
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "uno"
4) "1"
5) "two"
6) "2"
7) "three"
8) "3"
9) "four"
10) "400"
11) "five"
12) "500"
redis> ZADD myzset INCR 10 one
"11"
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "uno"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
7) "one"
8) "11"
9) "four"
10) "400"
11) "five"
12) "500"
redis> ZADD myzset -inf "negative infinity" +inf "positive infinity"
(integer) 2
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "negative infinity"
2) "-inf"
3) "uno"
4) "1"
5) "two"
6) "2"
7) "three"
8) "3"
9) "one"
10) "11"
11) "four"
12) "400"
13) "five"
14) "500"
15) "positive infinity"
16) "inf"
ZCARD
获取一个zset的基数, 即zset中元素的个数
ZCARD key
O(1)
返回值:zset内元素个数
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZCARD myzset
(integer) 2
ZCOUNT
返回分数在min和max之间的元素个数,默认情况下,min和max都是包含的,可以通过(排除。
ZCOUNT key min max
O(log(N))
返回值:满足条件的元素列表个数
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZCOUNT myzset -inf +inf
(integer) 3
redis> ZCOUNT myzset 1 3
(integer) 3
redis> ZCOUNT myzset (1 3
(integer) 2
redis> ZCOUNT myzset (1 (3
(integer) 1
ZRANGE
返回指定区间里的元素,分数按照升序。带上WITHSCORES可以把分数也返回。
ZRANGE key start stop [WITHSCORES]
[start, stop]为下标构成的区间,从0开始,支持负数。
O(log(N)+M)
返回值:区间内的元素列表
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"
5) "three"
6) "3"
redis> ZRANGE myzset 0 -1
1) "one"
2) "two"
3) "three"
redis> ZRANGE myzset 2 3
1) "three"
redis> ZRANGE myzset -2 -1
1) "two"
2) "three"
ZREVANGE
返回指定区间里的元素,分数按照降序排序。注:这个命令可能在 6.2.0 之后废弃,并且功能合并到 ZRANGE 中。
ZREVRANGE key start stop [WITHSCORES]
O(log(N)+M)
返回值:区间内的元素列表
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZREVRANGE myzset 0 -1 WITHSCORES
1) "three"
2) "3"
3) "two"
4) "2"
5) "one"
6) "1"
redis> ZREVRANGE myzset 0 -1
1) "three"
2) "two"
3) "one"
redis> ZREVRANGE myzset 2 3
1) "one"
redis> ZREVRANGE myzset -2 -1
1) "two"
2) "one"
ZRANGEBYSCORE
返回分数在min和max之间的元素,默认情况下min和max都是包含的,可以通过(排除。
备注:这个命令可能在 6.2.0 之后废弃,并且功能合并到 ZRANGE 中。
ZRANGEBYSCORE key min max [WITHSCORES]
O(log(N)+M)
返回值:区间内的元素列表
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZRANGEBYSCORE myzset -inf +inf
1) "one"
2) "two"
3) "three"
redis> ZRANGEBYSCORE myzset 1 2
1) "one"
2) "two"
redis> ZRANGEBYSCORE myzset (1 2
1) "two"
redis> ZRANGEBYSCORE myzset (1 (2
(empty array)
ZPOPMAX BZPOPMAX
删除并返回分数最高的count个元素。B版本是阻塞版本
ZPOPMAX key [count] [timeout]
timeout是阻塞版本的参数
时间复杂度:O(log(N) * M)
返回值:分数和元素列表。
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZPOPMAX myzset
1) "three"
2) "3"
ZPOPMIN BZPOPMIN
删除并返回分数最低的count个元素。
ZPOPMIN key [count] [timeout]
timeout是阻塞版本的参数
时间复杂度:O(log(N) * M)
返回值:分数和元素列表
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZPOPMIN myzset
1) "one"
2) "1"
ZRANK ZREVRANK
返回指定元素的排名,升序/降序
ZRANK key member
O(log(N))
返回值:排名
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZRANK myzset "three"
(integer) 2
redis> ZRANK myzset "four"
(nil)
ZSCORE
返回指定元素的分数
ZSCORE key member
O(1)
返回值:分数
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZSCORE myzset "one"
"1"
ZREM
删除指定元素
ZREM key member [member …]
O(M*log(N))
返回值:本次操作删除的元素个数
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZREM myzset "two"
(integer) 1
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "three"
4) "3"
ZREMRANGBYRANK
按照排序,升序删除指定范围的元素,左闭右闭
ZREMRANGEBYRANK key start stop
O(log(N)+M)
返回值:本次操作删除的元素个数
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZREMRANGEBYRANK myzset 0 1
(integer) 2
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "three"
2) "3"
ZREMRANGEBYSCORE
按照分数删除指定范围的元素,左闭右闭
ZREMRANGEBYSCORE key min max
O(log(N)+M)
返回值:本次操作删除的元素个数
redis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZADD myzset 3 "three"
(integer) 1
redis> ZREMRANGEBYSCORE myzset -inf (2
(integer) 1
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "two"
2) "2"
3) "three"
4) "3"
ZINCRBY
为指定的元素的关联分数添加指定的分数值
ZINCRBY key increment member
O(log(N))
返回值:添加后元素的分数
edis> ZADD myzset 1 "one"
(integer) 1
redis> ZADD myzset 2 "two"
(integer) 1
redis> ZINCRBY myzset 2 "one"
"3"
redis> ZRANGE myzset 0 -1 WITHSCORES
1) "two"
ZINTERSTORE
求给定有序集合中元素的交集并保存进目标有序集合中,在合并过程中以元素为单位进行合并,元素对应的分数按照不同的聚合方式和权重得到新的分数
ZINTERSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE <SUM | MIN |MAX>]
时间复杂度O(NK)+O(Mlog(M))
返回值:目标集合中元素个数
redis> ZADD zset1 1 "one"
(integer) 1
redis> ZADD zset1 2 "two"
(integer) 1
redis> ZADD zset2 1 "one"
(integer) 1
redis> ZADD zset2 2 "two"
(integer) 1
redis> ZADD zset2 3 "three"
(integer) 1
redis> ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3
(integer) 2
redis> ZRANGE out 0 -1 WITHSCORES
1) "one"
2) "5"
3) "two"
4) "10"
ZUNIONSTORE
求出给定有序集合中元素的并集并保存进目标有序集合中,在合并过程中以元素为单位进行合并,元素对应的分数按照不同的聚合方式和权重得到新的分数
ZUNIONSTORE destination numkeys key [key …] [WEIGHTS weight [weight …]] [AGGREGATE <SUM | MIN | MAX>]
O(N)+O(M*log(M))
返回值:目标集合中元素个数
redis> ZADD zset1 1 "one"
(integer) 1
redis> ZADD zset1 2 "two"
(integer) 1
redis> ZADD zset2 1 "one"
(integer) 1
redis> ZADD zset2 2 "two"
(integer) 1
redis> ZADD zset2 3 "three"
(integer) 1
redis> ZUNIONSTORE out 2 zset1 zset2 WEIGHTS 2 3
(integer) 3
redis> ZRANGE out 0 -1 WITHSCORES
1) "one"
2) "5"
3) "three"
4) "9"
5) "two"
6) "10"
6.2内部编码
- ziplist(压缩列表):当有序集合的元素个数⼩于 zset-max-ziplist-entries 配置(默认 128 个),
同时每个元素的值都⼩于 zset-max-ziplist-value 配置(默认 64 字节)时,Redis 会⽤ ziplist 来作
为有序集合的内部实现,ziplist 可以有效减少内存的使⽤。 - skiplist(跳表):当 ziplist 条件不满⾜时,有序集合会使⽤ skiplist 作为内部实现,因为此时
ziplist 的操作效率会下降。
6.3 使用场景
有序集合⽐较典型的使⽤场景就是排⾏榜系统。例如常⻅的⽹站上的热榜信息,榜单的维度可能
是多⽅⾯的:按照时间、按照阅读量、按照点赞量。本例中我们使⽤点赞数这个维度,维护每天的热
榜
7.SCAN 渐进式遍历
scan命令进行渐进式遍历键,解决了keys获取键时可能出现的阻塞问题。每次scan命令的时间复杂度是O(1),但要完整地完成所有键的遍历,需要执行多次SCAN。
- 首次从scan 0开始
- 当scan返回的位置为0时,遍历结束。
以渐进的方式进行键的遍历
SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
O(1)
返回值:下次scan的游标(cursor)以及本次得到的键。
redis 127.0.0.1:6379> scan 0
1) "17"
2) 1) "key:12"
2) "key:8"
3) "key:4"
4) "key:14"
5) "key:16"
6) "key:17"
7) "key:15"
8) "key:10"
9) "key:3"
10) "key:7"
11) "key:1"
redis 127.0.0.1:6379> scan 17
1) "0"
2) 1) "key:5"
2) "key:18"
3) "key:0"
4) "key:2"
5) "key:19"
6) "key:13"
7) "key:6"
8) "key:9"
9) "key:11"