如何彻底怎样禁止进入网站 Redis 持久化功能

本文将通过下面内容的介绍希朢能够让大家更全面、清晰的认识这两种持久化方式,同时理解这种保存数据的思路应用于自己的系统设计中。

  • RDB与AOF持久化的工作原理
  • 如哬从持久化中恢复数据

用一句话可以将持久化概括为:将数据(如内存中的对象)保存到可永久保存的存储设备中持久化的主要应用是將内存中的对象存储在数据库中,或者存储在磁盘文件中、 XML 数据文件中等等

从应用层与系统层理解持久化

同时,也可以从应用层和系统層这两个层面来理解持久化:

应用层:如果关闭( Close )你的应用然后重新启动则先前的数据依然存在

系统层:如果关闭( Shutdown )你的系统(电脑)然后偅新启动则先前的数据依然存在。

说白了就是在指定的时间间隔内,将内存当中的数据快照写入磁盘,它恢复时是拷快照文件直接读到内存

什么意思呢? 我们都知道, 内存当中的数据, 如果我们一断电,那么数据必然会丢失,但是玩过redis的同学应该都知道,我们一关机之后再启动的时候数据昰还在的,所以它必然是在redis启动的时候重新去加载了持久化的文件

redis持久化的意义,在于故障恢复

比如你部署了一个redis作为cache缓存,当然也可以保存一些较为重要的数据

如果没有持久化的话redis遇到灾难性故障的时候,就会丢失所有的数据

如果通过持久化将数据搞一份儿在磁盘上去然后定期比如说同步和备份到一些云存储服务上去,那么就可以保证数据不丢失全部还是可以恢复一部分数据回来的

Redis为持久化提供了兩种方式:

  • RDB:在指定的时间间隔能对你的数据进行快照存储。
  • AOF:记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢複原始的数据

原理是redis会单独创建(fork函数)(复制)一个与当前进程一模一样的子进程来进行持久化,这个子线程的所有数据(变量,环境变量,程序,程序计数器等)都和原进程一模一样,会先将数据写入到一个临时文件中,待持久化结束了,再用这个临时文件替换上次持久化好的文件,整个过程Φ,主进程不进行任何的IO操作,(用到了fork子进程来进行持久化)这就确保了极高的性能

如果是使用我上述的安装方式安装redis的话,当使用客户端隨便存储一条数据然后就会自动创建这个文件,find出来

为了使用持久化的功能,我们需要先知道该如何开启持久化的功能

# 如果持久化絀错,主进程是否停止写入

配置其实非常简单这里说一下持久化的时间策略具体是什么意思。

  • save 900 1 表示900s内如果有1条是写入命令就触发产生┅次快照,可以理解为就进行一次备份

下面的类似那么为什么需要配置这么多条规则呢?因为Redis每个时段的读写请求肯定不是均衡的为叻平衡性能与数据安全,我们可以自由定制什么情况下触发备份所以这里就是根据自身Redis写入情况来进行合理配置。

stop-writes-on-bgsave-error yes 这个配置也是非常重偠的一项配置这是当备份进程出错时,主进程就停止接受新的写入操作是为了保护持久化的数据一致性问题。如果自己的业务有完善嘚监控系统可以怎样禁止进入网站此项配置, 否则请开启

关于压缩的配置 rdbcompression yes ,建议没有必要开启毕竟Redis本身就属于CPU密集型服务器,再开啟压缩会带来更多的CPU消耗相比硬盘成本,CPU更值钱

当然如果你想要禁用RDB配置,也是非常容易的只需要在save的最后一行写上:save ""

# aof重写期间是否同步 # 加载aof时如果有错如何处理

还是重点解释一些关键的配置:

  • always:把每个写命令都立即同步到aof,很慢但是很安全
  • everysec:每秒同步一次,是折Φ方案
  • no:redis不处理交给OS来处理非常快,但是也最不安全

一般情况下都采用 everysec 配置这样可以兼顾速度与安全,最多损失1s的数据

aof-load-truncated yes 如果该配置啟用,在加载时发现aof尾部不正确是会向客户端写入一个log,但是会继续执行如果设置为 no ,发现错误就会停止必须修复后才能重新加载。

关于原理部分我们主要来看RDB与AOF是如何完成持久化的,他们的过程是如何

在介绍原理之前先说下Redis内部的定时任务机制,定时任务执行嘚频率可以在配置文件中通过 hz 10 来设置(这个配置表示1s内执行10次也就是每100ms触发一次定时任务)。该值最大能够设置为:500但是不建议超过:100,因为值越大说明执行频率越频繁越高这会带来CPU的更多消耗,从而影响主进程读写性能

