一、Redis 事务
1.1 事务本质
一组命令的集合
1.2 数据库事务与redis事务
1.2.1 数据库事务
数据库事务通过ACID(原子性、一致性、隔离性、持久性)来保证。
数据库中除查询操作以外,插入(Insert)、删除(Delete)和更新(Update)这三种操作都会对数据造成影响,因为事务处理能够保证一系列操作可以完全地执行或者完全不执行,因此在一个事务被提交以后,该事务中的任何一条SQL语句在被执行的时候,都会生成一条撤销日志(Undo Log)。
1.2.2 Redis事务
redis事务提供了一种“将多个命令打包, 然后一次性、按顺序地执行”的机制, 并且事务在执行的期间不会主动中断 —— 服务器在执行完事务中的所有命令之后, 才会继续处理其他客户端的其他命令。
Redis中一个事务从开始到执行会经历开始事务(muiti)、命令入队和执行事务(exec)三个阶段,事务中的命令在加入时都没有被执行,直到提交时才会开始执行(Exec)一次性完成。
1.2.2.1 两种错误不同处理方式
1)代码语法错误(编译时异常)
发生代码语法错误时,所有命令都不执行。
2)代码逻辑错误(运行时错误)
发生代码逻辑错误时,其他命令可以正常执行 (该点不保证事务的原子性)
为什么redis不支持回滚来保证原子性
1.2.2.2 这种做法的优点:
- Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
- 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。
鉴于没有任何机制能避免程序员自己造成的错误, 并且这类错误通常不会在生产环境中出现, 所以 Redis 选择了更简单、更快速的无回滚方式来处理事务。
1.3 事务监控
redis使用watch key监控指定数据,相当于加乐观锁
watch保证事务只能在所有被监视键都没有被修改的前提下执行, 如果这个前提不能满足的话,事务就不会被执行。
watch执行流程:
二、数据持久化
Redis是一种内存型数据库,一旦服务器进程退出,数据库的数据就会丢失,为了解决这个问题Redis供了两种持久化的方案,将内存中的数据保存到磁盘中,避免数据的丢失两种持久化方式:快照(RDB文件)和追加式文件(AOF文件),下面分别为大家介绍两种方式的原理。
- RDB持久化方式会在一个特定的间隔保存那个时间点的数据快照。
- AOF持久化方式则会记录每一个服务器收到的写操作。在服务启动时,这些记录的操作会逐条执行从而重建出原来的数据。写操作命令记录的格式跟Redis协议一致,以追加的方式进行保存。
- Redis的持久化是可以禁用的,就是说你可以让数据的生命周期只存在于服务器的运行时间里。
- 两种方式的持久化是可以同时存在的,但是当Redis重启时,AOF文件会被优先用于重建数据。
2.1 RDB持久化
RDB持久化产生的文件是一个经过压缩的二进制文件,这个文件可以被保存到硬盘中,可以通过这个文件还原数据库的状态,它可以手动执行,也可以在redis.conf配置文件中配置,定时执行。
2.1.1 工作原理
在进行RDB时,redis的主进程不会做io操作,会fork一个子进程来完成该操作:
1)Redis 调用forks。同时拥有父进程和子进程。
2)子进程将数据集写入到一个临时 RDB 文件中。
3)当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。
这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益(因为是使用子进程进行写操作,而父进程依然可以接收来自客户端的请求)
2.1.2 触发机制
在Redis中RDB持久化的触发分为两种:自己手动触发与自动触发。
2.1.2.1 手动触发
1)save
save命令是同步的命令,会占用主进程,会造成阻塞,阻塞所有客户端的请求
2)bgsave
bgsave是异步进行,进行持久化的时候,redis还可以将继续响应客户端请求
bgsave和save对比:
命令 | save | bgsave |
IO类型 | 同步 | 异步 |
阻塞 | 是 | 是(阻塞发生在fock(),通常非常快) |
复杂度 | O(n) | O(n) |
优点 | 不会消耗额外的内存 | 不阻塞客户端命令 |
缺点 | 阻塞客户端命令 | 需要fock子进程,消耗内存 |
2.1.2.2 自动触发
触发条件:
save自动触发配置,见下面配置,满足m秒内修改n次key,触发rdb
# 时间策略 save m n m秒内修改n次key,触发rdb
save 900 1
save 300 10
save 60 10000
# 文件名称
dbfilename dump.rdb
# 文件保存路径
dir /home/work/app/redis/data/
# 如果持久化出错,主进程是否停止写入
stop-writes-on-bgsave-error yes
# 是否压缩
rdbcompression yes
# 导入时是否检查
rdbchecksum yes
1)从节点全量复制时,主节点发送rdb文件给从节点完成复制操作,主节点会触发bgsave命令;
2)执行flushall命令,会触发rdb
3)退出redis,且没有开启aof时
2.1.3 RDB优缺点
2.1.3.1 优点:
1)RDB 的内容为二进制的数据,占用内存更小,更紧凑,更适合做为备份文件;
2)RDB 对灾难恢复非常有用,它是一个紧凑的文件,可以更快的传输到远程服务器进行 Redis 服务恢复;
3)RDB 可以更大程度的提高 Redis 的运行速度,因为每次持久化时 Redis 主进程都会 fork() 一个子进程,进行数据持久化到磁盘,Redis 主进程并不会执行磁盘 I/O 等操作;
4)与 AOF 格式的文件相比,RDB 文件可以更快的重启。
2.1.3.2 缺点:
1)因为 RDB 只能保存某个时间间隔的数据,如果中途 Redis 服务被意外终止了,则会丢失一段时间内的 Redis 数据。
2)RDB 需要经常 fork() 才能使用子进程将其持久化在磁盘上。如果数据集很大,fork() 可能很耗时,并且如果数据集很大且 CPU 性能不佳,则可能导致 Redis 停止为客户端服务几毫秒甚至一秒钟。
2.2 AOF持久化
以日志的形式来记录每个写的操作,将Redis执行过的所有指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
2.2.1 AOF配置项
# 默认不开启aof 而是使用rdb的方式
appendonly no
# 默认文件名
appendfilename "appendonly.aof"
# 每次修改都会sync 消耗性能
# appendfsync always
# 每秒执行一次 sync 可能会丢失这一秒的数据
appendfsync everysec
# 不执行 sync ,这时候操作系统自己同步数据,速度最快
# appendfsync no
AOF的整个流程大体来看可以分为两步,一步是命令的实时写入(如果是appendfsync everysec 配置,会有1s损耗),第二步是对aof文件的重写。
2.2.2 AOF 重写机制
随着Redis的运行,AOF的日志会越来越长,如果实例宕机重启,那么重放整个AOF将会变得十分耗时,而在日志记录中,又有很多无意义的记录,比如我现在将一个数据 incr一千次,那么就不需要去记录这1000次修改,只需要记录最后的值即可。所以就需要进行 AOF 重写。
Redis 提供了bgrewriteaof指令用于对AOF日志进行重写,该指令运行时会开辟一个子进程对内存进行遍历,然后将其转换为一系列的 Redis 的操作指令,再序列化到一个日志文件中。完成后再替换原有的AOF文件,至此完成。
同样的也可以在redis.config中对重写机制的触发进行配置:
通过将no-appendfsync-on-rewrite设置为yes,开启重写机制;auto-aof-rewrite-percentage 100意为比上次从写后文件大小增长了100%再次触发重写;
auto-aof-rewrite-min-size 64mb意为当文件至少要达到64mb才会触发制动重写。
2.2.3 触发方式
在Redis中AOF持久化的触发也分为两种:自己手动触发与自动触发。
2.2.3.1 手动触发
bgrewriteaof
2.2.3.2 自动触发
就是根据配置规则来触发,当然自动触发的整体时间还跟Redis的定时任务频率有关系。
2.2.4 AOF的优缺点
2.2.4.1 优点
1)数据安全
aof 持久化可以配置 appendfsync 属性,有 always,每进行一次 命令操作就记录到 aof 文件中一次。
2)解决数据一致性问题。
通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
3)AOF 机制的 rewrite 模式。
AOF 文件没被 rewrite 之前(文件过大时会对命令 进行合并重写),可以删除其中的某些命令(比如误操作的 flushall))
2.2.4.2 缺点
1)AOF 文件比 RDB 文件大,且恢复速度慢。
2)数据集大的时候,比 rdb 启动效率低。
2.3 rdb与aof对比
比较项 | RDB | AOF |
启动优先级 | 低 | 高 |
体积 | 小 | 大 |
恢复速度 | 快 | 慢 |
数据安全性 | 性丢数据 | 根据策略决定 |
2.4 总结
RDB基于快照方式在一个特定的间隔保存那个时间点的数据,备份数据相对较小,恢复速度较块,但是可能会发生数据丢失;AOF持久化方式则会记录每一个服务器收到的写操作,备份文件体积较大,恢复速度较慢,但是这种方式制定一定的策略,不会丢失数据,相对来说数据安全性要比RDB高。在真实的企业生产环境中,Redis数据备份策略,一般是同时开启RDB和AOF两种备份方式,尽可能提高企业安全性的同时,也可以针对某个时间点基于数据快照快速恢复数据。