自学内容网 自学内容网

2024.11.6-Redis的事务与持久化

6.1 Redis的事务

6.1.1 事务的简介

MULTI、EXEC、DISCARD和WATCH 是 Redis 事务相关的命令。Redis的事务是将一系列待执行的指令存到一个Queue中,并使用exec执行事务。
​
--1. Redis事务是一个独立的隔离机制:事务中的所有命令都会序列化到queue、并按顺序地执行queue里的指令。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
​
​
multi: 用于开启事务,将待执行的命令放入到队列中
exec命令:负责触发并执行事务中的所有命令:
discard:  用于取消组队。
watch:监听

6.1.2 事务的基本操作

qianfeng01:6379> multi    #  开启事务
OK
qianfeng01:6379> set k2 v2    #向队列中添加要执行的指令
QUEUED
qianfeng01:6379> set k3 v3
QUEUED
qianfeng01:6379> set k4 v4
QUEUED
qianfeng01:6379> exec     #  执行事务,也就是执行队列中的指令 ,一旦执行了exec指令,表示事务结束
1) OK
2) OK
3) OK
qianfeng01:6379> keys *   # 查看
1) "k3"
2) "k4"
3) "k2"
4) "k1"
​
qianfeng01:6379> multi     #开启事务
OK
qianfeng01:6379> set k11 v11
QUEUED
qianfeng01:6379> set k12 v12
QUEUED
qianfeng01:6379> discard   #退出组队, 也可以理解为退出事务,即结束事务
OK
qianfeng01:6379> exec      #因为没有事务,所以执行报错。
(error) ERR EXEC without MULTI

6.1.3 事务出错的情况

错误情况1:
    当开启事务,组队出错,  调用exec时,直接报错,不执行。
错误情况2:
    当开启事务,组队没问题, exec时错误,不影响后续的指令的执行。

参考案例:

127.0.0.1:6379> multi    <==开启事务
OK
127.0.0.1:6379> set a1 zhangsan
QUEUED
127.0.0.1:6379> set a2 lisi
QUEUED
127.0.0.1:6379> set a3     <==语法错误,组队出错
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> set a4 zhaoliu
QUEUED
127.0.0.1:6379> exec      <==调用exec时,直接报错,不执行。
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> keys *    <== 没有a1,a2,a4
1) "n4"
2) "n3"
3) "n2"
4) "n1"
127.0.0.1:6379> multi      <==开启事务
OK
127.0.0.1:6379> set a1 zhangsan
QUEUED
127.0.0.1:6379> INCR a1     <==语法没报错,但是a1对应的value不是整形,不能+1
QUEUED
127.0.0.1:6379> set a2 lisi
QUEUED
127.0.0.1:6379> exec    <==调用exec时,有错误,但是不影响后续的指令的执行。
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
127.0.0.1:6379> keys *   <== 有a1,a2
1) "a1"
2) "n3"
3) "n2"
4) "a2"
5) "n4"
6) "n1"
​

6.1.4 悲观锁和乐观锁

悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,当使用者每次在使用临界资源的时候都认为临界资源可能正在被其他人修改,所以每次在使用该临界资源时都要上锁,这样的话,当别人想用这个临界资源时,就会被阻塞,直到正在使用的人释放了锁,别人获取到锁,别人才可以上锁,才继续干活。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
​
第一个线程:
      int balance= 5000  v1.0
      .....
      ....
      ...
      balance-=4000      v1.1
​
第二个线程:
      int balance= 5000 v1.0
      .....
      ....
      ...
      balance-=3000    v1.2      check-and-set机制(乐观锁)
​
​
乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新过这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
​
两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下,即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果经常产生冲突,上层应用会不断的进行retry,这样反倒是降低了性能,所以这种情况下用悲观锁就比较合适。

6.1.5 乐观锁的演示

watch key [key]   作用:监听key
​
开启第一个窗口:
    watch balance
    multi
    decrby balance 4000
​
开启第二个窗口:
    watch balance
    multi
    decrby balance 3000
​
然后两个窗口执行事务,会发现,一个执行成功,另一个执行失败(nil)

6.1.6 总结

1. 单独的隔离操作 
    事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 
2. 没有隔离级别的概念 
    队列中的命令没有提交之前都不会实际被执行,因为事务提交前任何指令都不会被实际执行
3. 不保证原子性 
    事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚 
    
redis事务+乐观锁的应用场景:商品秒杀、抢票等

6.2 Redis的持久化

redis虽然是基于内存的,但是也可以选择性的将数据持久化到磁盘上的,以保证数据的安全性(万一宕机了,岂不是损失大了)。而redis的持久化方式有两种,一种是RDB方式,一种是AOF方式
​
redis4.0.14 默认是RDB持久化机制

6.2.1 RDB持久化

1)原理
RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的数据进行快照并持久化到硬盘。

 

 

2)参数
# 设置保存机制,    第二个参数表示保存的时间范围,第三个参数表示在时间段内发生了多少次key的更改
save 900 1
save 300 10
save 60 10000
​
#指定存储位置,可以写绝对路径
dir ./
#指定存储的文件名
dbfilename dump.rdb   
​
# 当save失败时,则停止写操作
stop-writes-on-bgsave-error yes
# 是否开启压缩,算法LZF
rdbcompression yes
# 是否开启检查机制,比较消耗性能,不建议开启
rdbchecksum yes
3)如何触发RDB快照
# 满足以下配置时会触发
save 900 1
save 300 10
save 60 10000
​
# 主动调用save指令    前台执行持久化操作, 会影响前台做其他写操作, 是一个同步指令
# 主动调用bgsave指令   开启持久化操作,后台执行,不影响前台执行,  是一个异步指令
4)如何禁用RDB快照
方式1:注释掉所有的save行
方式2:save "" 
5)如何备份数据
只需要将相关的dump.rdb文件保存到你喜欢的目录下。如果宕机了,就使用一个新的机器加载这个文件即可。
注意:只需要在文件所在的目录下启动服务,会主动加载对应名字的rdb文件
6)小贴士
这种方式,如果宕机了,会丢失上次快照到宕机时这个时间段的新数据

6.2.2 AOF持久化

1)原理
aof的全称:append only file,  保存的是客户端的写操作(set)
aof是默认不开启的,需要手动设置,设置也非常简单,只需要将对应的no改为yes即可.相应的文件就会保存到和dump.rdb同一个目录下了(dir参数指定的目录)。

2)参数
# 开启aof持久化机制
        appendonly yes
# 指定生成的文件名
        appendfilename "appendonly.aof"
​
# aof的持久化策略: 只能选择一个,默认的是每秒
# 只要发生set操作,就持久化
        #appendfsync always
# 每秒持久化一次
        appendfsync everysec
# 关闭自动同步策略,改为手动
#appendfsync no
​
#重写机制的条件,100指的是当文件大于min-size的100%,即128mb的时候,开启重写机制
        auto-aof-rewrite-percentage 100
#指定重写机制的最小字节数
        auto-aof-rewrite-min-size 64mb
3)aof文件的修复
redis-check-aof --fix appendonly.aof

6.2.3 总结

1. 当两种持久化机制都开启时,redis服务会默认加载aof的文件,而不加载rdb文件。

2. RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.

3. AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保存每次写的操作到文件末尾.

4. Redis还能对AOF文件进行后台重写,使得AOF文件的体积不至于过大.   set k1 v1  set k1 v2  重写后只保存set k1 v2

5. 如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化方式.

6. 你也可以同时开启两种持久化方式, 在这种情况下, 当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.

原文地址:https://blog.csdn.net/weixin_64513190/article/details/143424075

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!