Redis基础

一.初始Redis

1.1SQL 和 NoSql的区别

1.1.1结构化和非结构化

(1) SQL关系性数据库

传统关系型数据库是结构化数据,每一张表都有严格的约束信息:字段名、字段数据类型、字段约束等等信息,插入的数据必须遵守这些约束

image-20221108150421251

(2) NoSql数据库

NoSql对数据库格式没有严格约束,往往形式松散,自由。

可以是key-value,可以是文档,或者图格式

image-20221108150842073

image-20221108150759880

image-20221108150824222

1.1.2关联和非关联

(1) 关系型数据库

image-20221108151050108

(2) 非关系型数据库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
id: 1,
name: "张三",
orders: [
{
id: 1,
item: {
id: 10, title: "荣耀6", price: 4999
}
},
{
id: 2,
item: {
id: 20, title: "小米11", price: 3999

}
}
]
}

1.1.3查询方式

image-20221108151404130

1.1.4 事务

传统关系型数据库能满足事务ACID的原则 ,而非关系型数据库往往不支持事务,或者不能严格保证ACID的特性,只能实现基本的一致性。

1.1.5总结

image-20221108154744967

1.2 认识Redis

特征:

  • 键值(key-value)型,value支持多种不同数据结构,功能丰富
  • 单线程,每个命令具备原子性
  • 低延迟,速度快(基于内存、IO多路复用、良好的编码)。
  • 支持数据持久化(定期将内存搬运到磁盘)
  • 支持主从集群、分片集群(数据拆分)(可以做读写分离,大大提高效率)
  • 支持多语言客户端

Redis的官方网站地址:RedisRedis Redis

1.3 Redis安装启动

Redis是基于C编写,所以需要先安装Redis所需的gcc依赖

1
yum install -y gcc 

如果有了就跳过

安装包上传到usr/local/src

image-20221109102716711

1
2
tar -zxvf redis-6.2.6.tar.gz 
1

cd到redis的目录:

1
2
cd redis-6.2.6/
1

编译和运行

1
2
make && make install
1

默认启动:

需要一直挂着页面

1
redis-server

后台启动:

前提是必须修改配置文件(/usr/local/src/redis-6.2.6/redis.conf)

(1) 先备份一份

1
cp redis.conf redis.conf.bak

(2) 修改

1
vi redis.conf

eg:修改密码为1234

image-20221109111623471

(3) 运行

1
2
3
cd /usr/local/src/redis-6.2.6
redis-server redis.conf
12

(4) 查看是否启动

1
2
ps -ef | grep redis
1

image-20221109111925399

(5) 停止redis -9:强制但是不安全

1
2
kill -9 进程号
1

开机自启

(1) 新建系统服务文件

1
2
vi /etc/systemd/system/redis.service
1

内容:

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=redis-server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/redis-server /usr/local/src/redis-6.2.6/redis.conf
PrivateTmp=true

[Install]
WantedBy=multi-user.target
1234567891011

(2) 重新加载系统服务

1
2
systemctl daemon-reload
1

(3)启动

1
2
systemctl start redis
1

(4)查看状态

1
2
systemctl status redis
1

image-20221109113222600

(5) 设置开机自启

1
2
systemctl enable redis
1

image-20221109113355471

1.4 Redis客户端

安装完成Redis,我们就可以操作Redis,实现数据的CRUD了。这需要用到Redis客户端,包括:

  • 命令行客户端
  • 图形化桌面客户端
  • 编程客户端
1.4.1.Redis命令行客户端

Redis安装完成后就自带了命令行客户端:redis-cli,使用方式如下:

1
redis-cli [options] [commonds]

redis-cli -h 192.168.200.131 -p 6379 -a 1234

其中常见的options有:

  • -h 127.0.0.1:指定要连接的redis节点的IP地址,默认是127.0.0.1
  • -p 6379:指定要连接的redis节点的端口,默认是6379
  • -a 123321:指定redis的访问密码

其中的commonds就是Redis的操作命令,例如:

  • ping:与redis服务端做心跳测试,服务端正常会返回pong

不指定commond时,会进入redis-cli的交互控制台:

image-20221109130629001

也可以先不写密码,后面来补充!

image-20221109130833848

1.4.2.图形化桌面客户端

