# 二、Redis数据类型
Redis是一个key-value的数据库,key一般是String类型,不过value的类型多种多样。
这里先列出五中数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(集合)、Zset(有序集合)
需要注意的是:
- 每种数据结构都有自己底层的内部编码实现,而且是多种实现,这样Redis会在合适的场景选择合 适的内部编码。
- 每种数据结构都有两种以上的内部编码实现,例如string数据结构就包含了raw、int和 embstr三种内部编码。
- 有些内部编码可以作为多种外部数据结构的内部实现,例如ziplist就是hash、list和zset共有的内部编码
# 1、Redis 键(key)
Redis 键命令用于管理 redis 的键。
例如:我们删除key,前提是key存在。
127.0.0.1:6379> set name redis
OK
127.0.0.1:6379> del name
(integer) 1
2
3
4
5
DEL 是一个命令, runoobkey 是一个键。 如果键被删除成功,命令执行后输出 (integer) 1,否则将输出 (integer) 0
接下来我们来学习key的有关命令。
通过help [command] 可以查看一个命令的具体用法:
127.0.0.1:6379> help keys KEYS pattern summary: Find all keys matching the given pattern since: 1.0.0 group: generic
1
2
3
4
5
6
# 1.1、KEYS pattern
查看所有符合给定模式的key
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set name redis
OK
127.0.0.1:6379> keys *
1) "name"
2
3
4
5
6
7
8
# 1.2、EXISTS key
检查给定 key 是否存在。
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists age
(integer) 0
2
3
4
5
# 1.3、DEL key
该命令用于在 key 存在时删除 key。
127.0.0.1:6379> DEL name
(integer) 1
127.0.0.1:6379> DEL age
(integer) 0
2
3
4
5
# 1.4、MOVE key db
将当前数据库的 key 移动到给定的数据库 db 当中。
127.0.0.1:6379> move name 1
(integer) 1
127.0.0.1:6379> keys *
(empty list or set)
//切换到数据库1中,查询
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> keys *
1) "name"
2
3
4
5
6
7
8
9
10
11
12
# 1.5、EXPIRE key seconds
为给定 key 设置过期时间,以秒计。
127.0.0.1:6379> expire name 3
(integer) 1
//等3秒查询
127.0.0.1:6379> keys *
(empty list or set)
2
3
4
5
6
# 1.6、RENAME key newkey
修改key的名称
127.0.0.1:6379> rename name name1
OK
127.0.0.1:6379> keys *
1) "name1"
2
3
4
5
# 1.7、TYPE key
返回 key 所储存的值的类型。
127.0.0.1:6379> type name
string
2
# 1.8、PERSIST key
移除 key 的过期时间,key 将持久保持。
127.0.0.1:6379> set age 12
OK
127.0.0.1:6379> expire age 60
(integer) 1
127.0.0.1:6379> persist age
(integer) 1
127.0.0.1:6379> ttl age
(integer) -1
2
3
4
5
6
7
8
9
10
11
# 1.9、TTL key
查看还有多少秒过期,-1 表示永不过期,-2 表示已过期。
以下是设置age为10秒过期,中间使用ttl查看还有多久过期,最后过期就会返回-2
127.0.0.1:6379> expire age 10
(integer) 1
127.0.0.1:6379> ttl age
(integer) 5
127.0.0.1:6379> ttl age
(integer) 1
127.0.0.1:6379> ttl age
(integer) -2
2
3
4
5
6
7
8
9
10
11
# 2、 字符串(String)
String是redis最基本的类型,你可以理解成Memcached一模一样的类型,一个key对应一个value。
Redis的string可以包含任何数据,比如jpg图片或者序列化的对象。
其value是字符串,不过根据字符串的格式不同,又可以分为3类:
- string:普通字符串
- int:整数类型,可以做自增、自减操作
- float:浮点类型,可以做自增、自减操作
不管是哪种格式,底层都是字节数组形式存储,只不过是编码方式不同。字符串类型的最大空间不能超过512M。
# 2.1、SET key value
设置指定 key 的值。
127.0.0.1:6379> set name xiaoming
OK
2
# 2.2、GET key
获取指定 key 的值。
127.0.0.1:6379> get name
"xiaoming"
2
# 2.3、MSET key value [key value ...]
批量添加多个String类型的键值对
127.0.0.1:6379> mset k1 v1 k2 v2
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "name"
2
3
4
5
6
7
# 2.4、MGET key1 [key2..]
根据多个key获取多个String类型的value,这个可以用在项目的浏览量和点赞的应用上
127.0.0.1:6379> mget k1 k2
1) "v1"
2) "v2"
2
3
# 2.5、INCR key
将 key 中储存的数字值增一。
127.0.0.1:6379> set age 20
OK
127.0.0.1:6379> incr age
(integer) 21
127.0.0.1:6379> incr age
(integer) 22
2
3
4
5
6
7
# 2.6、INCRBY key increment
让一个整型的key自增并指定步长,例如:incrby num 2 让num值自增2
127.0.0.1:6379> incr age
(integer) 22
127.0.0.1:6379> incrby age 20
(integer) 42
2
3
4
5
# 2.7、INCRBYFLOAT key increment
将 key 所储存的值加上给定的浮点增量值(increment)
127.0.0.1:6379> incrbyfloat age 9
"51"
127.0.0.1:6379> incrbyfloat age 0.1
"51.10000000000000001"
2
3
4
# 2.8、DECR key
将 key 中储存的数字值减一。
127.0.0.1:6379> set num 1
OK
127.0.0.1:6379> decr num
(integer) 0
2
3
4
# 2.9、DECRBY key decrement
key 所储存的值减去给定的减量值(decrement) 。
127.0.0.1:6379> incrby num 20
(integer) 21
127.0.0.1:6379> decrby num 10
(integer) 11
2
3
4
5
# 2.10、SETNX key value
添加一个String类型的键值对,前提是这个key不存在,否则不执行
127.0.0.1:6379> setnx num 10
(integer) 0
127.0.0.1:6379> get num
"11"
2
3
4
5
# 2.11、SETEX key seconds value
添加一个String类型的键值对,并且指定有效期(以秒为单位)。
127.0.0.1:6379> setex time 200 fly
OK
127.0.0.1:6379> get time
"fly"
2
3
4
# 2.12、APPEND key value
如果 key 已经存在并且是一个字符串, APPEND 命令将指定的 value 追加到该 key 原来值(value)的末尾。
127.0.0.1:6379> get num
"11"
127.0.0.1:6379> append num 200
(integer) 5
127.0.0.1:6379> get num
"11200"
2
3
4
5
6
7
# 2.13、GETRANGE key start end
getrange 获取指定区间范围内的值,类似between...and的关系,从零到负一表示全部
127.0.0.1:6379> set name a3121assaxd
OK
//全部获取
127.0.0.1:6379> getrange name 0 -1
"a3121assaxd"
//截取部分字符串
127.0.0.1:6379> getrange name 0 2
"a31"
2
3
4
5
6
7
8
9
# 2.14、SETRANGE key offset value
setrange 设置指定区间范围内的值,格式是setrange key值 具体值
127.0.0.1:6379> setrange name 1 xxx
(integer) 11
127.0.0.1:6379> get name
"axxx1assaxd"
2
3
4
5
# 2.15、总结
- String数据结构是简单的key-value类型,value其实不仅可以是String,也可以是数字。
- 常规key-value缓存应用: 常规计数:微博数,粉丝数等。
问题1:Redis没有类似MySQL中的Table的概念,我们该如何区分不同类型的key呢?
比如在我们开发一个项目中,需要将用户和产品的信息存入到id,这时用户的id和产品的id可能都为1,那我们怎么存储到redis,我们知道redis的key不能重复。
这时我们就要看一下key的结构了:
Redis的key允许有多个单词形成层级结构,多个单词之间用':'隔开,格式如下:
例如:项目名称:业务名称:类型:id
这个格式并非固定,也可以根据自己的需求来删除或添加词条。
例如我们的项目名称叫 blog,有user和product两种不同类型的数据,我们可以这样定义key:
user相关的key:blog:user:1
product相关的key:blog:product:1
如果Value是一个Java对象,例如一个User对象,则可以将对象序列化为JSON字符串后存储:
key | value |
---|---|
blog:user:1 | {"id":1, "name": "xiaoming", "phone": 123456789} |
blog:product:1 | {"id":1, "name": "huwei", "color": "red"} |
添加的数据:
'{"id":1, "name":"xiaoming", "phone": 12345678911}'
'{"id":2, "name":"xiaohong", "phone": 18212121111}'
'{"id":1, "name":"huwei", "color": "red"}'
'{"id":2, "name":"xiaomi", "color": "black"}'
2
3
4
127.0.0.1:6379> set blog:user:1 '{"id":1, "name": "xiaoming", "phone": 123456789}'
OK
127.0.0.1:6379> set blog:user:2 '{"id":2, "name":"xiaohong", "phone": 18212121111}'
OK
127.0.0.1:6379> set blog:product:1 '{"id":1, "name":"huwei", "color": "red"}'
OK
127.0.0.1:6379> set blog:product:2 '{"id":2, "name":"xiaomi", "color": "black"}'
OK
2
3
4
5
6
7
8
9
10
11
添加完之后,打开之前安装的Redis客户端工具,然后查看我们刚添加的数据,树状的文件夹列表。
还有很多的命令这里不再一一讲述,具体可以看官网发布的命令去学习:https://redis.io/commands
# 3、哈希(Hash)
Redis hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。如用户信息等。
Redis hash 是一个键值对集合,类似于Java中的HashMap结构。
Redis 中每个 hash 可以存储 232 - 1 键值对(40多亿)。
String结构是将对象序列化为JSON字符串后存储,当需要修改对象某个字段时很不方便
key | value |
---|---|
blog:user:1 | {"id":1, "name": "xiaoming", "phone": 123456789} |
blog:user:2 | {"id":2, "name":"xiaohong", "phone": 18212121111} |
Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD:
以下是Hash常见的命令:
# 3.1、HSET key field value
添加或者修改hash类型 key 的field的值
127.0.0.1:6379> hset dog color red
(integer) 1
127.0.0.1:6379> hset dog age 2
(integer) 1
127.0.0.1:6379> hset tree name guihua
(integer) 1
127.0.0.1:6379> hset tree age 20
(integer) 1
2
3
4
5
6
7
8
# 3.2、HGET key field
获取存储在哈希表中指定字段的值。
127.0.0.1:6379> hget tree age
"20"
127.0.0.1:6379> hget dog color
"red"
2
3
4
# 3.3、HMSET key field1 value1 [field2 value2 ]
批量添加多个hash类型key的field的值
127.0.0.1:6379> hmset dog name xiaohua sex nan
OK
2
# 3.4、HMGET key field1 [field2]
批量获取多个hash类型key的field的值
127.0.0.1:6379> hmget dog name age
1) "xiaohua"
2) "2"
2
3
# 3.5、HGETALL key
获取在哈希表中指定 key 的所有字段和值
127.0.0.1:6379> hgetall dog
1) "color"
2) "red"
3) "age"
4) "2"
5) "name"
6) "xiaohua"
7) "sex"
8) "nan"
2
3
4
5
6
7
8
9
# 3.6、HKEYS key
获取一个hash类型的key中的所有的field
127.0.0.1:6379> hkeys dog
1) "color"
2) "age"
3) "name"
4) "sex"
2
3
4
5
# 3.7、HVALS key
获取一个hash类型的key中的所有的value
127.0.0.1:6379> hvals dog
1) "red"
2) "2"
3) "xiaohua"
4) "nan"
2
3
4
5
# 3.8、HINCRBY key field increment
让一个hash类型key的字段值自增并指定步长
127.0.0.1:6379> hincrby dog age 5
(integer) 7
2
# 3.9、HSETNX key field value
只有在字段 field 不存在时,设置哈希表字段的值。
127.0.0.1:6379> hsetnx dog age 3
(integer) 0
2
# 3.10、HEXISTS key field
查看哈希表 key 中,指定的字段是否存在。
127.0.0.1:6379> hexists dog name
(integer) 1
2
# 3.11、HLEN key
获取哈希表中字段的数量
127.0.0.1:6379> hlen dog
(integer) 4
2
# 4、列表(List)
Redis列表是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
它的底层实际是个链表 !
Redis中的List类型与Java中的LinkedList类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。
特征也与LinkedList类似:
- 有序
- 元素可以重复
- 插入和删除快
- 查询速度一般
常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。
一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
# 4.1、LPUSH key value1 [value2]
将一个或多个值插入到列表头部(左侧)。
127.0.0.1:6379> lpush cat xiaohua
(integer) 1
2
# 4.2、LPOP key
移出并获取列表的第一个元素(左侧),当列表 key 不存在时,则返回nil。
127.0.0.1:6379> lpop cat1
(nil)
127.0.0.1:6379> lpop cat
"xiaohua"
2
3
4
# 4.3、RPUSH key value1 [value2]
向列表右侧插入一个或多个元素。
127.0.0.1:6379> rpush cat xiaolan xiaoming
(integer) 2
2
# 4.4、RPOP key
移除并返回列表右侧的第一个元素。
127.0.0.1:6379> rpop cat
"xiaoming"
2
# 4.5、LRANGE key start stop
获取列表指定范围内的元素。
其中 0 表示列表的第一个元素, 1 表示列表的第二个元素,以此类推
0,-1范围是全部查出。
127.0.0.1:6379> lrange cat 0 2
1) "xiaolan"
2
# 4.6、LREM key count value
根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素。
127.0.0.1:6379> lrem cat 1 "xiaolan"
(integer) 1
2
# 4.7、LTRIM key start stop
对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。
127.0.0.1:6379> RPUSH mylist "hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist "hello"
(integer) 2
127.0.0.1:6379> RPUSH mylist "foo"
(integer) 3
127.0.0.1:6379> RPUSH mylist "bar"
(integer) 4
127.0.0.1:6379> LTRIM mylist 1 -1
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "foo"
3) "bar"
2
3
4
5
6
7
8
9
10
11
12
13
14
# 4.8、RPOPLPUSH source destination
移除列表的最后一个元素,并将该元素添加到另一个列表并返回
127.0.0.1:6379> rpoplpush mylist myotherlist
"bar"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "foo"
2
3
4
5
# 4.9、LSET key index value
将列表 key 下标为 index 的元素的值设置为 value 。
127.0.0.1:6379> exists mylist # 对空列表(key 不存在)进行 LSET
(integer) 1
127.0.0.1:6379> lset mylist 0 item # 对非空列表进行 LSET
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "item"
2) "foo"
2
3
4
5
6
7
# 4.10、LINSERT key BEFORE|AFTER pivot value
在列表的元素前或者后插入元素。
127.0.0.1:6379> LINSERT mylist BEFORE "foo" "world"
(integer) 3
127.0.0.1:6379> Lrange mylist 0 -1
1) "item"
2) "world"
3) "foo"
2
3
4
5
6
# 4.11、LLEN key
获取哈希表中字段的数量。
127.0.0.1:6379> Llen mylist
(integer) 3
2
# 4.12、Lindex key index
按照索引下标获得元素(-1代表最后一个,0代表是第一个,即所有)
相当于 Java 链表操作中的 get(int index) 操 作;
127.0.0.1:6379> Lindex cat 1
(nil)
127.0.0.1:6379> Lindex cat 0
"xiaolan"
127.0.0.1:6379> Lindex cat -1
"xiaolan"
2
3
4
5
6
# 4.13、总结
- 链表的操作无论是头和尾效率都极高,但假如是对中间元素进行操作,效率就低了。
- 它是一个字符串链表,left,right 都可以插入添加 。
- 如果键不存在,创建新的链表 如果键已存在,新增内容。
- 如果值全移除,对应的键也就消失了。
list就是链表,略有数据结构知识的人都应该能理解其结构。使用Lists结构,我们可以轻松地实现最新消息排行等功能。List的另一个应用就是消息队列,可以利用List的PUSH操作,将任务存在List中,然后工作线程再用POP操作将任务取出进行执行。Redis还提供了操作List中某一段的api,你可以直接查询,删除List中某一段的元素。
Redis的list是每个子元素都是String类型的双向链表,可以通过push和pop操作从列表的头部或者尾部 添加或者删除元素,这样List即可以作为栈,也可以作为队列。
# 4.14、问题
1、list 实现队列
队列是先进先出的数据结构,常用于消息排队和异步逻辑处理,它会确保元素的访问顺序:
127.0.0.1:6379> RPUSH books python java golang
(integer) 3
127.0.0.1:6379> LPOP books
"python"
127.0.0.1:6379> LPOP books
"java"
127.0.0.1:6379> LPOP books
"golang"
127.0.0.1:6379> LPOP books
(nil)
2
3
4
5
6
7
8
9
10
2、list 实现栈
栈是先进后出的数据结构,跟队列正好相反:
127.0.0.1:6379> RPUSH books python java golang
(integer) 3
127.0.0.1:6379> RPOP books
"golang"
127.0.0.1:6379> RPOP books
"java"
127.0.0.1:6379> RPOP books
"python"
127.0.0.1:6379> RPOP books
(nil)
127.0.0.1:6379>
2
3
4
5
6
7
8
9
10
11
# 5、集合(Set)
Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
Redis的Set结构与Java中的HashSet类似,可以看做是一个value为null的HashMap。
# 5.1、SADD key member1 [member2]
将一个或多个成员元素加入到集合中,不能重复
127.0.0.1:6379> sadd book java vue spring
(integer) 3
2
# 5.2、SMEMBERS key
返回集合中的所有成员。
127.0.0.1:6379> smembers book
1) "vue"
2) "java"
3) "spring"
2
3
4
# 5.3、SISMEMBER key member
判断 member 元素是否是集合 key 的成员
127.0.0.1:6379> sismember book java
(integer) 1
127.0.0.1:6379> sismember book go
(integer) 0
2
3
4
# 5.4、SCARD key
获取集合里面的元素个数
127.0.0.1:6379> scard book
(integer) 3
2
# 5.5、SREM key member1 [member2]
移除集合中一个或多个成员
127.0.0.1:6379> srem book spring
(integer) 1
2
# 5.6、SRANDMEMBER key [count]
令用于返回集合中的一个随机元素。
127.0.0.1:6379> srandmember book
"java"
127.0.0.1:6379> srandmember book 2
1) "vue"
2) "java"
2
3
4
5
# 5.7、SPOP key
移除并返回集合中的一个随机元素
127.0.0.1:6379> smembers book
1) "vue"
2) "java"
127.0.0.1:6379> spop book
"java"
127.0.0.1:6379> smembers book
1) "vue"
2
3
4
5
6
7
# 5.8、SMOVE source destination member
将 member 元素从 source 集合移动到 destination 集合
127.0.0.1:6379> sadd book java go spring
(integer) 3
127.0.0.1:6379> smembers book
1) "vue"
2) "go"
3) "java"
4) "spring"
127.0.0.1:6379> smove book books java
(integer) 1
2
3
4
5
6
7
8
9
# 5.9、SDIFF key1 [key2]
返回第一个集合与其他集合之间的差异。
127.0.0.1:6379> smembers book
1) "vue"
2) "go"
3) "spring"
127.0.0.1:6379> smembers books
1) "vue"
2) "springboot"
3) "java"
127.0.0.1:6379> sdiff book books
1) "go"
2) "spring"
2
3
4
5
6
7
8
9
10
11
# 5.10、SINTER key1 [key2]
返回给定所有集合的交集
127.0.0.1:6379> sinter book books
1) "vue"
2
# 5.11、SUNION key1 [key2]
返回所有给定集合的并集
127.0.0.1:6379> sunion book books
1) "vue"
2) "springboot"
3) "go"
4) "spring"
5) "java"
2
3
4
5
6
# 5.12、应用学习
在我们的实际项目中,例如在微博中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis还为 集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集 合中。
1、小明的爱好关注了:足球、电影、王者荣耀、电子书。
2、小兰的爱好关注了:电影、体育、衣服、彩妆。
将他们的爱好都存入到集合中:
127.0.0.1:6379> sadd xiaoming football dianying wangzhe dianzishu
(integer) 4
127.0.0.1:6379> sadd xiaolan dianying tiyu yifu caizhuang
(integer) 4
2
3
4
下面将实现以下功能:
- 统计小明的爱好有几个?,小兰的爱好有几个?
127.0.0.1:6379> scard xiaoming
(integer) 4
127.0.0.1:6379> scard xiaolan
(integer) 4
2
3
4
- 小明和小兰共同的爱好有哪些?
127.0.0.1:6379> sinter xiaoming xiaolan
1) "dianying"
2
- 有哪些是小明的爱好但不是小兰的爱好?,有哪些是小兰的爱好但不是小明的爱好
127.0.0.1:6379> sdiff xiaoming xiaolan
1) "football"
2) "dianzishu"
3) "wangzhe"
127.0.0.1:6379> sdiff xiaolan xiaoming
1) "tiyu"
2) "yifu"
3) "caizhuang"
2
3
4
5
6
7
8
- 小明和小兰总共有哪些爱好?
127.0.0.1:6379> sunion xiaoming xiaolan
1) "football"
2) "dianzishu"
3) "dianying"
4) "wangzhe"
5) "yifu"
6) "caizhuang"
7) "tiyu"
2
3
4
5
6
7
8
- 判断体育是否是小明的爱好。
127.0.0.1:6379> sismember xiaoming tiyu
(integer) 0
2
- 判断体育是否是小兰的爱好。
127.0.0.1:6379> sismember xiaolan tiyu
(integer) 1
2
- 将体育从小兰的爱好中移除。
127.0.0.1:6379> srem xiaolan tiyu
(integer) 1
127.0.0.1:6379> smembers xiaolan
1) "dianying"
2) "caizhuang"
3) "yifu"
2
3
4
5
6
# 6、有序集合(sorted set或zset)
这可能使 Redis 最具特色的一个数据结构了,它类似于 Java 中 SortedSet 和 HashMap 的结合体,一 方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以为每个 value 赋予一个 score 值,用 来代表排序的权重。
Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
SortedSet中的每一个元素都带有一个score属性,可以基于score属性对元素排序,底层的实现是一个跳表(SkipList)加 hash表。
SortedSet具备下列特性:
- 可排序
- 元素不重复
- 查询速度快
因为SortedSet的可排序特性,经常被用来实现排行榜这样的功能。
这里先说一下跳跃表吧
想象你是一家创业公司的老板,刚开始只有几个人,大家都平起平坐。后来随着公司的发展,人数越来 越多,团队沟通成本逐渐增加,渐渐地引入了组长制,对团队进行划分,于是有一些人又是员工又有组 长的身份。
再后来,公司规模进一步扩大,公司需要再进入一个层级:部门。于是每个部门又会从组长中推举一位 选出部长。
跳跃表就类似于这样的机制,最下面一层所有的元素都会串起来,都是员工,然后每隔几个元素就会挑 选出一个代表,再把这几个代表使用另外一级指针串起来。然后再在这些代表里面挑出二级代表,再串 起来。最终形成了一个金字塔的结构。
想一下你目前所在的地理位置:亚洲 > 中国 > 某省 > 某市 > ....,就是这样一个结构!
# 6.1、ZADD key score1 member1 [score2 member2]
添加一个或多个元素到sorted set ,如果已经存在则更新其score值。
127.0.0.1:6379> zadd book 1 java1
(integer) 1
2
# 6.2、ZRANGE key start stop [WITHSCORES]
通过索引区间返回有序集合指定区间内的成员
127.0.0.1:6379> zadd book 2 java2 3 java3
(integer) 2
127.0.0.1:6379> zrange book 0 -1
1) "java1"
2) "java2"
3) "java3"
2
3
4
5
6
# 6.3、ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT]
# 添加三条数据
127.0.0.1:6379> ZADD salary 2500 jack
(integer) 1
127.0.0.1:6379> ZADD salary 5000 tom
(integer) 1
127.0.0.1:6379> ZADD salary 12000 peter
# Inf无穷大量+∞,同样地,-∞可以表示为-Inf。
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf
1) "jack"
2) "tom"
3) "peter"
# 递减排列
127.0.0.1:6379> ZREVRANGE salary 0 -1 WITHSCORES
1) "peter"
2) "12000"
3) "tom"
4) "5000"
5) "jack"
6) "2500"
# 显示工资 <=5000 的所有成员
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 5000 WITHSCORES
1) "jack"
2) "2500"
3) "tom"
4) "5000"
# 显示工资大于 5000 小于等于 400000 的成员
127.0.0.1:6379> ZRANGEBYSCORE salary (5000 400000
1) "peter"
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 6.4、ZREM key member [member ...]
移除有序集中的一个或多个成员
127.0.0.1:6379> zrange book 0 -1
1) "java1"
2) "java2"
3) "java3"
127.0.0.1:6379> zrem book java1
(integer) 1
127.0.0.1:6379> zrange book 0 -1
1) "java2"
2) "java3"
2
3
4
5
6
7
8
9
# 6.5、ZCARD key
获取有序集合的成员数
127.0.0.1:6379> zcard book
(integer) 2
2
# 6.6、ZCOUNT key min max
计算在有序集合中指定区间分数的成员数
127.0.0.1:6379> zcount book 1 3
(integer) 2
2
# 6.7、ZRANK key member
返回有序集中指定成员的排名。其中有序集成员按分数值递增(从小到大)顺序排列。
# 显示所有成员及其 score 值
127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES
1) "jack"
2) "2500"
3) "tom"
4) "5000"
5) "peter"
6) "12000"
# 显示 jack 的薪水排名,最少
127.0.0.1:6379> zrank salary jack
(integer) 0
2
3
4
5
6
7
8
9
10
11
12
# 6.8、ZREVRANK key member
返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
# jack排名第三
127.0.0.1:6379> zrevrank salary jack
(integer) 2
2
3
# 6.9、ZSCORE key member
获取sorted set中的指定元素的score值
127.0.0.1:6379> zscore book java2
"2"
2
# 6.10、ZINCRBY key increment member
让sorted set中的指定元素自增,步长为指定的increment值
127.0.0.1:6379> zincrby book 10 java
"30"
2
ZDIFF、ZINTER、ZUNION:求差集、交集、并集
注意:所有的排名默认都是升序,如果要降序则在命令的Z后面添加REV即可
# 6.11、练习
将以下数据存入到Redis的Zset中。
java 20,go 19,vue 30 ,spring 32,python 12,html 9
127.0.0.1:6379> zadd book 20 java 19 go 30 vue 32 spring 12 python 9 html
(integer) 6
2
- 删除go
127.0.0.1:6379> zrem book go
(integer) 1
127.0.0.1:6379> zrange book 0 -1
1) "html"
2) "python"
3) "java"
4) "vue"
5) "spring"
2
3
4
5
6
7
8
- 获取vue的价格
127.0.0.1:6379> zscore book vue
"30"
2
- 查询vue价格的排名
127.0.0.1:6379> zrank book vue
(integer) 3
2
- 查询价格低于20以下的
127.0.0.1:6379> zcount book 0 20
(integer) 3
2
- 给java的价格加上10
127.0.0.1:6379> zincrby book 10 java
"30"
2
- 查询价格的前三名
127.0.0.1:6379> zrevrange book 0 2
1) "spring"
2) "vue"
3) "java"
2
3
4
和set相比,sorted set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列
排行榜应用,取TOP N操作 !