中国建设电工立网站,优秀网页欣赏,企业网站不足,动画制作专业对于Redis中间件来说#xff0c;一般是作为内存型数据库或者缓存出现的。但是由于其数据是在内存中#xff0c;因此当Redis所在的主机宕机之后#xff0c;数据就会消失#xff0c;再次重启之后#xff0c;没有任何数据。这对于生产环境来说#xff0c;是属于P0级别的灾难…对于Redis中间件来说一般是作为内存型数据库或者缓存出现的。但是由于其数据是在内存中因此当Redis所在的主机宕机之后数据就会消失再次重启之后没有任何数据。这对于生产环境来说是属于P0级别的灾难了。
因此对于Redis来说不仅要将数据存在内存中还要将数据持久化到硬盘上。这样当Redis重启之后可以通过硬盘中的数据来恢复内存中的数据。如果Redis是作为内存数据库的话那么客户端就可以继续进行访问得到数据如果Redis是作为缓存的话那么就可以减少MySQL的压力从而避免MySQL宕机。 Redis有两种持久化方式RDB和AOF。 RDB
RDB是定期备份的持久化方式即Redis定期会把内存中的数据进行备份生成一个快照保存在硬盘中。这样当Redis重启的时候就可以读取RDB文件来恢复内存数据。
触发方式
手动触发
程序猿在客户端输入特定的命令来触发Redis服务器快照的生成。
save通过save命令可以使Redis服务器触发快照行为进行备份
bgsave通过bgsave命令同样可以使Redis触发快照行为进行备份。 对于save和bgsave两个命令来说最大的区别就是save会和其他客户端命令一样在同一个进程中执行因此就会影响其他客户端命令的执行而对于bgsave命令来说并不会在当前进程中执行而是fork一个子进程在子进程中执行这样就不会影响其他客户端的请求。 bgsave的执行流程 1. 客户端发送bgsave命令之后Redis服务器会判断是否已经正在执行该命令。如果正在执行那么就会直接进行返回。
2. 如果没有执行那么Redis服务器就会通过fork命令来创建出一个子进程。 fork命令是Linux系统提供的一个创建子进程的API。简单来说fork命令就是将原来的进程给简单粗暴的复制一份。复制完成之后两个进程之间就没有任何的关系各自会执行各自的内容不过由于后续的进程即子进程是父进程复制而来因此两个进程中的数据是完成相同的。这样让子进程生成一份快照就相当于让父进程生成一份快照。 对于fork命令来说是不是有比较大的性能开销不会执行fork命令进行内存拷贝的时候并不是在内存空间中把所有的数据全部复制一份而是采用写时拷贝的方式来完成。 所谓写时拷贝当父子进程的数据是完成相同时两者指向的内存空间还是同样的位置。但是当任一进程发生改变时才会开辟一个新的内存空间来记录变化的数据。 综上所述使用fork命令生成父子进程时并不会产生较大的性能开销。毕竟Redis改变的数据并不是大多数而是一小部分因此对于写时拷贝来说消耗并不是很大整体来说较快。 3. 父进程继续执行客户端的其他命令请求而子进程则是来生成快照进行备份。
4. 子进程持久化完成之后就会来通知父进程。父进程再更新一些统计信息之后子进程就可以销毁了。
自动触发
1. 在Redis的配置文件中可以进行配置以来达到自动触发定期快照的操作
2. 在主从模式中给主节点加从节点时主节点会主动生成快照发送给从节点
3. 当客户端发送shutdown命令进程关闭服务器时会触发快照的生成但是如果是意外宕机例如掉电或者kill那么此时就不会生成快照。
RDB文件
1. RDB文件的存放位置是可以通过Redis的配置信息来设置的默认是放在/var/lib/redis中。 2. Redis文件是一个二进制的文件。即把内存中的数据通过压缩的形式保存到这个二进制文件中。通过压缩可以节省空间但是进行操作时就会消耗一定的CPU资源。
3. Redis重启时就会通过RDB文件来恢复内存中的数据。但是如果RDB的数据内容发生了变化那么就有可能重启失败也有可能重启成功。因此Redis还专门提供了检查RDB文件的工具可以在重启服务器之前先检查RDB文件是否发生错误。
4. 在快照生成RDB文件时会将生成的这些内容存储到一个临时的文件中。当快照生成完毕就会使用新生成的RDB文件来代替旧的RDB文件这样硬盘中自始至终就只有一个文件了。 5. 在bgsave命令的执行流程中虽然fork子进程的性能消耗并不大但是RDB文件的生成也有一个较高的性能开销因此RDB文件不是实时备份而是定期备份。正是由于定期备份因此在一次备份完成之后Redis宕机再次重启时备份之后操作的数据都不复存在。
RDB特点
1. RDB文件是一个二进制格式的文件因此非常适合用于备份、全量复制等场景。
2. Redis加载RDB恢复数据往往比加载AOF恢复数据要快。这是因为RDB使用二进制来组织数据而AOF则是使用文本格式来组织数据而计算机天然对二进制好感度高。
3. Redis无法做到实时持久化毕竟生成一次快照消耗的资源还是较多的属于重量级操作频繁执行成本过高。
4. RDB使用二进制格式保存但是Redis不同的版本可能二进制格式略有不同因此可能存在兼容性问题例如将5版本的RDB放到7版本的RDB文件中就可能运行不起来。
AOF
AOFAppend Only File是实时备份的持久化方式。所谓实时备份并不是将Redis服务器内存中的数据进行持久化而是把用户进行的操作当作日志记录成文件。也就是说当用户执行某条操作时Redis就会进行记录并且写入到文件中。这样当Redis服务器重新启动的时候就回去读取AOF文件用来恢复数据。 对于RDB方式的持久化来说最大的问题是不能实时持久化来保存数据。这就导致在某些突发情况发生后Redis服务器重启时Redis内存中的数据可能会存在丢失的情况。 因此AOF方式的持久化就是用来解决RDB存在的问题。当开启AOF方式的持久化之后Redis服务器重新启动时就会读取AOF文件中的内容来恢复内存数据不会再读取RDB文件的内容。 开启AOF
默认情况下Redis服务器是使用RDB的方式来进行持久化的。对于AOF来说默认则是关闭状态要想使用AOF就要在配置文件中进行开启 当AOF方式的持久化开启之后RDB就会失效。并且对于AOF来说其文件生成的位置和RDB文件生成的位置在同一目录下。
AOF与Redis性能间的关系
引入AOF之后既要操作内存Redis服务器需要对客户端发送的请求进行响应又要操作硬盘Redis服务器需要把客户端的操作当成日志写入文件这是否对Redis的效率产生了很大的影响答案是没有。
AOF虽然是把客户端的操作给记录下来但是并不是直接让工作线程把数据给写入硬盘。而是先把数据写入到内存中的缓冲区中当积累一定数量之后通过积累可以降低写硬盘的次数从而减少性能的消耗统一写入硬盘写入硬盘时采用了顺序读取的方式相对随机读取来说还是比较快的一种读取方式。 通过上述描述我相信大家存在一个疑惑把数据写入缓冲区那不还是在内存中这些数据依然有丢失的风险因此AOF依旧没解决RDB存在的问题。 其实不然AOF的确解决了RDB存在的不能实时持久化的问题这本质上存在一个可靠和性能的矛盾性。当数据特别可靠时其性能一定会有所损耗当性能非常好时其数据可靠性就会有所下降。例如MySQL中的隔离级别当隔离级别是可串行化时其数据基本上完全可靠但是性能低下当隔离级别是读未提交时其读取到的数据不一定可靠但是其性能一定非常高。 综上针对Redis的AOF来说其官方也给出了不同的措施来解决不同业务场景下的问题即程序员根据对系统的评估来取舍缓存区的刷新策略。刷新频率越高那么其性能影响也就越大但是其数据的可靠性就越高刷新频率越低性能影响就会越小但是数据的可靠性就会降低。 在Redis中使用appendfsync属性来配置刷新策略并且给出了三个配置值。
可配置值说明性能与可靠性always 客户端进行操作之后数据进入缓存区之后直接写入AOF文件中。 性能最低可靠性最高。 everysec 客户端进行操作之后先写入缓冲区然后每秒写入一次文件。 性能适中可靠性适中。 Redis默认此刷新策略。 no 客户端进行操作之后先写入缓存区然后根据操作系统来控制写入文件。 性能最高可靠性最低。
重写机制
在AOF文件中记录的是客户端每次进行的操作。但是在客户端操作的过程中可能某个变量会重复被操作最后被删除。这些操作如果记录在AOF文件中那么在Redis服务器重启的时候也会对这个变量进行反复操作最后删除那么就是消耗大量内存但是做了无用的事。
因此Redis就存在一个机制能够对AOF文件进行整理操作这个整理就能够剔除其中的冗余操作并且合并一些操作达到给AOF文件瘦身的效果。这样当Reids服务器进行重启的时候就不会机械性的做一些无用的操作。
这个机制就被称为Redis的重写机制。
触发方式
手动触发和自动触发两种。
手动触发使用bgrewriteaof命令进行操作
自动触发则根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发时机auto-aof-rewrite-min-size表示触发重写时AOF的最小文件大小默认是64MBauto-aof-rewrite-percentage代表当前AOF占用大小相比较上次重写时增加的比例。
重写流程 ① 当Redis接收到了重写操作时就会fork一个子进程。如果此时Redis服务器已经在重写那么就不会再次执行命令直接返回。 ② 父进程仍然接收请求子进程负责针对AOF文件进行重写。在重写的时候并不关心AOF文件原来有啥内容只关心此时内存中数据的最终状态。因此子进程只需要把当前的数据获取出来以AOF文件的格式写入到一个新的AOF文件中。
③ 子进程在重写AOF文件的同时父进程还是会不停的接收客户端的请求并且把这些请求产生的AOF数据写入到缓冲区中再刷新到原来的AOF文件中。在执行这些命令的同时父进程还会准备一个新的缓冲区把fork之后产生的AOF数据放入其中。 为啥要准备这个新的缓冲区 当fork之后子进程中的内存数据是父进程fork之前的因此对于fork之后的请求对内存造成的修改子进程是不知道的。所以当Redis把子进程的内存数据整理完毕之后如果直接代替之前的文件那么整理文件过程中产生的数据会丢失。所以要准备这个缓冲区来接收fork之后的一些请求。 ④ 子进程整理完毕之后会通知父进程父进程把新缓冲区中的内容加入到新AOF文件之中就可以用新的文件来代替旧的AOF文件。 当在重写过程中发现Redis正在备份。那么此时AOF重写就会停止等待RDB快照完成再继续进行重写的操作。 混合持久化
对于RDB来说是没法做到实时备份存在数据丢失的风险对于AOF来说是使用文本的格式来写入数据导致后续加载文件的成本较高。
由于RBD和AOF各有优缺点因此就又有了混合持久化的方式。正所谓小孩子才做选择大人全都要。简单来说混合持久化就是对于每一个操作都会使用AOF的方式来写入文件当执行重写操作时就会把当前内存的状态按照RDB的格式写入到新的AOF文件中。这样即可以保证所有数据的及时更新又可以在读取文件时采用较小的成本。