redis学习(二)之五大基本数据类型

Redis五大基本数据类型

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets) 与范围查询, bitmapshyperloglogs地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication)LUA脚本(Lua scripting)LRU驱动事件(LRU eviction)事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)

1、Redis-Key

Redis常规命令查询:Redis常规命令

1
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
33
34
35
127.0.0.1:6379> keys * # 查询所有的key
(empty array)
127.0.0.1:6379> set name ldg # set key
OK
127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> set age 25
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> EXISTS name # 查看当前的key是否存在
(integer) 1
127.0.0.1:6379> EXISTS name1
(integer) 0
127.0.0.1:6379> move name 1 # 移除当前的key
(integer) 1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> set name ldg
OK
127.0.0.1:6379> get name
"ldg"
127.0.0.1:6379> EXPIRE name 10 # 设置key的过期时间,单位是秒
(integer) 1
127.0.0.1:6379> ttl name # 查看当前key的过期剩余时间
(integer) 5
127.0.0.1:6379> ttl name
(integer) 3
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> get name # get key
(nil)
127.0.0.1:6379> type age # 查看当前key的一个类型
string

2、String(字符串)

1
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#################################################################################
127.0.0.1:6379> set k1 v1 # 设置值
OK
127.0.0.1:6379> get k1 # 获得值
"v1"
127.0.0.1:6379> keys * # 获取所有的key
1) "k1"
127.0.0.1:6379> EXISTS k1 # 判断某一个key是否存在
(integer) 1
127.0.0.1:6379> APPEND k1 "hello" # 追加字符串,如果当前key不存在,就相当于set key
(integer) 7
127.0.0.1:6379> get k1
"v1hello"
127.0.0.1:6379> STRLEN k1 # 获取字符串的长度
(integer) 7
127.0.0.1:6379> APPEND k1 ",nihao"
(integer) 13
127.0.0.1:6379> STRLEN k1
(integer) 13
127.0.0.1:6379> get k1
"v1hello,nihao"
#################################################################################
127.0.0.1:6379> set views 0 # 初始浏览量为0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views # 自增1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> decr views # 自减1
(integer) 1
127.0.0.1:6379> decr views
(integer) 0
127.0.0.1:6379> decr views
(integer) -1
127.0.0.1:6379> get views
"-1"
127.0.0.1:6379> incrby views 10 #可以设置步长,指定增量
(integer) 9
#################################################################################
127.0.0.1:6379> set k1 "ldg,nihao" # 设置k1的值
OK
127.0.0.1:6379> get k1
"ldg,nihao"
127.0.0.1:6379> getrange k1 0 3 # 截取字符串[0,3]
"ldg,"
127.0.0.1:6379> getrange k1 0 -1 # 获取全部的字符串,和get key是一样的
"ldg,nihao"
127.0.0.1:6379> set k2 abcdefg
OK
127.0.0.1:6379> get k2
"abcdefg"
127.0.0.1:6379> setrange k2 1 xx # 替换指定位置开始的字符串
(integer) 7
127.0.0.1:6379> get k2
"axxdefg"
#################################################################################
# setex (set with expire) # 设置过期时间
# setnx (set if not exist) # 不存在在设置(在分布式锁中会常常使用)
127.0.0.1:6379> setex k3 30 "hello" # 设置k3的值为hello,30秒后过期
OK
127.0.0.1:6379> ttl k3
(integer) 28
127.0.0.1:6379> get k3
"hello"
127.0.0.1:6379> ttl k3 # 查看当前key的过期时间
(integer) 23
127.0.0.1:6379> keys *
1) "k3"
127.0.0.1:6379> setnx mykey "redis" # 如果mykey不存在,创建mykey
(integer) 1
127.0.0.1:6379> ttl k3
(integer) -2
127.0.0.1:6379> setnx mykey MongoDB # 如果key存在,创建失败
(integer) 0
127.0.0.1:6379> get mykey
"redis"
#################################################################################
# mset和mget
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 同时设置多个值
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k3"
3) "k2"
127.0.0.1:6379> mget k1 k2 k3 # 同事获取多个值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k4 v4 # mset是一个原子性的操作,要么一起成功,要么一起失败
(integer) 0
127.0.0.1:6379> get k4
(nil)
#################################################################################
# 对象
127.0.0.1:6379> set user:1 {name:zhangsan,age:3} #设置一个user:1对象,值为jso字符串来保存一个对象
OK
127.0.0.1:6379> get user:1
"{name:zhangsan,age:3}"
# 这里的key是一个巧妙的设计:user:{id}:{field},如此设计在Redis是完全ok的
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
#################################################################################
# getset 先get在set
127.0.0.1:6379> getset db redis # 如果不存在值,则返回nil
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongodb # 如果存在值,获取原来的值,并设置新的值
"redis"
127.0.0.1:6379> get db
"mongodb"
#################################################################################

