当前位置: 首页 > 科技观察

十分钟彻底搞懂Redis持久化与主从复制

时间:2023-03-17 17:43:49 科技观察

什么是Redis持久化?Redis作为键值内存数据库(NoSQL),将数据存储在内存中。记忆中,如下:这样做有什么问题吗?其实稍微有点计算机基础的人都知道,只要服务器关机(各种原因引起),内存中保存的数据就会消失。当守护进程退出时,内存中的数据也会随之消失。对于只使用Redis作为缓存的项目,数据丢失可能问题不大,重新从数据源加载数据即可,但是如果直接将用户提交的业务数据存储在Redis中,将Redis作为数据库来使用,里面存放着重要的业务数据,那么Redis内存数据丢失的影响可能是毁灭性的。为了避免数据在内存中丢失,Redis提供了对持久化的支持。我们可以选择不同的方式将数据从内存保存到硬盘,从而实现数据的持久化。Redis提供了两种不同的数据持久化方式:RDB和AOF。下面就来详细介绍一下这几种不同的持久化方式。RDBRDB是一种快照存储持久化方式。具体来说,就是将Redis在某一时刻的内存数据保存到硬盘上的一个文件中。默认保存的文件名为dump.rdb,当Redis服务器启动时,会重新加载dump.rdb文件的数据恢复到内存中。启用RDB持久化模式启用RDB持久化模式非常简单。客户端可以向Redis服务器发送save或bgsave命令让服务器生成RDB文件,也可以通过服务器配置文件指定触发RDB的条件。1.save命令save命令是一个同步操作。#同步数据到磁盘>save当客户端向服务器发送save命令请求进行持久化,服务器会在save命令后阻塞其他客户端请求,直到数据同步完成。如果数据量太大,同步数据的时间会比较长,这期间Redis服务器是收不到其他请求的,所以生产环境最好不要使用save命令。2.bgsave命令与save命令不同。bgsave命令是一个异步操作。#将数据集异步保存到磁盘>bgsave当客户端发送服务发出bgsave命令时,Redis服务器主进程会fork一个子进程来解决数据同步问题。将数据保存到rdb文件后,子进程就会退出。因此,相对于save命令,Redis服务器在处理bgsave时使用子线程进行IO写入,主进程仍然可以接收其他请求,但是fork子进程是同步的,所以fork子进程时,无法接收其他请求。这意味着如果分叉子进程花费的时间太长(通常很快),bgsave命令仍会阻止其他客户端请求。3、除了通过客户端发送命令外,还有一种方式可以自动触发服务端配置,即在Redis配置文件中保存指定触发RDB持久化的条件,如[howmanywriteoperationsarereachedwithinhow许多秒]启动RDB数据同步。例如,我们可以在配置文件redis.conf中指定如下选项:#atleastonewritecommandwithin900ssave9001#atleast10writecommandswithin300ssave30010#atleast10000writecommandswithin60ssave6010000然后在启动服务器时加载配置文件。#启动服务器加载配置文件redis-serverredis.conf,通过服务器配置文件触发RDB,类似于bgsave命令。当达到触发条件时,会fork出一个子进程进行数据同步,但是最好不要使用这种方式触发RDB持久化,因为设置触发时间太短,容易频繁写入rdb文件,影响服务器性能,时间设置过长会造成数据丢失。rdb文件前面介绍了服务器端生成rdb文件的三种方式,无论是主进程生成还是子进程生成,过程如下:生成临时rdb文件,写入数据。完成数据写入,将官方的rdb文件替换为临时文件。删除原来的db文件。RDB默认生成的文件名为dump.rdb。当然,我可以通过配置文件进行更详细的配置。例如单机下启动多个redisserver进程时,可以通过端口号配置不同的rdb名称,如下所示:#是否压缩rdb文件rdbcompressionyes#rdb文件名dbfilenameredis-6379.rdb#rdb文件savedirectorydir~/redis/RDB相比AOF方式,通过rdb文件恢复数据速度更快。rdb文件非常紧凑,适合数据备份。通过RDB进行数据备份对Redis服务器的性能影响不大,因为它是使用子进程生成的。RDB的几个缺点如果服务器宕机,使用RDB会导致一定时间内的数据丢失。比如我们设置10分钟同步一次或者5分钟同步一次达到1000次写入,那么如果触发没有达到条件服务器宕机,这个时间段的数据就会丢失。使用save命令会导致服务器阻塞,数据同步完成后才能接收后续请求。使用bgsave命令fork子进程时,如果数据量过大,forks进程也会被阻塞。另外,fork子进程会消耗内存。AOF说完了RDB,再来说说Redis的另一种持久化方式:AOF(Append-onlyfile)。不同于RDB存储某一时刻的快照,AOF持久化方式会记录客户端对服务端的每一次写操作命令,并将这些写操作追加保存到Redis协议中后缀为aof的文件末尾。当Redis服务器重启时,会加载并运行aof文件的命令,达到恢复数据的目的。启用AOF持久化模式。Redis默认不开启AOF持久化模式。我们可以在配置文件中开启,进行更详细的配置,如下redis.conf文件:#开启aof机制appendonlyyes#aof文件名appendfilename"appendonly.aof"#写策略,总是表示每次写操作保存到aof文件,也可以是everysec或者noappendfsyncalways#默认不重写aof文件no-appendfsync-on-rewriteno#保存目录dir~/redis/上面配置文件中的三种写策略,我们可以通过appendfsync选项来指定写入策略,一共有三个选项。appendfsync总是#appendfsynceverysec#appendfsyncno1。alwaysclient的每一次写操作都会保存到aof文件中。这种策略很安全,但是每次写都有IO操作,所以也很慢。2、everysecappendfsync默认的写策略是每秒写一次aof文件,所以最多1s的数据可能会丢失。3、noRedis服务器不负责写入aof,而是由操作系统来处理何时写入aof文件。更快,但也是最不安全的选择,不推荐。AOF文件重写AOF将客户端的每一次写操作都追加到aof文件的末尾,比如对一个key多次执行incr命令。这时候aof将每条命令都保存到aof文件中,aof文件就会变得很大。incrnum1incrnum2incrnum3incrnum4incrnum5incrnum6...incrnum100000aof文件太大,加载aof文件恢复数据时会很慢。为了解决这个问题,Redis支持aof文件重写,通过重写aof,可以生成最小的命令集来恢复当前数据,比如上面例子中的这么多命令,可以重写为:setnum100000aoffileis一个二进制文件,不像上面的例子,直接保存每条命令,使用Redis自带的格式,上面只是为了演示。这两种重写方式可以通过redis.conf配置文件中的no-appendfsync-on-rewrite选项设置是否开启重写。该方法每次fsync都会重写,影响服务器性能,所以默认值为no,不推荐使用。#默认不重写aof文件no-appendfsync-on-rewriteno客户端向服务端发送bgrewriteaof命令,服务端也可以进行AOF重写。#让服务器异步重写追加的aof文件Command>bgrewriteaof重写aof文件的好处压缩aof文件,减少磁盘占用。aof的命令被压缩成最小命令集,加快了数据恢复的速度。AOF文件损坏。在写aof日志文件的时候,如果Redis服务器挂了,aof日志文件就会出现格式错误。当Redis服务器重启后,Redis服务器会拒绝加载aof文件。您可以通过以下步骤和数据恢复来修复aof。现在备份aof文件,以防万一。使用redis-check-aof命令修复aof文件。命令格式如下:#repairaoflogfile$redis-check-aof-fixfile.aof重启Redis服务器,加载修复的aof文件,恢复数据。AOF的优点AOF只追加日志文件,因此对服务器性能影响较小,比RDB速度快,消耗内存少。AOF的缺点AOF方式生成的日志文件太大。即使用AFO改写,文件还是很大。恢复数据比RDB慢。选择RDB还是AOF?通过上面的介绍,我们了解了RDB和AOF的优缺点,应该如何选择呢?通过下面的表示,我们可以从几个方面比较RDB和AOF。在应用的时候,我们应该根据自己的实际需求选择RDB还是AOF。其实如果我们希望数据足够安全,我们可以同时开启这两种方式,但是两种持久化方式同时进行IO操作,会严重影响服务器性能,所以有时候不得不做出取舍。当同时开启RDB和AOF时,Redis会优先使用AOF日志来恢复数据,因为AOF文件比RDB文件更完整。总结上面提到了很多关于Redis持久化机制的知识。其实如果只是把Redis当做缓存服务器,根本不需要考虑持久化。然而,在当今大多数服务器架构中,Redis只是扮演着一个缓存服务器的角色,它也可以作为一个数据库来保存我们的业务数据。这时候我们就需要了解一下Redis持久化策略的区别和选择。