1.事务机制
1.1 事务介绍
redis是支持事务的。
举一个经典的例子:转账。
A向B汇款,那么A账户会扣钱
B账户会加钱
这两个步骤一定是在一个事务中的,要么都成功,要么都失败。
redis事务是基于队列实现的,创建一个事务队列,然后将事务操作都放入到对列中,最后依次执行。
1.2 事务的处理机制
在redis中,如果开启了事务,某一条命令执行出错了,此时事务会怎么处理呢?你可能会说了,要么都成功,要么都失败,有一个失败,那就全失败了呗。
这么想不能算错,但是redis对于命令执行错误有两种解决方式:
- 语法错误(编译)
- 执行错误(运行)
1.2.1 语法错误
也就是执行命令的语法不对:
#开启事务
multi
#命令
set name zhangsan
set age
seterror sex 1
#执行事务
exec
1
2
3
4
5
6
7
8
整个事务中,只有一条指令是正确的,当执行exec后,会直接返回错误,正确的命令也不会执行。
1.2.2 执行错误
命令在执行的发生错误
#开启事务
multi
#命令
set lesson java
rpush lesson eureka feign nacos
set lesson redis
#执行事务
exec
#获取数据
get lesson
1
2
3
4
5
6
7
8
9
10
上面的事务中,语法是没有问题的,所以在运行之前redis是无法发现错误的,但是在执行的时候出现了错误,因此只会错误的命令不执行,而正确的命令会执行。
1.3 springboot整合事务操作
1)修改redisconfig配置类,开启事务控制
//开启redis事务控制
redisTemplate.setEnableTransactionSupport(true);
1
2
2)自定义方法,测试事务效果
@Test
@Transactional(rollbackFor = Exception.class)
public void multiTest(){
//开启事务
redisTemplate.multi();
try{
redisTemplate.opsForValue().set("lesson","java");
redisTemplate.opsForSet().add("lesson","eureka","feign","gateway");
redisTemplate.opsForValue().set("lesson","redis");
System.out.println(redisTemplate.opsForValue().get("lesson"));
}catch (Exception e){
//回滚
System.out.println("出现异常");
redisTemplate.discard();
}finally {
redisTemplate.exec();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2. 持久化机制
2.1 场景分析
redis是将数据存放到内存中的,一旦服务器宕机重启,内存中的数据就会消失,为了避免这种事情发生,redis提供了持久化机制,将内存中的数据存放到磁盘上,避免数据意外丢失。
redis提供了两种持久化机制,AOF和RDB。
2.2.RDB快照
2.2.1 概述
RDB是redis默认的持久化机制,基于快照的思想,当符合一定条件(自动或者手动)时,redis就会将这一刻的内存数据进行快照并保存到磁盘上,产生一个经过压缩的二进制文件,后缀名.rdb的文件
因为RDB文件是保存在磁盘上的,因此即使Redis进程退出,甚至服务器宕机重启。只要RDB文件存在,就可以利用它来还原Redis数据。
2.2.2 RDB触发条件
在redis.conf文件中配置一些默认的触发机制
save "" # 不使用RDB存储 不能主从
save 3600 1 #表示一个小时内至少一个键被更改则进行快照
save 300 100 #表示5分钟(300秒)内至少100个键被更改则进行快照。
save 60 10000 #表示1分钟内至少10000个键被更改则进行快照。
1
2
3
4
手动执行save或者bgsave命令
在redis客户端手动执行save或者bgsave命令,手动触发RDB快照
#执行save命令(同步执行)
save
#执行bgsave命令(异步子线程执行)
bgsave
1
2
3
4
5
这两个命令都可以触发快照,那么他们两个的区别是什么呢?
save:同步处理,阻塞redis服务进程,服务器不会执行任何命令,直到RDB文件保存完毕。
bgsave:会fork一个和主线程一致的子线程复制操作RDB文件,不会阻塞redis服务进程。
redis默认使用的是bgsave来保存快照数据
2.2.3 优缺点
优点:
基于二进制文件完成数据备份,占用空间少,便于文件传输
能够自定义规则,根据redis繁忙状态进行数据备份
缺点:
无法保证数据的完整性,会丢失最后一次快照后的所有数据
bgsave每次执行都会阻塞redis服务进程创建子线程,频繁执行影响系统的吞吐率
2.3.AOF
2.3.1 概述
RDB方式会出现数据丢失的问题,对于这个问题,可以通过Redis中另外一种持久化方式解决:AOF。
AOF 是reids提供的另外一种持久化方式,与RDB快照记录数据不同的是,当开启AOF持久化后,redis会将客户端发送的所有更改数据的命令记录到磁盘的AOF文件中,这样的话,当redis重启后,通过读取AOF文件,按顺序获取记录的数据修改命令,即可完成数据的恢复。
举个例子,对Redis执行三条写命令:
set name czy
hset cart shop nike
sadd lesson java python hadoop
1
2
3
4
5
RDB会将name,cart,lesson三个键值对数据进行保存,而AOF会将set,hset,sadd三个命令保存到AOF文件中。
2.3.2 基础使用
AOF方式需要手动开启,修改redis.conf
# 是否开启AOF,默认为no
appendonly yes
#设置AOF文件名称
appendfilename appendonly.aof
1
2
3
4
5
当开启了AOF机制之后,Redis何时向AOF文件中记录内容呢?
对于AOF的触发方式有三种:always,everysec,no。默认使用everysec,可以通过redis.conf中的appendfsync属性进行配置。
开启AOF后,重启redis,进入redis客户端执行多条写命令,这些命令会被保存到appendonly.aof文件中。
set name zhangsan
set age 18
set sex male
get name
get age
get sex
1
2
3
4
5
6
此时查看redis/data目录,会新产生一个appendonly.aof文件。 查看文件内容
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$8
zhangsan
*3
$3
set
$3
age
$2
18
*3
$3
set
$3
sex
$4
male
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
通过文件查看,可以看到,在aof文件中,记录了对redis操作的所有写命令,读命令并不会记录。
2.3.3 执行原理
AOF功能实现的真个执行过程可以分为三个部分:命令追加,文件写入,文件同步。
客户端向redis发送写命令。
Redis将接收到的写命令保存到缓冲文件中的末尾,这个过程是命令追加。
redis将缓冲区文件内容写入到AOF文件中,这个过程叫文件写入。
redis根据策略将AOF文件保存到磁盘,这个过程叫文件同步。
何时将AOF文件同步到磁盘的策略依据就是redis.conf文件中appendfsync属性值:always,everysec,no
always:每次执行写命令都会将缓冲区文件的内容写入到AOF文件中,并将AOF文件同步到磁盘。该效率最低,安全性最高。
ererysec:每次执行写命令都会将缓冲区文件的内容写入到AOF文件中,并且每隔一秒会有子线程将AOF文件同步到磁盘,该方式兼备了效率与安全,即使出现宕机重启,也只是丢失不超过两秒的数据。
no:每次执行写命令都会将缓冲区文件的内容写入到AOF文件中,但并不会将AOF文件进行同步磁盘,同步操作交由操作系统完成(每30秒一次),该方式最快,但是最不安全。
模式 aof_buf写入到AOF是否阻塞 AOF文件写入磁盘是否阻塞 宕机重启时丢失的数据量 效率 安全
always 阻塞 阻塞 最多只丢失一个命令的数据 低 高
everysec 阻塞 不阻塞 不超过两秒的数据 中 中
no 阻塞 阻塞 操作系统最后一次对AOF写入磁盘的数据 高 低
2.3.4 AOF重写优化
2.3.4.1 概述
AOF会将对redis操作的所有写命令都记录下来,随着服务器的运行,AOF文件内保存的内容会越来越多,这样就会造成两个比较严重的问题:占用大量内存空间,数据还原花费的时间多。
举个栗子:
sadd lessons java
sadd lessons python go
sadd lessons hive
sadd lessons hadoop rocketmq
sadd lessons redis
1
2
3
4
5
当这些命令执行玩,AOF文件中记录5条命令。但是实际生产环境下,写命令会出现非常多,文件的体积会非常大。
为了解决AOF文件巨大的问题,Redis提供了AOF重写机制,当AOF文件体积超过阈值,就会触发AOF重写机制,Redis开启子线程创建一个新的AOF文件替代原来的AOF文件,新的AOF文件不会包含任何浪费空间的冗余命令,只存在恢复当前redis状态的最小命令集合。
2.3.4.2 触发配置
那么AOF文件达到多大时,会将其进行重写呢?对于重写阈值的配置,可以通过修改redis.conf进行配置。
#当前aof文件大小超过上一次aof文件大小的百分之多少时进行重写。如果之前没有重写过,以
启动时aof文件大小为准
auto-aof-rewrite-percentage 100
#限制允许重写最小aof文件大小,也就是文件大小小于64mb的时候,不需要进行优化
auto-aof-rewrite-min-size 64mb
1
2
3
4
5
6
除了让redis自动执行重写外,也可以手动让其进行执行:bgrewriteaof
2.4.RDB与AOF对比
RDB是默认开启的,AOF需要手动开启。
RDB性能优于AOF。
AOF安全性由于RDB。
AOF优先级高于RDB.
RDB存储某个时刻的数据快照,AOF存储写命令。
RDB在配置触发状态会丢失最后一次快照以后更改的所有数据;AOF默认使用everysec,每秒保存一次,最多丢失两秒以内的数据。
3.高可用-主从复制
3.1.问题概述
通过持久化机制的学习,可以发现,不管是RDB还是AOF,都不能百分百的避免数据的丢失。关键是现在只有一台服务器,持久化数据都是保存在这台服务器上,假设这台服务器的磁盘损坏,数据仍然会全部丢失。 那这个问题该怎么解决呢?
那我们想一下,现在所有持久化数据只是保存在一台服务器上,能不能让它们同时保存在多台服务器上,这样即使一台服务器出现问题,仍然可以从其他服务器同步数据。
这样就需要当一台服务器中数据更新后,可以自动的将更新的数据同步到其他服务器上, 这就是所谓的复制。
3.2.复制搭建&使用
关键步骤:
(1)安装依赖环境及安装Redis
tar -zxvf redis压缩包
#安装gcc
yum install -y gcc-c++ autoconf automake
#centos7 默认的 gcc 默认是4.8.5,版本小于 5.3 无法编译,需要先安装gcc新版才能编译
gcc -v
#升级新版gcc,配置永久生效
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
scl enable devtoolset-9 bash
echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
#将Redis的源码包上传 解压 并且 编译redis
cd redis-6.2.4
make
#安装到指定目录
mkdir -p /usr/local/redis
make PREFIX=/usr/local/redis install
sysctl vm.overcommit_memory=1
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
(2)创建目录
#日志 /usr/local/redis/log
#数据 /usr/local/redis/data
#配置文件 /usr/local/redis/conf
mkdir /usr/local/redis/logs -p
mkdir /usr/local/redis/data -p
mkdir /usr/local/redis/conf -p
1
2
3
4
5
6
将资料中配置文件复制到 conf 文件夹下
(3)启动Redis master节点
————————————————
版权声明:本文为CSDN博主「小程同学哦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45891099/article/details/125901587