数据结构是相同的!

String类似的使用场景,value除了是我们的字符串还可以是我们的数字!

  • 计数器
  • 统计多单位的数量
  • 粉丝数
  • 对象缓存存储

3、List(列表)

在redis里面,可以把list玩成栈、队列、阻塞队列

1635062371558

所有的list命令都是l开头的,不区分大小写命令

1
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#################################################################################
127.0.0.1:6379> lpush list one # 将一个值或多个值插入列表的头部(左)
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1 # 获取list中的值
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1 # 通过区间获取具体的值
1) "three"
2) "two"
127.0.0.1:6379> rpush list four # 将一个值或者多个值,插入到列表尾部(右)
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "four"
#################################################################################
# lpop rpop
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "four"
127.0.0.1:6379> lpop list # 移除list的第一个元素
"three"
127.0.0.1:6379> rpop list # 移除list的最后一个元素
"four"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one
#################################################################################
# lindex
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lindex list 1 # 通过下标获取list中的某一个值
"one"
127.0.0.1:6379> lindex list 0
"two"
#################################################################################
# llren
127.0.0.1:6379> lpush list one
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> llen list # 返回列表的长度
(integer) 3
#################################################################################
# 移除指定的值
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
4) "one"
127.0.0.1:6379> lrem list 1 one # 移除list集合中指定个数的value,精确匹配
(integer) 1
127.0.0.1:6379> lrem list 1 three
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "three"
3) "two"
127.0.0.1:6379> lrem list 2 three
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
#################################################################################
# trim 修剪
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "hello1"
(integer) 2
127.0.0.1:6379> rpush mylist "hello2"
(integer) 3
127.0.0.1:6379> rpush mylist "hello3"
(integer) 4
127.0.0.1:6379> ltrim mylist 1 2 # 通过下标截取指定的长度,这个list已经被改变了,截断了只剩下截取的元素
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
#################################################################################
127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "hello1"
(integer) 2
127.0.0.1:6379> rpush mylist "hello2"
(integer) 3
127.0.0.1:6379> rpoplpush mylist myotherlist # 移除列表的最后一个元素,将它移动到新的列表中
"hello2"
127.0.0.1:6379> lrange mylist 0 -1 # 查看原来的列表
1) "hello"
2) "hello1"
127.0.0.1:6379> lrange myotherlist 0 -1 # 查看目标列表中,确实存在该值
1) "hello2"
#################################################################################
# lset 将列表中指定下标的值替换为另外一个值,更新操作
127.0.0.1:6379> exists list # 判断这个列表是否存在
(integer) 0
127.0.0.1:6379> lset list 0 item # 如果不存在,我们去更新会报错
(error) ERR no such key
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 item # 如果存在,更新当前下标的值
OK
127.0.0.1:6379> lrange list 0 0
1) "item"
127.0.0.1:6379> lset list 1 other # 如果不存在,则会报错
(error) ERR index out of range
#################################################################################
# linsert 将某个具体的value插入到列表中某个元素的前面或者后面
127.0.0.1:6379> rpush mylist hello
(integer) 1
127.0.0.1:6379> rpush mylist world
(integer) 2
127.0.0.1:6379> linsert mylist before world other
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "other"
3) "world"
127.0.0.1:6379> linsert mylist after world new
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "other"
3) "world"
4) "new"
#################################################################################