GitHub上的大神编写了Redis的图形化桌面客户端,地址:https://github.com/uglide/RedisDesktopManager

不过该仓库提供的是RedisDesktopManager的源码,并未提供windows安装包。

在下面这个仓库可以找到安装包:https://github.com/lework/RedisDesktopManager-Windows/releases

resp.exe

image-20221109141759074

image-20221109142107511

二.Redis命令

0.通用命令

help @generic 查看所有的通用命令

image-20241021105219427

image-20241021105335724

生产过程中不建议用keys是因为它是单线程的,而这个行为是耗时的,会被阻塞很久耽误事情。

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
centos7_01_192.168.120.90:0>mset k1 v1 k2 v2 k3 v3 
"OK"
centos7_01_192.168.120.90:0>keys *
1) "k2"
2) "k1"
3) "k3"

#使用del
centos7_01_192.168.120.90:0>del k1 k2 k3 k4
"3"
centos7_01_192.168.120.90:0>keys *

centos7_01_192.168.120.90:0>mset name v1
"OK"
centos7_01_192.168.120.90:0>keys *
1) "name"

#使用exists
centos7_01_192.168.120.90:0>exists name
"1"
centos7_01_192.168.120.90:0>exists age
"0"

#使用expire和ttl
centos7_01_192.168.120.90:0>expire name 20
"1"
centos7_01_192.168.120.90:0>TTL name
"15"
centos7_01_192.168.120.90:0>TTL name
"14"
centos7_01_192.168.120.90:0>TTL name
"9"
centos7_01_192.168.120.90:0>TTL name
"4"
centos7_01_192.168.120.90:0>TTL name
"2"
centos7_01_192.168.120.90:0>TTL name
"1"
centos7_01_192.168.120.90:0>TTL name
"0"
centos7_01_192.168.120.90:0>TTL name
"-2"
centos7_01_192.168.120.90:0>TTL name
"-2"
centos7_01_192.168.120.90:0>TTL name
"-2"
centos7_01_192.168.120.90:0>TTL name
"-2"
centos7_01_192.168.120.90:0>TTL name
"-2"
# -2表示已经被删了
centos7_01_192.168.120.90:0>keys *

centos7_01_192.168.120.90:0>

#没有用expire设置有效期,那么-1表示的是永久有效
centos7_01_192.168.120.90:0>set name Kevin
"OK"
centos7_01_192.168.120.90:0>ttl name
"-1"
centos7_01_192.168.120.90:0>

expire设置存活周期,ttl查看剩余时间,不设置expire的话ttl为-1

1.String

image-20221109150526290

image-20221109150730084

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
#set 单个添加 值会被覆盖,所以是修改
centos7_01_192.168.120.90:0>set name Rose
"OK"
centos7_01_192.168.120.90:0>get name
"Rose"
centos7_01_192.168.120.90:0>set name Jack
"OK"
centos7_01_192.168.120.90:0>get name
"Jack"

#mset 批量添加
centos7_01_192.168.120.90:0>MSET k1 v1 k2 v2 k3 v3
"OK"
centos7_01_192.168.120.90:0>keys *
1) "name"
2) "k2"
3) "k1"
4) "k3"

centos7_01_192.168.120.90:0>MGET name k1 k2 k3
1) "Jack"
2) "v1"
3) "v2"
4) "v3"

#INCR
centos7_01_192.168.120.90:0>set age 18
"OK"
centos7_01_192.168.120.90:0>keys *
1) "k1"
2) "k2"
3) "age"
4) "k3"
5) "name"

centos7_01_192.168.120.90:0>INCR age
"19"
centos7_01_192.168.120.90:0>get age
"19"
centos7_01_192.168.120.90:0>INCR age
"20"
centos7_01_192.168.120.90:0>get age
"20"

#INCRBY 设置每次增长多少
#设置为负数就是自减了
centos7_01_192.168.120.90:0>INCRBY age 2
"22"
centos7_01_192.168.120.90:0>INCRBY age 2
"24"
centos7_01_192.168.120.90:0>INCRBY age 2
"26"
centos7_01_192.168.120.90:0>get age
"26"
centos7_01_192.168.120.90:0>INCRBY age -3
"23"
centos7_01_192.168.120.90:0>INCRBY age -3
"20"
centos7_01_192.168.120.90:0>get age
"20"

