Redis-五大基础数据类型

基础知识

redis默认有16个数据库Redis的瓶颈是根据机器的内存和网络带宽。

为什么单线程还可以这么快?

redis是c语言写的,官网提供的性能数据

1s 11万读取

1s 8万写入

误区:

  1. 高性能的服务器一定是多线程的
  2. 多线程一定比单线程效率高

CPU—>内存—>硬盘

核心:redis将所有的数据都放入内存中,所以用单线程去操作效率是很高的,多线程(CPU上下文会切换,十分耗时),对于内存系统,没有上下文切换效率会很高,多次读写都是在一个CPU上的,没有线程调度的耗时

五大数据类型

基础命令

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
# 切换数据库
select index

# 查看当前数据库的数据数
dbsize

# 查看当前所有符合pattern的key
keys pattern

# 是否存在该key,存在则返回1,不存在则返回0
exists key

# 移除key
move key

#设置kv
set key value

# 查看key存储的值
get key

# 查看类型
type key

# 设置过期时间为secondss
expire key seconds

#查看剩余时间
ttl key

# 清空当前数据库
flushdb

# 清空所有的数据库的内容
flushall

# 随机输出一个key
randomkey

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
120
121
122
123
# 追加key存储的value字符串
# 如果key不存在,则该命令相当于set
# append key value
append key "appendstring"

# 查看key存储的字符串的长度
strlen key

# 自增1,自减1的操作
# incr key
# decr key
127.0.0.1:6379> set views 1
OK
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> incr views
(integer) 3
127.0.0.1:6379> decr views
(integer) 2
127.0.0.1:6379> decr views
(integer) 1

# 一次性加或者减指定数字的操作
# incrby key increment
# decrby key decrement
127.0.0.1:6379> incrby views 10
(integer) 11
127.0.0.1:6379> decrby views 10
(integer) 1

# 获取一个范围内的字符串,即substring==>[start,end)
# 注意这里的getrange是闭区间,[start,end]
# getrange key start end
127.0.0.1:6379> set name zhima
OK
127.0.0.1:6379> getrange name 0 3
"zhim"
127.0.0.1:6379> getrange name 0 -1
"zhima"

# 替换字符串
# setrange key offset value
127.0.0.1:6379> set key randomstring
OK
127.0.0.1:6379> setrange key 3 xxx
(integer) 12
127.0.0.1:6379> get key
"ranxxxstring"

# setex (set with expire) 设置过期时间
# 设置该字段过期时间为30s
# setex key seconds value
setex key 30 "expire"

# 如果不存在则设置值,在分布式锁中经常使用
# setnx (set if not exist)
# setnx key value
127.0.0.1:6379> set key1 value1
OK
127.0.0.1:6379> get key1
"value1"
127.0.0.1:6379> setnx key1 "setnx"
(integer) 0
127.0.0.1:6379> set key1 "setnx"
OK
127.0.0.1:6379> get key1
"setnx"

# 批量获取和设置值
# mget mset msetnx
# mset key value [key value..]
# mget key [key..]
# msetex key value [key value..]
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
127.0.0.1:6379> mget k1 k2
1) "v1"
2) "v2"
127.0.0.1:6379> msetnx k1 modifiedv1 k4 v4 # 该操作是一个原子性的操作!
(integer) 0
127.0.0.1:6379> get k4
(nil)

# 删除
# del key
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> keys *
1) "k1"
127.0.0.1:6379> del k1
(integer) 1
127.0.0.1:6379> keys *
(empty list or set)

# 对象
set user:1{name:zhangsan,age:3} # 设置一个user:1对象 值为json字符串来保存
# 这里的key是一个巧妙的属性:{className}:{id}:{field},在redis中是可以的
127.0.0.1:6379> mset user:1:name zhima user:1:age 19
OK
127.0.0.1:6379> keys *
1) "user:1:age"
2) "user:1:name"
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhima"
2) "19"

# 组合命令
# getset先取得当前的值并返回,然后修改当前的值
# getset key value
127.0.0.1:6379> getset db redis
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db modified
"redis"
127.0.0.1:6379> get db
"modified"

List

可以给其设置一个使用规则,则可以将其实现栈或者队列的功能

1
2
3
4
5
6
7
8
9
10
11
# 设置和取值
# lrange key start stop [start,stop]
127.0.0.1:6379> lpush list1 v1 v2 v3
(integer) 3
127.0.0.1:6379> lrange list1 0 -1
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379> lrange list1 0 1
1) "v3"
2) "v2"

分析可知这里的lpush是头插入,也就是left插入,那与之对应的肯定还有个尾插入,即right插入,但是啊只有LRANGE操作来取得集合里的数据,没有RRANGE操作

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
127.0.0.1:6379> rpush list v1 v2 v3
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "v1"
2) "v2"
3) "v3"

# 删除头部的值并返回
# lpop key
127.0.0.1:6379> lpop list
"v1"
127.0.0.1:6379> lrange list 0 -1
1) "v2"
2) "v3"
# 删除尾部的值并返回
# rpop key
127.0.0.1:6379> rpop list
"v3"
127.0.0.1:6379> lrange list 0 -1
1) "v2"