小结

  • list实际是上一个链表,before Node after,left、right都可以插入值
  • 如果key不存在,创建新的链表
  • 如果key存在,新增内容
  • 如果移除了所有的值,空链表,也代表不存在
  • 在两边插入或者改动值,效率最高

应用:消息排队!消息队列(LPush Rpop)、栈(Lpush Lpop)

4、Set(集合)

set中的值是不重复的

1
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#################################################################################
127.0.0.1:6379> sadd myset hello # set集合中添加元素
(integer) 1
127.0.0.1:6379> sadd myset ldg
(integer) 1
127.0.0.1:6379> smembers myset # 查看指定set的所有制
1) "hello"
2) "ldg"
127.0.0.1:6379> sismember myset hello # 判断某一个值是不是在set集合中
(integer) 1
127.0.0.1:6379> sismember myset world
(integer) 0
#################################################################################
127.0.0.1:6379> scard myset # 获取set集合中的内容元素个数
(integer) 2
#################################################################################
127.0.0.1:6379> smembers myset
1) "hello"
2) "ldg"
127.0.0.1:6379> sadd myset hello1
(integer) 1
127.0.0.1:6379> scard myset
(integer) 3
127.0.0.1:6379> srem myset hello1 # 移除set集合中的指定元素
(integer) 1
127.0.0.1:6379> scard myset
(integer) 2
127.0.0.1:6379> smembers myset
1) "hello"
2) "ldg"
#################################################################################
# set无序不重复集合,抽随机
127.0.0.1:6379> smembers myset
1) "hello"
2) "hello1"
3) "ldg"
127.0.0.1:6379> srandmember myset # 随机抽取一个元素
"ldg"
127.0.0.1:6379> srandmember myset # 随机抽取一个元素
"hello1"
127.0.0.1:6379> srandmember myset
"ldg"
127.0.0.1:6379> srandmember myset
"ldg"
127.0.0.1:6379> srandmember myset
"ldg"
127.0.0.1:6379> srandmember myset 2 # 随机抽选出自定个数的元素
1) "hello"
2) "ldg"
127.0.0.1:6379> srandmember myset 2
1) "hello"
2) "ldg"
127.0.0.1:6379> srandmember myset 2
1) "hello"
2) "hello1"
#################################################################################
# 删除指定的key,随机删除key
127.0.0.1:6379> smembers myset
1) "hello"
2) "hello1"
3) "ldg"
127.0.0.1:6379> spop myset # 随机删除一些set集合中的元素
"ldg"
127.0.0.1:6379> spop myset
"hello1"
127.0.0.1:6379> smembers myset
1) "hello"
#################################################################################
# 将一个指定的值,移动到另外一个set集合
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset world
(integer) 1
127.0.0.1:6379> sadd myset ldg
(integer) 1
127.0.0.1:6379> sadd myset2 set2
(integer) 1
127.0.0.1:6379> smove myset myset2 ldg # 将一个指定的值,移动到另外一个set集合
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello"
2) "world"
127.0.0.1:6379> smembers myset2
1) "set2"
2) "ldg"
#################################################################################
数字集合类
- 差集
- 交集
- 并集
127.0.0.1:6379> sadd key1 a
(integer) 1
127.0.0.1:6379> sadd key1 b
(integer) 1
127.0.0.1:6379> sadd key1 c
(integer) 1
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sadd key2 d
(integer) 1
127.0.0.1:6379> sadd key2 e
(integer) 1
127.0.0.1:6379> sdiff key1 key2 # 差集,主要是求出key1 在key2中的差集
1) "b"
2) "a"
127.0.0.1:6379> sdiff key2 key1 # 差集,主要是求出key2 在key1中的差集
1) "d"
2) "e"
127.0.0.1:6379> sinter key1 key2 # 交集,共同好友可以这样实现
1) "c"
127.0.0.1:6379> sunion key1 key2 # 并集
1) "b"
2) "c"
3) "e"
4) "a"
5) "d"