#setnx
centos7_01_192.168.120.90:0>setnx name lli
"0"
centos7_01_192.168.120.90:0>get name
"Jack"
centos7_01_192.168.120.90:0>setnx name1 kevin
"1"
centos7_01_192.168.120.90:0>get name
"Jack"
centos7_01_192.168.120.90:0>get name1
"kevin"
#set和nx是组合的,可以分开可以合起来
centos7_01_192.168.120.90:0>set name lucy nx
null
centos7_01_192.168.120.90:0>get name
"Jack"

#setex set和expire的组合 添加并设置有效期
centos7_01_192.168.120.90:0>setex name 10 jack
"OK"
centos7_01_192.168.120.90:0>ttl name
"6"
centos7_01_192.168.120.90:0>ttl name
"3"
centos7_01_192.168.120.90:0>ttl name
"2"
centos7_01_192.168.120.90:0>ttl name
"1"
centos7_01_192.168.120.90:0>ttl name
"0"
centos7_01_192.168.120.90:0>ttl name
"-2"
centos7_01_192.168.120.90:0>get name
null

#set和ex分开的
centos7_01_192.168.120.90:0>set name Jack ex 10
"OK"
centos7_01_192.168.120.90:0>get name
"Jack"
centos7_01_192.168.120.90:0>ttl name
"4"
centos7_01_192.168.120.90:0>ttl name
"3"
centos7_01_192.168.120.90:0>ttl name
"-2"
centos7_01_192.168.120.90:0>get name
null

2.Key的层级格式

推荐用:

项目名:业务名:类型:id

这种形式去存储

image-20221109152434329

如果Value是一个Java对象,例如一个User对象,则可以将对象序列化为JSON字符串后存储:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
centos7_01_192.168.120.90:0>set heima:user:1 '{"id":1,"name": "Jack","age": 21}'
"OK"
centos7_01_192.168.120.90:0>set heima:user:2 '{"id":2,"name": "Rose","age": 20}'
"OK"
centos7_01_192.168.120.90:0>set heima:product:1 '{"id":1, "name": "小米11", "price": 4999}'
"OK"
centos7_01_192.168.120.90:0>set heima:product:2 '{"id":2, "name": "iphone", "price": 9809}'
"OK"
centos7_01_192.168.120.90:0>keys *
1) "heima:product:2"
2) "age"
3) "k2"
4) "k1"
5) "heima:product:1"
6) "heima:user:2"
7) "k3"
8) "name1"
9) "heima:user:1"

一旦我们向redis采用这样的方式存储,那么在可视化界面中,redis会以层级结构来进行存储,形成类似于这样的结构,更加方便Redis获取数据,避免了名字冲突

image-20241021113335832

3.Hash

本身Redis就是一个key-value的结构,而hash的value还是一个key-value的结构

image-20221109155158922

image-20221109155235999

1
2
3
4
5
6
7
#HSET 用法和set一样的,和string不同的是不止要给key还要给field
centos7_01_192.168.120.90:0>HSET heima:user:3 name Lucy
"1"
centos7_01_192.168.120.90:0>HSET heima:user:3 age 21
"1"
centos7_01_192.168.120.90:0>HSET heima:user:3 age 17
"0"

image-20241021184809896

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
#HMSET
centos7_01_192.168.120.90:0>HMSET heima:user:4 name hanmeimei
"OK"
centos7_01_192.168.120.90:0>HMSET hiema:user:4 name lilei age 20 sex man
"OK"
#HMGET
centos7_01_192.168.120.90:0>HMGET hiema:user:4 name age sex
1) "lilei"
2) "20"
3) "man"
#HGETALL
centos7_01_192.168.120.90:0>HGETALL hiema:user:4
1) "name"
2) "lilei"
3) "age"
4) "20"
5) "sex"
6) "man"

#HKEYS HVALS
centos7_01_192.168.120.90:0>HKEYS hiema:user:4
1) "name"
2) "age"
3) "sex"
centos7_01_192.168.120.90:0>HVALS hiema:user:4
1) "lilei"
2) "20"
3) "man"
#HINCRBY
centos7_01_192.168.120.90:0>HINCRBY hiema:user:4 age 2
"22"
#HSET和nx 原来有的改不了,原来没的创建
centos7_01_192.168.120.90:0>HSETNX hiema:user:4 sex women
"0"
centos7_01_192.168.120.90:0>HSETNX hiema:user:3 sex women
"1"
centos7_01_192.168.120.90:0>HGETALL hiema:user:3
1) "sex"
2) "women"