# 获取索引处的元素
# lindex key index
127.0.0.1:6379> lpush list v1 v2 v3
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379> lindex list 0
"v3"

# 获取集合长度
# llen key
127.0.0.1:6379> lrange list 0 -1
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379> llen list
(integer) 3

# 移除指定个数的匹配的值
# lrem key count value
127.0.0.1:6379> lrange list 0 -1
1) "v3"
2) "v3"
3) "v2"
4) "v1"
127.0.0.1:6379> lrem list 1 v1
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "v3"
2) "v3"
3) "v2"
127.0.0.1:6379> lrem list 2 v3
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "v2"

# 截取指定位置的值
# ltrim key start stop
127.0.0.1:6379> lrange list 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v2"
5) "v1"
127.0.0.1:6379> ltrim list 0 2
OK
127.0.0.1:6379> lrange list 0 -1
1) "v5"
2) "v4"
3) "v3"

# 将集合尾部元素移除,并在另一个集合头部加入一个元素
# rpoplpush source destination
127.0.0.1:6379> lrange list 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v2"
5) "v1"
127.0.0.1:6379> rpoplpush list otherlist
"v1"
127.0.0.1:6379> lrange list 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v2"
127.0.0.1:6379> lrange otherlist 0 -1
1) "v1"

# 修改指定索引处元素的值
127.0.0.1:6379> lrange list 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v2"
127.0.0.1:6379> lset list 0 modified
OK
127.0.0.1:6379> lrange list 0 -1
1) "modified"
2) "v4"
3) "v3"
4) "v2"
# lpush key value [value...]
# 当该集合不存在的时候会自动创建
# lset key index value
# 当该集合不存在的时候会报错

# 在指定值的前面|后面插入值
# linsert key BEFORE|AFTER pivot value
127.0.0.1:6379> lrange list 0 -1
1) "v5"
2) "v4"
3) "v3"
4) "v2"
5) "v1"
127.0.0.1:6379> linsert list before v2 brforev2
(integer) 6
127.0.0.1:6379> linsert list after v4 afterv4
(integer) 7
127.0.0.1:6379> lrange list 0 -1
1) "v5"
2) "v4"
3) "afterv4"
4) "v3"
5) "brforev2"
6) "v2"
7) "v1"

该List实质上是使用链表实现的

栈:出栈(Lpop)入栈(Lpush)== 出栈(Rpop) 入栈(Rpush)

队列:出队(Lpop)入队(Rpush)== 出栈(Rpop) 入栈(Lpush)

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
# 添加一个元素
# sadd key member [member..]
# 查看所有的成员
# smembers key
127.0.0.1:6379> sadd set a b c a
(integer) 3
127.0.0.1:6379> smembers set
1) "b"
2) "a"
3) "c"

# 判断是否包含某个元素
127.0.0.1:6379> smembers set
1) "b"
2) "a"
3) "c"
127.0.0.1:6379> sismember set c
(integer) 1
127.0.0.1:6379> sismember set d
(integer) 0

# 查看集合的长度
127.0.0.1:6379> smembers set
1) "b"
2) "a"
3) "c"
127.0.0.1:6379> scard set
(integer) 3

# 删除某个元素
# srem key member [member..]
127.0.0.1:6379> smembers set
1) "b"
2) "a"
3) "c"
127.0.0.1:6379> srem set a c
(integer) 2
127.0.0.1:6379> smembers set
1) "b"

# 随机返回指定个数的元素
# srandmember key count
127.0.0.1:6379> smembers set
1) "d"
2) "a"
3) "b"
4) "c"
5) "e"
127.0.0.1:6379> srandmember set 3
1) "d"
2) "e"
3) "c"
127.0.0.1:6379> srandmember set 3
1) "d"
2) "b"
3) "a

# 随机删除指定个数的元素,不写count默认为1
# spop key [count]
127.0.0.1:6379> smembers set
1) "d"
2) "a"
3) "b"
4) "c"
5) "e"
127.0.0.1:6379> spop set 3
1) "c"
2) "e"
3) "a"
127.0.0.1:6379> smembers set
1) "b"
2) "d"

# 将一个指定的值,移到另一个集合中
# smove source destination member
127.0.0.1:6379> sadd set a b c d e
(integer) 5
127.0.0.1:6379> smove set set2 a
(integer) 1
127.0.0.1:6379> smembers set2
1) "a"
127.0.0.1:6379> smembers set
1) "c"
2) "b"
3) "d"
4) "e"

# 交集 sinter key [key..]
# 差集 sdiff key [key..]
# 并集 sunion key [key..]
127.0.0.1:6379> smembers set
1) "c"
2) "b"
3) "d"
4) "e"
127.0.0.1:6379> smembers set2
1) "b"
2) "a"
3) "g"
127.0.0.1:6379> sinter set set2
1) "b"
127.0.0.1:6379> sdiff set set2
1) "d"
2) "e"
3) "c"
127.0.0.1:6379> sunion set set2
1) "c"
2) "b"
3) "d"
4) "e"
5) "a"
6) "g"

Hash