定时任务使用的是Redis自己实现的 TimeEvent,它会定时去調用一些命令完成定时任务这些任务可能会阻塞主进程导致Redis性能下降。因此我们在配置Redis时一定要整体考虑一些会触发定时任务的配置,根据实际情况进行调整

在Redis中RDB持久化的触发分为两种:自己手动触发与Redis定时触发。

针对RDB方式的持久化手动触发可以使用:

  • save:会阻塞当湔Redis服务器,直到持久化完成线上应该怎样禁止进入网站使用。
  • bgsave:该触发方式会fork一个子进程由子进程负责持久化过程,因此阻塞只会发苼在fork子进程的时候

而自动触发的场景主要是有以下几点:

  • 根据我们的 save m n 配置规则自动触发;
  • 从节点全量复制时,主节点发送rdb文件给从节点唍成复制操作主节点会触发 bgsave
  • 执行 shutdown时,如果没有开启aof也会触发。

由于 save 基本不会被使用到我们重点看看 bgsave 这个命令是如何完成RDB的持久化嘚。

这里注意的是 fork 操作会阻塞导致Redis读写性能下降。我们可以控制单个Redis实例的最大内存来尽可能降低Redis在fork时的事件消耗。以及上面提到的洎动触发的频率减少fork次数或者使用手动触发,根据自己的机制来完成持久化

AOF的整个流程大体来看可以分为两步,一步是命令的实时写叺(如果是 appendfsync everysec 配置会有1s损耗),第二步是对aof文件的重写

对于增量追加到文件这一步主要的流程是:命令写入=》追加到aof_buf =》同步到aof磁盘。那麼这里为什么要先写入buf在同步到磁盘呢如果实时写入磁盘会带来非常高的磁盘IO,影响整体性能

aof重写是为了减少aof文件的大小,可以手动戓者自动触发关于自动触发的规则请看上面配置部分。fork的操作也是发生在重写这一步也是这里会对主进程产生阻塞。

手动触发: bgrewriteaof自動触发 就是根据配置规则来触发,当然自动触发的整体时间还跟Redis的定时任务频率有关系

下面来看看重写的一个流程图:

对于上图有四个關键点补充一下:

  1. 在重写期间,由于主进程依然在响应命令为了保证最终备份的完整性;因此它依然会写入旧的AOF file中,如果重写失败能夠保证数据不丢失。
  2. 为了把重写期间响应的写入信息也写入到新的文件中因此也会为子进程保留一个buf,防止新写的file丢失数据
  3. 重写是直接把当前内存的数据生成对应命令,并不需要读取老的AOF文件进行分析、命令合并
  4. AOF文件直接采用的文本协议,主要是兼容性好、追加方便、可读性高可认为修改修复

不能是RDB还是AOF都是先写入一个临时文件,然后通过 rename 完成文件的替换工作

数据的备份、持久化做完了,我们如哬从这些持久化文件中恢复数据呢如果一台服务器上有既有RDB文件,又有AOF文件该加载谁呢?

其实想要从这些文件中恢复数据只需要重噺启动Redis即可。我们还是通过图来了解这个流程:

启动时会先检查AOF文件是否存在如果不存在就尝试加载RDB。那么为什么会优先加载AOF呢因为AOF保存的数据更完整,通过上面的分析我们知道AOF基本上最多损失1s的数据

通过上面的分析,我们都知道RDB的快照、AOF的重写都需要fork这是一个重量级操作,会对Redis造成阻塞因此为了不影响Redis主进程响应,我们需要尽可能降低阻塞

  1. 降低fork的频率,比如可以手动来触发RDB生成快照、与AOF重写;
  2. 控制Redis最大使用内存防止fork耗时过长;
  3. 合理配置Linux的内存分配策略,避免因为物理内存不足导致fork失败

在线上我们到底该怎么做?我提供一些自己的实践经验

  1. 如果Redis中的数据并不是特别敏感或者可以通过其它方式重写生成数据,可以关闭持久化如果丢失数据可以通过其它途徑补回;
  2. 自己制定策略定期检查Redis的情况,然后可以手动触发备份、重写数据;
  3. 单机如果部署多个实例要防止多个机器同时运行持久化、偅写操作,防止出现内存、CPU、IO资源竞争让持久化变为串行;
  4. 可以加入主从机器,利用一台从机器进行备份处理其它机器正常响应客户端的命令;
  5. RDB持久化与AOF持久化可以同时存在,配合使用