4.List

image-20221109162502511

image-20221109163700818

BLPOP 是阻塞等待,当前进程阻塞,等待另外一个进程输入结果

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
#LPUSH
centos7_01_192.168.120.90:0>LPUSH users 1 2 3
"3"
#RPUSH
centos7_01_192.168.120.90:0>RPUSH users 456
"4"
centos7_01_192.168.120.90:0>RPUSH users 4 5 6
"7"
#LPOP 直接移除
centos7_01_192.168.120.90:0>LPOP users 1
1) "3"

#RPOP
centos7_01_192.168.120.90:0>RPOP users 1
1) "6"

#LRANGE
centos7_01_192.168.120.90:0>LRANGE users 1 2
1) "1"
2) "456"

#BLPOP 有的话弹出,没有的话等待指定时间,这里是100秒
centos7_01_192.168.120.90:0>BLPOP user2 100
1) "user2"
2) "Jack"

5.Set

image-20221109164228655

image-20241021194250280

单个集合的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#SADD添加
centos7_01_192.168.120.90:0>SADD s1 a b c
"3"
#SMEMBERS 查看所有
centos7_01_192.168.120.90:0>SMEMBERS s1
1) "b"
2) "c"
3) "a"
# SREM 删除
centos7_01_192.168.120.90:0>SREM s1 a
"1"
#SISMEMBER 是否存在
centos7_01_192.168.120.90:0>SISMEMBER s1 a
"0"
centos7_01_192.168.120.90:0>SISMEMBER s1 b
"1"
#SCARD 计数
centos7_01_192.168.120.90:0>SCARD s1
"2"

image-20221109165305468

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
centos7_01_192.168.120.90:0>sadd zs lisi wangwu zhaoliu
"3"
centos7_01_192.168.120.90:0>sadd ls wangwu mazi ergou
"3"
centos7_01_192.168.120.90:0>sinter zs ls
1) "wangwu"

centos7_01_192.168.120.90:0>sdiff zs ls
1) "lisi"
2) "zhaoliu"

centos7_01_192.168.120.90:0>sunion zs ls
1) "wangwu"
2) "ergou"
3) "lisi"
4) "zhaoliu"
5) "mazi"

centos7_01_192.168.120.90:0>sismember zs lisi
"1"
centos7_01_192.168.120.90:0>sismember ls zhangsan
"0"
centos7_01_192.168.120.90:0>sismember ls zhangsan
"0"
centos7_01_192.168.120.90:0>srem zs lisi
"1"

6.SortedSet

image-20221109165841177

每个元素都带上分数,所以才能实现排序

image-20241021195555459

image-20221109170635790

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
#ZADD 添加
centos7_01_192.168.120.90:0>zadd stus 85 jack 89 Lucy 82 Rose 95 Tom 78 Jerry 92 Amy 76 Miles
"7"
#ZREM 删除
centos7_01_192.168.120.90:0>zrem stus Tom
"1"
#ZSCORE
centos7_01_192.168.120.90:0>zscore stus Amy
"92"
#ZRANK 这个是从0开始数的排名 升序
centos7_01_192.168.120.90:0>zrank stus Rose
"2"
#ZREVRANK 降序
centos7_01_192.168.120.90:0>zrevrank stus Rose
"3"
#ZCOUNT 0-80分
centos7_01_192.168.120.90:0>zcount stus 0 80
"2"
#ZINCRBY 自增,一个加分操作
centos7_01_192.168.120.90:0>zincrby stus 2 Amy
"94"
#这是后三名,因为原来的是按照成绩升序排的
centos7_01_192.168.120.90:0>zrange stus 0 2
1) "Miles"
2) "Jerry"
3) "Rose"
#这是前三名
centos7_01_192.168.120.90:0>zrevrange stus 0 2
1) "Amy"
2) "Lucy"
3) "jack"
#80以下的人
centos7_01_192.168.120.90:0>zrangebyscore stus 0 80
1) "Miles"
2) "Jerry"