微博,A用户将所有关注的人放在一个set集合中,将它的粉丝也放在一个集合中

应用:共同关注、共同爱好、二度好友、推荐好友

5、Hash(哈希)

Map集合,key-map!这个时候,这个值是一个map集合。

本质和String类型没有太大区别,还是一个简单的key-value

1
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
127.0.0.1:6379> hset myhash field1 ldg # set一个具体的key-value
(integer) 1
127.0.0.1:6379> hget myhash field1 # 获取一个字段值
"ldg"
127.0.0.1:6379> hmset myhash field1 hello field2 world # set多个key-value
OK
127.0.0.1:6379> hmget myhash field1 field2 # 获取多个字段值
1) "hello"
2) "world"
127.0.0.1:6379> hgetall myhash # 获取全部的数据
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hdel myhash field1 # 删除hash指定key字段!对应的value值也就消失了
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "world"
#################################################################################
hlen
127.0.0.1:6379> hmset myhash field1 hello field2 world
OK
127.0.0.1:6379> hgetall myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
127.0.0.1:6379> hlen myhash # 获取hash表的字段数量
(integer) 2
#################################################################################
127.0.0.1:6379> hexists myhash field1 # 判断hash中指定字段是否存在
(integer) 1
127.0.0.1:6379> hexists myhash field3
(integer) 0
#################################################################################
# 只获取所有的field
# 只获取所有的value
127.0.0.1:6379> hkeys myhash # 只获取所有的field
1) "field1"
2) "field2"
127.0.0.1:6379> hvals myhash # 只获取所有的value
1) "hello"
2) "world"
#################################################################################
incr decr
127.0.0.1:6379> hset myhash field3 5
(integer) 1
127.0.0.1:6379> hincrby myhash field3 1 # 指定增量
(integer) 6
127.0.0.1:6379> hincrby myhash field3 -1
(integer) 5
127.0.0.1:6379> hsetnx myhash field4 hello # 如果不存在,则可以创建值
(integer) 1
127.0.0.1:6379> hsetnx myhash field4 world # 如果存在,则不能创建
(integer) 0

hash变更的数据 user name age,尤其是用户信息之类的,经常变动的信息!hash更适合于对象的存储,String更适合字符串存储!

6、ZSet(有序集合)

在set的基础上,增加了一个值!

1
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
127.0.0.1:6379> zadd myset 1 one 
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three # 添加多个值
(integer) 2
127.0.0.1:6379> zrange myset 0 -1
1) "one"
2) "two"
3) "three"
#################################################################################
排序如何实现
127.0.0.1:6379> zadd salary 2500 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 5000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 500 ldg
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf # 显示全部得到用户 从小到大
1) "ldg"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores # 显示全部的用户并且附带成绩
1) "ldg"
2) "500"
3) "xiaohong"
4) "2500"
5) "zhangsan"
6) "5000"
127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores # 显示工资小于2500员工的升序排序
1) "ldg"
2) "500"
3) "xiaohong"
4) "2500"
127.0.0.1:6379> zrevrange salary 0 -1 # 移除了一个元素后,工资从大到小排序
1) "zhangsan"
2) "ldg"
#################################################################################
移除zset中的元素
127.0.0.1:6379> zrange salary 0 -1
1) "ldg"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:6379> zrem salary xiaohong # 移除有序集合中的指定元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "ldg"
2) "zhangsan"
127.0.0.1:6379> zcard salary # 获取有序集合中的个数
(integer) 2
#################################################################################
127.0.0.1:6379> zadd myset 1 hello
(integer) 1
127.0.0.1:6379> zadd myset 2 world 3 ldg
(integer) 2
127.0.0.1:6379> zcount myset 1 3 # 获取指定区间的成员变量
(integer) 3
127.0.0.1:6379> zcount myset 1 2
(integer) 2
#################################################################################

其余的一些API,通过查看官方文档进行了解

案例思路:set 排序,存储班级成绩表,工资表倒序!

普通消息:1,重要消息:2,带权重进行判断!

排行榜应用实现,取Top N测试!

0%