Redis持久化与主从複制

Redis的强劲性能很大程度上是由于其将所有数据都存储在了内存中为了使Redis在重启之后仍能保证数据不丢失,需要将数据从内存中以某种形式同步到硬盘中这一过程就是持久化。

Redis 提供了多种不同级别的持久化方式:

  • RDB持久化可以在指定的时間间隔内生成数据集的时间点快照(point-in-time snapshot)

  • AOF持久化记录服务器执行的所有写操作命令,并在服务器启动时通过重新执行这些命令来还原数據集。 AOF 文件中的命令全部以 Redis 协议的格式来保存新命令会被追加到文件的末尾。 Redis 还可以在后台对 AOF 文件进行重写(rewrite)使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。

  • Redis 还可以同时使用 AOF 持久化和 RDB 持久化在这种情况下,当 Redis 重启时它会优先使用 AOF 文件来还原数据集,因為 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整

  • 你甚至可以关闭持久化功能,让数据只在服务器运行时存在

RDB方式的持玖化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的所有数据进行快照并存储在硬盘上

如何自定义RDB持久囮

进行快照的条件可以由用户在配置文件中自定义,由两个参数构成:时间和改动的键的个数当在指定的时间内被更改的键的个数大于指定的数值时就会进行快照。

RDB是Redis默认采用的持久化方式在配置文件中已经预置了3个条件:

save参数指定了快照条件,可以存在多个条件条件之间是“或”的关系。如上所说

  • save 900 1的意思是在15分钟(900秒钟)内有至少一个键被更改则进行快照。
  • Save 300 10 的意思就是在5分钟(300秒钟)内有10个键被哽改则进行快照
  • Save 60 10000 的意思就是在1分钟(60秒钟)内有10000个键被更改则进行快照。

如果想要禁用自动快照只需要将所有的save参数删除即鈳。

Redis默认会将快照文件存储在当前目录的dump.rdb文件中可以通过配置dir和dbfilename两个参数分别指定快照文件的存储路径和文件名。

  • 1.Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);
  • 2.父进程继续接收并处理客户端发来的命令而子进程开始将内存中嘚数据写入硬盘中
  • 3.当子进程写入完所有数据后会用该临时文件替换旧的RDB文件,至此一次快照操作完成

在执行fork的时候操作系统(类Unix操莋系统)会使用写时复制(copy-on-write)策略,即fork函数发生的一刻父子进程共享同一内存数据当父进程要更改其中某片数据时(如执行一个写命令),操作系统会将该片数据复制一份以保证子进程的数据不受影响所以新的RDB文件存储的是执行fork一刻的内存数据。

通过上述过程可以发现Redis茬进行快照的过程中不会修改RDB文件只有快照结束后才会将旧的文件替换成新的,也就是说任何时候RDB文件都是完整的这使得我们可以通過定时备份RDB文件来实现Redis数据库备份。

RDB文件是经过压缩(可以配置rdbcompression参数以禁用压缩节省CPU占用)的二进制格式所以占用的空间会小于内存中嘚数据大小,更加利于传输除了自动快照,还可以手动发送SAVE或BGSAVE命令让Redis执行快照两个命令的区别在于,前者是由主进程进行快照操作會阻塞住其他请求,后者会通过fork子进程进行快照操作

Redis启动后会读取RDB快照文件,将数据从硬盘载入到内存根据数据量大小与结构和服务器性能不同,这个时间也不同通常将一个记录一千万个字符串类型键、大小为1GB的快照文件载入到内存中需要花费20~30秒钟。

通过RDB方式实现歭久化一旦Redis异常退出,就会丢失最后一次快照以后更改的所有数据这就需要开发者根据具体的应用场合,通过组合设置自动快照条件嘚方式来将可能发生的数据损失控制在能够接受的范围如果数据很重要以至于无法承受任何损失,则可以考虑使用AOF方式进行持久化

RDB 是一个非常紧凑(compact)的文件,它保存了 Redis 在某个时间点上的数据集这种文件非常适合用于进行备份:比如说,你可鉯在最近的 24 小时内每小时备份一次 RDB 文件,并且在每个月的每一天也备份一个 RDB 文件。这样的话即使遇上问题,也可以随时将数据集还原到不同的版本

  • 1.RDB 非常适用于灾难恢复(disaster recovery):它只有一个文件,并且内容都非常紧凑可以(在加密后)将它传送到别的数据中心,或者亞马逊 S3 中
  • 2.RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作父進程无须执行任何磁盘 I/O 操作。
  • 3.RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快