Map集合,key-Map集合

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
# hset key field value
# 放入一个map
# hget key field
127.0.0.1:6379> hset hashmap name zhima
(integer) 1
127.0.0.1:6379> hget hashmap name
"zhima"

# 设置和取得多个键值对
# hmset key field name [field name..]
# hmget key field [field..]
127.0.0.1:6379> hmset user:1 name zhim age 10
OK
127.0.0.1:6379> hmget user:1 name age
1) "zhim"
2) "10"
# 使用hset更新键值对
127.0.0.1:6379> hset user:1 name zhima
(integer) 0
127.0.0.1:6379> hmget user:1 name age
1) "zhima"
2) "19"

# 取得所有的键值对
# hgetall key
127.0.0.1:6379> hgetall user:1
1) "name"
2) "zhima"
3) "age"
4) "19"

# 获取键值对个数
# hlen key
127.0.0.1:6379> hlen user:1
(integer) 2

# 删除键值对
# hdel key field
127.0.0.1:6379> hdel user:1 name
(integer) 1
127.0.0.1:6379> hgetall user:1
1) "age"
2) "19"

# 是否存在该键值对
# hexists key field
127.0.0.1:6379> hexists user:1 name
(integer) 1
127.0.0.1:6379> hexists user:1 unknown
(integer) 0

# 获得所有的键
# hkeys key
# 获得所有的值
# hvals key
127.0.0.1:6379> hkeys user:1
1) "name"
2) "age"
127.0.0.1:6379> hvals user:1
1) "zhima"
2) "19"

# 增加值
# hincrby key field increment
# !注意:!这里没有自减的方法,但是可以为increment设置负数来实现减
127.0.0.1:6379> hincrby user:1 name 1
(error) ERR hash value is not an integer
127.0.0.1:6379> hincrby user:1 age 2
(integer) 21
127.0.0.1:6379> hmset user:2 name lizhi age "19"
OK
127.0.0.1:6379> hgetall user:2
1) "name"
2) "lizhi"
3) "age"
4) "19"
127.0.0.1:6379> hincrby user:2 age 2
(integer) 21
127.0.0.1:6379> hincrby user:2 age -1
(integer) 20

# 如果不存在该字段,则添加该字段
# 如果存在,则不进行操作
# hsetnx key field value
127.0.0.1:6379> hsetnx user:1 name modified
(integer) 0
127.0.0.1:6379> hgetall user:1
1) "name"
2) "zhima"
3) "age"
4) "21"
127.0.0.1:6379> hsetnx user:1 address unknown
(integer) 1
127.0.0.1:6379> hgetall user:1
1) "name"
2) "zhima"
3) "age"
4) "21"
5) "address"
6) "unknown"

Hashmap适合存储对象

Zset(有序列表)

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
# 添加值 这个score相当于权重,用来排序
# zadd key [NX|XX] [CH] [INCR] score member [score member..]
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset 2 two 3 three
(integer) 2

# 正序输出
# zrange key start stop [withscores]
127.0.0.1:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
# 倒叙输出
# zrevrange key start stop [withscores]
127.0.0.1:6379> zrevrange salary 0 -1
1) "lizhi"
2) "xiaozhang"
3) "zhima"
# 携带权重输出
127.0.0.1:6379> zrange salary 0 -1 withscores
1) "zhima"
2) "1000"
3) "xiaozhang"
4) "1500"
5) "lizhi"
6) "2000"

# zrangebyscore key min max [withscores] [limit offset count]
# 获取score在min到max之间的元素,闭区间
127.0.0.1:6379> zrangebyscore salary 1000 1600
1) "zhima"
2) "xiaozhang"
127.0.0.1:6379> zrangebyscore salary -inf +inf
1) "zhima"
2) "xiaozhang"
3) "lizhi"
# zrevrangebyscore key max min [withscores] [limit offset count]
# 倒叙输出score在max到min之间的,闭区间,
# [limit offset count]是指定显示从offset开始的count个数据,包括offset所在的元素
127.0.0.1:6379> zrevrangebyscore salary 1600 1000
1) "xiaozhang"
2) "zhima"
127.0.0.1:6379> zadd salary 10 xiaoming 27 ziaohzhyang 19 zhima 25 lizhi
(integer) 4
127.0.0.1:6379> zrangebyscore salary 10 19
1) "xiaoming"
2) "zhima"
127.0.0.1:6379> zrangebyscore salary 10 25 withscores
1) "xiaoming"
2) "10"
3) "zhima"
4) "19"
5) "lizhi"
6) "25"
127.0.0.1:6379> zrangebyscore salary 10 25 limit 0 2
1) "xiaoming"
2) "zhima"

# 删除元素
127.0.0.1:6379> zrem salary xiaoming
(integer) 1

# 查看该集合的长度
# zcard key
127.0.0.1:6379> zcard salary
(integer) 3

# 查看符合[min,max]区间的元素个数
# zcount key min max
127.0.0.1:6379> zcount salary 10 19
(integer) 2

注:以上命令只是常用命令,更多命令可以在官网查看

英文官网地址:https://redis.io/

中文官网地址:http://www.redis.cn/

给作者买杯咖啡吧~~~