前言
Reids安装请看:Linux环境下安装Redis
这里说的数据类型是value的数据类型,key的类型都是字符串。
5种数据类型:
Redis 常用数据类型操作命令: Redis命令中心
Redis键(key)的相关命令:
- keys * : 查看当前库所有的key
- exists key : 判断某个key是否存在
- type key : 查看key的类型
- del key: 删除指定的key数据
- unlink key : 根据value删除非阻塞删除,仅仅将keys从keyspace元数据中删除,真正的删除会在后续异步中操作
- expire key 10: 设置key的有效时间为10秒
- ttl key:查看指定的key还有多少秒过期,-1:表示永不过期,-2:表示已过期
- select dbindex:切换数据库【0-15】,默认为0
- dbsize:查看当前数据库key的数量
- flushdb:清空当前库
- flushall:清空全部库
1. 字符串String
String是Redis最基本的类型,可以理解为和Memcached一样的类型,一个key 对应一个value。
String类型是二进制,意味着可以包含任何数据,比如jpg图片或者序列化对象。一个Redis字符串value最多可以是512M
1.1 常用命令
set: 添加键值对
1
127.0.0.1:6379> set key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]
- NX:当数据库中key不存在时,可以将key-value添加到数据库
- XX:当数据库中key存在时,可以将key-value添加数据库,与NX参数互斥
- EX:key的超时秒数
- PX:key的超时毫秒数,与EX互斥
- value中若包含空格、特殊字符,需用双引号包裹
1
2127.0.0.1:6379> set xiaoyuge 180 NX
OKget: 获取值
1
get <key>
示例:
1
2127.0.0.1:6379> get xiaoyuge
"180"append: 追加值
1
append <key> <value>
将给定的value追加到原值的末尾。
示例:
1
2
3
4
5
6
7
8127.0.0.1:6379> set xiaoyuge 180
OK
127.0.0.1:6379> get xiaoyuge
"180"
127.0.0.1:6379> append xiaoyuge cm
(integer) 5
127.0.0.1:6379> get xiaoyuge
"180cm"strlen: 获取值的长度
1
strlen <key>
示例:
1
2127.0.0.1:6379> strlen xiaoyuge
(integer) 8setnx: key不存在时,设置key的值
1
setnx <key> <value>
示例:
1
2
3
4
5127.0.0.1:6379> setnx ygb cool ## ygb不存在,返回1,表示设置成功
(integer) 1
127.0.0.1:6379> setnx ygb cool ## 再次通过setnx设置ygb,由于已经存在了,所以设置失败,返回0
(integer) 0
127.0.0.1:6379>incr: 原子递增1
1
incr <key>
将key中存储的值增加1, 只能对数值操作,如果key不存在,则会新建一个,值为1
示例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> flushdb #清空db,方便测试
OK
127.0.0.1:6379> set age 18 #age值为18
OK
127.0.0.1:6379> incr age #age增加1,返回19
(integer) 19
127.0.0.1:6379> get age #获取age的值
"19"
127.0.0.1:6379> incr salary #salary不存在,自动创建一个,值为1
(integer) 1
127.0.0.1:6379> get salary #获取salary的值decr: 原子递减1
1
decr <key>
将key中存储的值减1,只能对数值操作,如果为空,新增值为-1
示例:
1
2
3
4
5
6
7
8
9
10127.0.0.1:6379> set age 18
OK
127.0.0.1:6379> get age
"18"
127.0.0.1:6379> decr age
(integer) 17
127.0.0.1:6379> keys age1
(empty array)
127.0.0.1:6379> decr age1
(integer) -1incrby/decrby: 递增或递减指定的数字
1
2incrby <key> <步长>
decrby <key> <步长>将key中存储的数字值递增指定的步长,若key不存在,则相当于在原值为0的值上递增指定的步长。
示例:
1
2
3
4
5
6127.0.0.1:6379> incrby age 18
(integer) 18
127.0.0.1:6379> decrby age 2
(integer) 16
127.0.0.1:6379> get age
"16"mset: 同时设置多个key-value
1
2
3
4mset <key1> <value1> <key2> <value2> ...
设置name = xiaoyuge, age = 18
127.0.0.1:6379> mset name xiaoyuge age 18mget: 获取多个key对应的值
1
2
3
4
5
6mget <key1> <key2> ....
示例
127.0.0.1:6379> mget name age
1) "xiaoyuge"
2) "18"msetnx: 当多个key都不存在时,则设置成功
1
msetnx <key1> <value1> <key2> <value2> ...
原子性,要么都成功,或者都失败
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14127.0.0.1:6379> flushdb #清空
OK
127.0.0.1:6379> set k1 v1 #先设置k1
OK
127.0.0.1:6379> msetnx k1 v1 k2 v2 #当k1和k2都不存在,同时设置k1,k2,由于k1已经存在,所以操作失败
(integer) 0
127.0.0.1:6379> mget k1 k2 # 获取k1、k2, k2不存在
1) "v1"
2) (nil)
127.0.0.1:6379> msetnx k2 v2 k3 v3 #当k2和k3都不存在,同时设置k2,k3,设置成功
(integer) 1
127.0.0.1:6379> mget k2 k3 # 获取k2、k3
1) "v2"
2) "v3"getrange: 获取值的范围,类似于Java的substring
1
getrange key <start> <end>
获取[start, end]之间的字符,返回为字符串
示例:
1
2
3
4127.0.0.1:6379> set k1 xiaoyuge
OK
127.0.0.1:6379> getrange k1 0 4
"xiaoy"setrange: 覆盖自定位置的值
1
setrange <key> <start> <value>
从 start 位置开始覆盖,覆盖的长度为value的长度, 总长度不变
示例:
1
2
3
4
5
6
7
8
9
10
11
12127.0.0.1:6379> get k1
"xiaoyuge"
127.0.0.1:6379> setrange k1 0 nb
(integer) 8
127.0.0.1:6379> get k1
"nbaoyuge"
127.0.0.1:6379> get k1
"nbaoyuge"
127.0.0.1:6379> setrange k1 0 xiao
(integer) 8
127.0.0.1:6379> get k1
"xiaoyuge"setex: 设置键值&过期时间(秒)
1
setex <key> <过期时间s> <value>
示例:
1
2
3
4
5
6127.0.0.1:6379> setex k1 120 v1 #设置k1的值为v1,有效期120秒
OK
127.0.0.1:6379> get k1 #获取k1的值
"v1"
127.0.0.1:6379> ttl k1 #获取k1还有多少秒失效
(integer) 113getset: 以新换旧,设置新值同时返回旧值
1
getset <key> <value>
示例:
1
2
3
4
5
6
7
8
9
10127.0.0.1:6379> set name xiaoyuge #设置name为xiaoyuge
OK
127.0.0.1:6379> getset name xiaoyuge666 #设置name为xiaoyuge666,返回name的旧值
"xiaoyuge"
127.0.0.1:6379> getset age 18 #设置age为18,age未设置过,返回age的旧值为null
(nil)
127.0.0.1:6379> get name #获取现在的name,返回xiaoyuge666
"xiaoyuge666"
127.0.0.1:6379> get age #获取age
"18"
1.2 数据结构
String的数据结构为简单动态字符串(Simple Dynamic String,简写SDS)。是可以修改的字符串,内部结构类似于Java中的ArrayList,采用分配冗余空间的方式来减少内存的频繁分配。
如图所示,内部为当前字符串实际分配的空间capacity,一般要高于实际字符串长度len。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次会多扩容1M的空间
要注意的是字符串最大长度为512M。
2. 列表List
列表List是简单的字符串列表,按照插入顺序排序,添加元素时可以插入列表的头部或者尾部。
它的底层实现实际上使用双向链表实现的,对两端的操作性能很高,通过索引下标操作中间节点性能会较差。
2.1 常用命令
lupsh/rpush: 从左边或者右边插入一个或多个值
1
2lpush <key1> <value1> <value2> <value3> ...
rpush <key1> <value1> <value2> <value3> ...示例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> rpush k v1 v2 v3 #列表k的右边插入3个元素
(integer) 3
127.0.0.1:6379> lpush k v4 v5 v6 #列表k的左边插入3个元素
(integer) 6
127.0.0.1:6379> lrange k 0 6 #输出[0,6]范围内的元素
1) "v6"
2) "v5"
3) "v4"
4) "v1"
5) "v2"
6) "v3"lrange: 从列表左边获取指定范围内的值
1
lrange <key> <start> <end>
返回列表key中指定的区间的元素,区间偏移量start ,end指定。
下标index参数start和end都从0开始,也可以使用负数下标,以 -1表示列表最后一个元素,-2表示倒数第二个元素…..
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14127.0.0.1:6379> lpush n v1 v2 v3 v4 v5 v6
(integer) 6
127.0.0.1:6379> lrange n 0 -1 #取出n集合中所有元素 start 0表示从第一个开始, end -1表示最后一个
1) "v6"
2) "v5"
3) "v4"
4) "v3"
5) "v2"
6) "v1"
127.0.0.1:6379> lrange n -3 -1 #获取倒数第三至倒数一个元素 start 一定要小于end
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379>lpop/rpop: 从左边或者右边弹出多个元素
1
lpop/rpop <key> <count>
count: 可以省略,默认为1
lpop/rpop操作之后,弹出的值会从列表中删除,当所有的值都删除后,键就删除
示例:
1
2
3
4
5
6
7
8
9127.0.0.1:6379> rpush k v1 v2 v3 #集合k 右边添加3个元素
(integer) 3
127.0.0.1:6379> lpop k #左边弹出1个元素
"v1"
127.0.0.1:6379> rpop k 2 # 右边弹出2个元素
"v3"
"v2"
127.0.0.1:6379> exists k # 查询key是否存在
(integer) 0rpoplpush: 从一个列表右边弹出一个元素放到另外一个列表中
1
rpoplpush <source> <destination>
从source的右边弹出一个元素放到destination列表的左边
示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22127.0.0.1:6379> rpush k 1 2 3 #列表k的右边添加3个元素[1,2,3]
(integer) 3
127.0.0.1:6379> lrange k 0 -1 #从左到右输出k列表中的元素
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> rpush k1 4 5 6 #列表k1的右边添加3个元素[4,5,6]
(integer) 3
127.0.0.1:6379> lrange k1 0 -1 #从左到右输出k1列表中的元素
1) "4"
2) "5"
3) "6"
127.0.0.1:6379> rpoplpush k k1 #从k的右边弹出一个元素放到k1的左边
"3"
127.0.0.1:6379> lrange k 0 -1 #k中剩下2个元素了
1) "1"
2) "2"
127.0.0.1:6379> lrange k1 0 -1 #k1变成来4个元素
1) "3"
2) "4"
3) "5"
4) "6"lindex: 获取指定索引位置的元素(从左到右)
1
lindex <key> <index>
返回列表key中下标为index的元素。
下标从0开始,也可以是负数,-1 表示列表最后一个元素,-2表示列表倒数第二个元素…..
如果key不是列表类型,返回一个错误
如果index超出了列表的长度范围,返回 nil
示例:
1
2
3
4
5
6
7
8
9
10
11127.0.0.1:6379> lrange k1 0 -1
1) "3"
2) "4"
3) "5"
4) "6"
127.0.0.1:6379> lindex k1 2 #返回索引位置2的元素
"5"
127.0.0.1:6379> lindex k1 6 #返回索引位置6的元素,超出了列表长度
(nil)
127.0.0.1:6379> lindex k1 -1 #返回最后一个元素
"6"llen: 获取列表长度
1
llen <key>
返回列表长度,如果key不存在,则被解释为一个空列表,返回0;
如果key不是列表类型,返回一个错误
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15127.0.0.1:6379> lrange k1 0 -1
1) "3"
2) "4"
3) "5"
4) "6"
127.0.0.1:6379> llen k1 #返回k1集合的长度
(integer) 4
127.0.0.1:6379> set name xiaoyuge #设置字符串
OK
127.0.0.1:6379> type name #查看name的类型
string
127.0.0.1:6379> llen name #获取name的长度,因为name为String类型,所以报错
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> strlen name #字符串的长度使用strlen
(integer) 8linsert: 在某个值的前或者后插入一个值
1
linsert <key> before|after <value> <newvalue>
将值newvalue插入到列表key中,位于value值之前或者之后
当value不存在列表key中,不执行任何操作,返回 -1
当key不存在时,key被视为空列表,不执行任何操作, 返回 0
如果命令执行成功,返回插入操作完成之后,列表的长度
如果key不是列表类型,返回一个错误
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17127.0.0.1:6379> rpush k 1 2 3 #列表k中添加3个元素
(integer) 3
127.0.0.1:6379> lrange k 0 -1 #输出k全部元素
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> linsert k before 1 0 #在1前面添加0,添加成功,返回列表长度
(integer) 4
127.0.0.1:6379> lrange k 0 -1 #输出k全部元素
1) "0"
2) "1"
3) "2"
4) "3"
127.0.0.1:6379> linsert k before 4 5 #在4前面添加5,由于元素4不存在,插入失败返回-1
(integer) -1
127.0.0.1:6379> linsert k1 before 4 5 #在列表k1中元素4前面插入5,由于列表k1不存在,返回0
(integer) 0lrem: 删除指定数量的某个相同的元素
1
lrem <key> <count> <value>
根据count的值,移除列表中与参数value相等的count个元素
count的值可以是以下几种
count > 0: 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count
count < 0: 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。
count = 0: 移除列表总所有与value相等的值
因为不存在的 key 被视作空表(empty list),所以当 key 不存在时,总是返回 0 。
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18127.0.0.1:6379> flushdb #清空db,方便测试
OK
127.0.0.1:6379> rpush k1 v1 v2 v3 v2 v2 v1 #k1列表中插入6个元素
(integer) 6
127.0.0.1:6379> lrange k1 0 -1 #输出k1集合中所有元素
1) "v1"
2) "v2"
3) "v3"
4) "v2"
5) "v2"
6) "v1"
127.0.0.1:6379> lrem k1 2 v2 #k1集合中从左边删除2个v2
(integer) 2
127.0.0.1:6379> lrange k1 0 -1 #输出列表,列表中还有1个v2,前面2个v2干掉了
1) "v1"
2) "v3"
3) "v2"
4) "v1"lset: 替换指定位置的值
1
lset <key> <index> <value>
将列表key下标为index的元素替换为value, 当index参数超出范围,或者对一个空列表进行操作时,返回一个错误
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18127.0.0.1:6379> flushdb #清空db,方便测试
OK
127.0.0.1:6379> rpush k v1 v2 v3 #k集合中放入3个元素
(integer) 3
127.0.0.1:6379> lrange k 0 -1 #输出k集合元素
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> lset k 1 vv #将k集合中第2个元素替换为vv
OK
127.0.0.1:6379> lrange k 0 -1
1) "v1"
2) "vv"
3) "v3"
127.0.0.1:6379> lset k 10 vv #将k集合中第11个元素替换为vv,由于集合长度小于10,报错
(error) ERR index out of range
127.0.0.1:6379> lset k1 1 vv #k1不存在,报错
(error) ERR no such key
2.2 数据结构
List的数据结构为快速链表quickList
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也就是压缩列表。 它将所有的元素紧挨着一起存储,分配的是一块连续的内存。
当就比较多的时候才会改成quickList。
因为普通的链表需要的附加指针空间太大,会比较浪费空间,比如这个列表里存储的只是int类型的书,结构上还需要2个额外的指针prev和next。
redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用,这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。
3. 集合Set
Redis set对外提供的功能与list类似,是一个列表的功能,特殊之处在于set可以自动去重
set时String类型的无序集合,它的底层实际上时一个value为null的hash表,添加、删除、查找复杂度都是O(1)
一个算法,如果时间复杂度是O(1),那么随着数据的增加,查找数据的时间不变,也就是不管数据多少,查找时间都是一样的。
3.1 常用命令
sadd: 添加一个或者多个元素
1
2
3
4
5
6sadd <key> <value1> <value2> ...
示例:
127.0.0.1:6379> sadd s1 v1 v2 v3
(integer) 3
127.0.0.1:6379>smembers取出所有的元素
1
2
3
4
5
6
7smembers <key>
示例:
127.0.0.1:6379> smembers s1 #输出结果为无序
1) "v3"
2) "v1"
3) "v2"sismember: 判断集合中是否存在某个值
1
2
3
4sismember <key> <value>
判断集合key是否包含元素value, 1:有, 0:没有
sismember: set is member(是否是set中的成员)scard: 返回集合中元素的个数
1
scard <key>
返回集合key中元素个数,当key不存在返回0
srem: 删除多个元素
1
srem <key> <member> [member ...]
移除集合key中的一个或多个member元素,不存在的元素会被忽略,当key不是集合类型,返回一个错误
返回被成功移除的元素数量,不包括被忽略的元素
spop: 随机弹出多个值
1
spop <key> <count>
随机从key集合中弹出count个元素,count默认为1,返回被移除的元素
当count大于元素集合个数的时候,弹出全部
当key不存在或者空集时,返回nil
srandmember: 随机获取多个元素,不会从集合中删除
1
srandmember <key> <count>
从key指定的集合中随机返回count个元素,count可以不指定,默认值是1。
srandmember 和 spop的区别: 都可以随机获取多个元素,srandmember 不会删除元素,而spop会删除元素。
返回值: 1. 只提供 key 参数时,返回一个元素;如果集合为空,返回 nil 。 2. 如果提供了count参数,那么返回一个数组;如果集合为空,返回空数组。
smove: 将某个元素从一个集合移到另一个集合
1
smove <source> <destination> <member>
将member元素从source集合移动到destination集合。
smove是原子性操作,如果source集合不存在或者不保护指定的member元素,则smove命令不执行任何操作,仅返回0。
否则,member元素从source集合中移除,并添加到destination集合中去(destination集合不存在的话,会自动添加一个)当destination已经包含member元素,smove只是删除source中的member元素
如果member被成功删除,返回1;如果member不是source集合成员,并且没有任何对destination的操作,那么返回0
*sinter 取多个集合的交集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16sinter key [key ...]
示例
127.0.0.1:6379> smembers s #查询s集合的所有元素
1) "v3"
2) "v4"
3) "v2"
127.0.0.1:6379> sadd s2 v1 v2 v3 #集合s2添加三个元素
(integer) 3
127.0.0.1:6379> smembers s2 #查询s2集合的所有元素
1) "v3"
2) "v1"
3) "v2"
127.0.0.1:6379> sinter s s2 #获取集合s s2的交集
1) "v3"
2) "v2"sinterstore: 将多个集合的交集放到一个新的集合中
1
sinterstore destination key [key ...]
这个命令类似于sinter命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。 返回结果集中的成员数量。
sunion: 取多个集合的并集,自动去重
1
2
3
4
5
6
7sunion key [key ...]
示例:
127.0.0.1:6379> sunion s s2
1) "v1"
2) "v3"
3) "v2"
4) "v4"sunionstore: 将多个集合的并集放到一个新的集合中
1
sinterstore destination key [key ...]
这个命令类似于 sunion 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。 返回值:结果集中的成员数量。
sdiff: 取多个集合的差集
1
sdiff key [key ...]
返回一个集合的全部成员,该集合是所有给定集合之间的差集。 不存在的 key 被视为空集。
sdiffstore: 将多个集合的差集放到一个新的集合中
1
sdiffstore destination key [key ...]
这个命令类似于 sdiff 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集。
3.2 数据结构
set数据机构是字典,字典是用hash表实现的。
Java中的hashSet的内部实现使用HashMap,只不过所有的value都指向同一个对象。
Redis的set结构也是一样的,它的内部也使用hash结构,所有的value都指向同一个内部值。
4. 哈希表 Hash
Redis hash是一个键值对集合。
Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。 类似于java里面的Map<String,Object>
4.1 常用命令
hset: 设置多个field值
1
2
3
4hset key field value [field value ...]
127.0.0.1:6379> hset set1 name xiaoyuge age 18
(integer) 2将哈希表 key 中的域 field 的值设为 value 。 如果 key 不存在,一个新的哈希表被创建并进行 hset 操作。 如果域 field 已经存在于哈希表中,旧值将被覆盖。
返回值: 如果 field 是哈希表中的一个新建域,并且值设置成功,返回 1 。 如果哈希表中域 field 已经存在且旧值已被新值覆盖,返回 0 。
hget: 获取指定field的值
1
2
3
4
5
6hget <key> <field>
127.0.0.1:6379> hget set1 name
"xiaoyuge"
127.0.0.1:6379> hget set1 age
"18"hgetall: 返回hash表所有的fileld和value
1
2
3
4
5
6
7hgetall <key>
127.0.0.1:6379> hgetall set1
1) "name"
2) "xiaoyuge"
3) "age"
4) "18"hexists: 判断给定的field是否存在,1:存在,0:不存在
1
hexists key field
查看哈希表 key 中,给定域 field 是否存在。 返回值: 如果哈希表含有给定域,返回 1 。 如果哈希表不含有给定域,或 key 不存在,返回 0 。
- hkeys: 列出所有的filed
1
hkeys key
- hvals: 列出所有的value
1
hvals key
- hlen: 返回field的数量
1
hlen key
- hincrby: filed的值加上指定的增量
1
hincrby key field increment
为哈希表 key 中的域 field 的值加上增量 increment 。 增量也可以为负数,相当于对给定域进行减法操作。 如果 key 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。 如果域 field 不存在,那么在执行命令前,域的值被初始化为 0 。 对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。
返回值: 执行 hincrby 命令之后,哈希表 key 中域 field 的值。
1
2
3
4
5127.0.0.1:6379> hincrby set1 age 3
(integer) 21
127.0.0.1:6379> hvals set1
1) "xiaoyuge"
2) "21" - hsetnx: 当filed不存在的时候,设置filed的值
1
hsetnx key field value
将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。 若域 field 已经存在,该操作无效。 如果 key 不存在,一个新哈希表被创建并执行 hsetnx 命令。
返回值: 设置成功,返回 1 。 如果给定域已经存在且没有操作被执行,返回 0
4.2 数据结构
Hash类型对应的数据结构是2种:ziplist(压缩列表),hashtable(哈希表)。
当field-value长度较短个数较少时,使用ziplist,否则使用hashtable。
5. 有序集合Zset
有序集合zset和普通集合set非常相似,是一个没有重复元素的字符串集合,不同之处是有序集合的每一个成员都关联一个评分(score),
这个评分被用来按照从最低分到最高分的方式排序集合中的成员。
成员是唯一的,但是评分可以重复。因为元素是有序的,所以可以很快的根据评分score或者次序position来获取一个范围的元素,访问有序集合中的中间元素也是非常快的。
5.1 常用命令
- zadd: 添加元素
1
zadd <key> <score1> <member1> <score2> <member2> ...
将一个或多个member元素及其score值加入到有序集 key 当中。 如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入这个 member 元素,来保证该 member 在正确的位置上。 score 值可以是整数值或双精度浮点数。 如果 key 不存在,则创建一个空的有序集并执行 zadd 操作。
当 key 存在但不是有序集类型时,返回一个错误。 被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。
zrange: score生序,获取指定索引范围的元素
1
zrange key start top [withscores]
返回存储在有序集合key中的指定范围的元素。 返回的元素可以认为是按score从最低到最高排列,如果得分相同,将按字典排序。
下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。 你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。
zrange key 0 -1:可以获取所有元素
withscores:让成员和它的 score 值一并返回,返回列表以 value1,score1, …, valueN,scoreN 的格式表示
时间复杂度:O(log(N)+M), N 为有序集的基数,而 M 为结果集的基数
zrevrange: score降序,获取指定索引范围的元素
1
zrevrange key start stop [WITHSCORES]
返回存储在有序集合key中的指定范围的元素。 返回的元素可以认为是按score最高到最低排列, 如果得分相同,将按字典排序。
下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。 你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。
withscores:让成员和它的 score 值一并返回,返回列表以 value1,score1, …, valueN,scoreN 的格式表示
- zrangebyscore:按照score升序,返回指定score范围内的数据
1
zrangebyscore key min max [WITHSCORES] [LIMIT offset count]
返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
具有相同 score 值的成员按字典序来排列(该属性是有序集提供的,不需要额外的计算)。
可选的 LIMIT 参数指定返回结果的数量及区间(就像SQL中的 SELECT LIMIT offset, count ),注意当 offset 很大时,定位 offset 的操作可能需要遍历整个有序集,此过程最坏复杂度为 O(N) 时间。
zrevrangebyscore:按照score降序,返回指定score范围内的数据
1
zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]
返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。
具有相同 score 值的成员按字典序的逆序排列。
除了成员按 score 值递减的次序排列这一点外, zrevrangebyscore 命令的其他方面和 zrangebyscore 命令一样。
zincrby:为指定元素的score加上指定的增量
1
zincrby key increment member
可以通过传递一个负数值 increment ,让 score 减去相应的值,比如 ZINCRBY key -5 member ,就是让 member 的 score 值减去 5 。
当 key 不存在,或 member 不是 key 的成员时, ZINCRBY key increment member 等同于 ZADD key increment member
zrem:删除集合中多个元素
1
zrem key member [member ...]
移除有序集 key 中的一个或多个成员,不存在的成员将被忽略。 当 key 存在但不是有序集类型时,返回一个错误。
- zremrangebyrank 根据索引范围删除元素
1
zremrangebyrank key start stop
移除有序集 key 中,指定排名(rank)区间内的所有成员。 区间分别以下标参数 start 和 stop 指出,包含 start 和 stop 在内。 下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。 你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。
- zremrangebyscore:根据score的范围删除元素
1
zremrangebyscore key min max
移除有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员
- zcount:统计指定score范围内的元素个数
1
zcount key min max
返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量
- zrank:按照score生序,返回某个元素在集合中的排名
1
zrank key member
返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递增(从小到大)顺序排列。 排名以 0 为底,也就是说, score 值最小的成员排名为 0 。
- zrevrank:按照score将许,返回某个元素在集合中的排名
1
zrevrank key member
返回有序集 key 中成员 member 的排名。其中有序集成员按 score 值递减(从大到小)排序。排名以 0 为底,也就是说, score 值最大的成员排名为 0
- zscore:返回集合中指定元素的score
1
zscore key member
返回有序集 key 中,成员 member 的 score 值。 如果 member 元素不是有序集 key 的成员,或 key 不存在,返回 nil
5.2 数据结构
SortedSet(zset)是redis提供的一个非常特别的数据结构,内部使用到了2种数据结构。
1. hash表
类似于java中的Map<String,score>,key为集合中的元素,value为元素对应的score,可以用来快速定位元素定义的score,时间复杂度为O(1)
2. 跳表
跳表(skiplist)是一个非常有限的数据结构,实现简单,插入、删除、查找的复杂度均为O(logN)
类似于Java中的ConcurrentSkipListSet
,根据score的值排序后生成一个跳表,可以快速按照位置的顺序或者score的顺序查找元素。
来看一下跳表的原理:
首先从考虑一个有序列表开始:
从该有序表中搜索元素 < 23, 43, 59 > ,需要比较的次数分别为 < 2, 4, 6 >,总共比较的次数为 2 + 4 + 6 = 12 次。有没有优化的算法吗? 链表是有序的,但不能使用二分查找。类似二叉搜索树,我们把一些节点提取出来,作为索引。得到如下结构:
这里我们把 < 14, 34, 50, 72 > 提取出来作为一级索引,这样搜索的时候就可以减少比较次数了。我们还可以再从一级索引提取一些元素出来,作为二级索引,变成如下结构:
如果元素足够多,这种索引结构就能体现出优势来了。