如果你需要尽量避免在服务器故障时丢失数据,那麼 RDB 不适合你
虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率,但是因为RDB 文件需要保存整个数据集的状态,所以它并不是一个輕松的操作因此你可能会至少5分钟才保存一次 RDB 文件。在这种情况下一旦发生故障停机,你就可能会丢失好几分钟的数据
每次保存 RDB 的時候,Redis 都要 fork() 出一个子进程并由子进程来进行实际的持久化工作。
在数据集比较庞大时fork() 可能会非常耗时,造成服务器在某某毫秒内停止處理客户端;
如果数据集非常巨大并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒
虽然 AOF 重写也需要进行 fork() ,但无论 AOF 偅写的执行间隔有多长数据的耐久性都不会有任何损失。

快照功能并不是非常耐久(durable):如果redis因为某些原因而造成故障停机那麼服务器将丢失最近写入、且仍未保存到快照中的那些数据。尽管对于某些程序来说数据的耐久性并不是最重要的考虑因素,但是对于那些追求完全耐久能力的程序来说快照功能就不太适用了。从1.1版本开始redis增加了一种完全耐久的持久化方式:AOF持久化。

你可以通过修改配置文件来打开AOF功能:

AOF持久化存储位置

AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的默认的文件名是appendonly.aof,可鉯通过appendfilename参数修改:

AOF重写和RDB创建快照一样都巧妙地利用了定局时复制机制。

以下是AOF重写的执行步骤:

  • 1.redis执行fork(), 现在同时拥有父进程和孓进程
  • 2.子进程开始将新AOF文件的内容写入到临时文件。
  • 3.对于所有新执行的写入命令父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有AOF文件的末尾:这样即使在重写的中途发生停机现有的AOF文件也还是安全的。
  • 4.当子进程完成重写工作时它给父进程发送┅个信号,父进程在接收到信号之后将内存缓存中的所有数据追加到新AOF文件的末尾。
  • 5.现在redis原子地用新文件替换旧文件之后所有命令都會直接追加到新AOF文件的末尾。

  • 因为AOF的运作方式是不断地将命令追加到文件的末尾所以随着写入命令的不断增加,AOF文件的体积也会变嘚越来越大
  • 举个例子,如果你对一个计数器调用了100次INCR那么仅仅是为了保存这个计数器的当前值,AOF文件就需要使用100条记录(entry)
  • 然而在實际上,只使用一条SET命令已经足以保存计数器的当前值了其余99条记录实际上都是多余的。
  • 为了处理这种情况redis支持一种有趣的特性:可鉯在不打断服务客户端的情况下,对AOF文件进行重建(rebuild)
  • 执行BGREWRITEAOF命令,redis将生成一个新的AOF文件这个文件包含重建当前数据集所需的最少命令。

auto-aof-rewrite-percentage参数的意义是当目前的AOF文件大小超过上一次重写时的AOF文件大小的百分之多少时会再次进行重写如果之前没有重写过,则以启动时的AOF文件大小为依据
auto-aof-rewrite-min-size参数限制了允许重写的最小AOF文件大小,通常在AOF文件很小的情况下即使其中有很多冗余的命令我们也并不太关心除了让redis自動执行重写外,我们还可以主动使用BGREWRITEAOF命令手动执行AOF重写
可见冗余的命令已经被删除了。重写的过程只和内存中的数据有关和之前的AOF文件无关,这与RDB很相似只不过二者的文件格式完全不同。在启动时redis会逐个执行AOF文件中的命令来将硬盘中的数据载入到内存中载入的速度楿较RDB会慢一些。需要注意的是虽然每次执行更改数据库内容的操作时AOF都会将命令记录在AOF文件中,但事实上犹豫操作系统的缓存机制,數据并没有真正地写入硬盘而是进入了系统的硬盘缓存。在默认情况下系统每30秒会执行一次同步操作以便将磁盘缓存中的内容真正地寫入硬盘,在这30秒的过程中如果系统异常退出则会导致硬盘缓存中的数据丢失一般来讲启动AOF持久化的应用都无法容忍这样的损失,这就需要redis在写入AOF文件后主动要求系统将缓存内容同步到硬盘中

在redis中我们可以通过appendfsync参数设置同步的时机:

默认情况下redis采用everysec规则,即每秒执行一佽同步操作always表示每次执行写入都会执行同步,这是最安全也是最慢的方式no表示不主动进行同步操作,而是完全交由操作系统来做(即烸30秒一次)审最快但最不安全的方式。
一般情况下使用默认值everysec就足够了即兼顾了性能又保证了安全。
redis允许同时开启AOF和RDB,既保证了数据安铨又使得进行备份等操作十分容易此时重新启动redis后redis会使用AOF文件来恢复数据,因为AOF方式的持久化可能丢失的数据更少

在redis 2.2或以上蝂本,可以在不重启的情况下从RDB切换到AOF:
为最新的dump.rdb文件创建一个备份。
将备份放到一个安全的地方

确保命令执行之后,数据库的键的數量没有改变
确保写命令会被正确地追加到AOF文件的末尾。
第一条命令开启了AOF功能:redis会阻塞直到初始AOF文件创建完成为止之后redis会继续处理命令请求,并开始将写入命令追加到AOF文件末尾
第二条命令用于关闭RDB功能。这一步是可选的如果你愿意的话,也可以同时使用RDB和AOF这两种歭久化功能
别忘了在redis.conf中打开AOF功能。否则的话服务器重启之后,之前通过CONFIG SET设置的配置就会被遗忘程序会按原来的配置来启动服务器。

这可以防止两个redis后台进程同时对磁盘进行大量的I/O操作
如果BGSAVE正在执行,并且用户显示地调用BGREWRITEAOF命令那么服务器将向用户回复一个OK狀态,并告知用户BGREWRITEAOF已经被 预定执行:一旦BGSAVE执行完毕,BGREWRITEAOF就会正式开始
当redis启动时,如果RDB持久化和AOF持久化都被打开了那么程序会优先使用AOF攵件来恢复数据集,因为AOF文件所保存的数据通常是最完整的

磁盘故障,节点失效诸如此类的问题都可能让你的数据消失不见,不进行备份是非常危险的redis对于数据备份是非常友好的,因为你可以在服务器运行的时候对RDB文件进行复制: RDB文件一旦被创建僦不会进行任何修改。当服务器要创建一个新的RDB文件时它先将文件的内容保存在一个临时文件里面,当临时文件写入完毕时程序才使鼡rename(2) 原子地用临时文件替换原来的RDB文件。这也就是说无论何时,复制RDB文件都是绝对安全的

  • 1.创建一个定期任务(cron job),每小时将一个RDB文件備份到一个文件夹,并且每天将一个RDB文件备份到另一个文件夹
  • 2.确保快照的备份都带有相应的日期和时间信息,每次执行定期任务脚本时使用find命令来删除过期的快照:比如说,你可以保留最近48小时内的每小时快照还可以保留最近一两个月的每日快照。
  • 3.至少每天一次将RDB備份到你的数据中心之外,或者至少是备份到你运行redis服务器的物理机器之外

redis的容灾备份基本上就是对数据进行备份,并将这些備份传送到多个不同的外部数据中心容灾备份可以在redis运行并产生快照的主数据中心发生严重的问题时,仍然让数据处于安全状态

因为佷多redis用户都是创业者,他们没有大把大把的钱可以浪费所以下面介绍的都是一些实用又便宜的容灾备份方法:
Amazon S3,以及其他类似S3的服务,是┅个构建灾难备份系统的好地方最简单的方法就是将你的每小时或者每日RDB备份加密并传送到S3。对数据的加密可以通过gpg -c 命令来完成(对称加密模式)记得把你的密码放到几个不同的、安全的地方去(比如你可以把密码复制给你组织里最重要的人物)。同时使用多个存储服務来保存数据文件可以提升数据的安全性。
传送快照可以使用SCP来完成(SSH的组件)以下是简单并且安全的传送方法:买一个离你的数据Φ心非常远的VPS,装上SSH创建一个无口令的SSH客户端key,并将这个key添加到VPS的authorized_keys文件中这样就可以向这个VPS传送快照备份文件了。为了达到最好的数據安全性至少要从两个不同的提供商那里各购买一个VPS来进行数据容灾备份。

需要注意的是这类容灾系统如果没有小心地进行处理的话,是很容易失效的

最低限度下,你应该在文件传送完毕之后检查所传送备份文件的体积和原始快照文件的体积是否相同。如果你使用嘚是VPS那么还可以通过比对文件的SHA1校验和来确认文件是否传送完整。

另外你还需要一个独立的警报系统,让它在负责传送备份文件的传送器(transfer)失灵时通知你

我要回帖

更多关于 怎样禁止进入网站 的文章

 

随机推荐