zoukankan      html  css  js  c++  java
  • Redis学习-持久化机制

    Redis持久化的意义

      在于故障恢复

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

      如果没有持久化的话,redis遇到灾难性故障的时候(断电、宕机),就会丢失所有的数据

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

    通常Redis 将数据存储在内存中或虚拟内存中,它是通过以下两种方式实现对数据的持久化(如果我们想要redis仅仅作为纯内存的缓存来用,那么可以禁止RDB和AOF所有的持久化机制)

    1、RDB 快照方式:(默认持久化方式)

      这种方式就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为 dump.rdb。客户端也可以使用 save 或者 bgsave 命令通知 redis做一次快照持久化。save 操作是在 主线程中保存快照的,由于 redis 是用一个主线程来处理所有客户端的请求,这种方式会阻塞所有客户端请求。所以不推荐使用。另一点需要注意的是,每次快照持久化都是将内存数 据完整写入到磁盘一次,并不是增量的只同步增量数据。如果数据量大的话,写操作会比较多,必然会引起大量的磁盘 IO 操作,可能会严重影响性能。

       注意:由于快照方式是在一定间隔时间做一次的,所以如果 redis 意外当机的话,就会 丢失最后一次快照后的所有数据修改。 

      save 900 1  
      save 300 10
      save 60 1000 

      每隔60s,如果有超过1000个key发生了变更,那么就生成一个新的dump.rdb文件,就是当前redis内存中完整的数据快照,这个操作也被称之为snapshotting,快照

      也可以手动调用save或者bgsave命令,同步或异步执行rdb快照生成

      save可以设置多个,就是多个snapshotting检查点,每到一个检查点,就会去check一下,是否有指定的key数量发生了变更,如果有,就生成一个新的dump.rdb文件

    2、AOF 方式

      这种方式 redis 会将每一个收到的写命令都通过 write 函数追加到文件中(默认 appendonly.aof)。当 redis 重启时会通过重新执行文件中保存的写命令来在内存中重建整 个数据库的内容。当然由于操作系统会在内核中缓存 write 做的修改,所以可能不是立即写 到磁盘上。这样的持久化还是有可能会丢失部分修改。不过我们可以通过配置文件告诉 redis 我们想要通过 fsync 函数强制操作系统写入到磁盘的时机。有三种方式如下(默认是: 每秒 fsync 一次)

       appendonly yes //启用日志追加持久化方式

      #appendfsync always //每次收到写命令就立即强制写入磁盘,最慢的,但是保证完全 的持久化,不推荐使用

      #appendfsync everysec //每秒钟强制写入磁盘一次,在性能和持久化方面做了很好的折 中,推荐

      #appendfsync no //完全依赖操作系统,性能最好,持久化没保证

      日志追加方式同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用 incr test 命令 100 次,文件中必须保存全部 100 条命令,其实有 99 条都是多余的。因为要恢复 数据库状态其实文件中保存一条 set test 100 就够了。为了压缩这种持久化方式的日志文件。 redis 提供了 bgrewriteaof bgrewriteaof bgrewriteaof bgrewriteaof 命令。收到此命令 redis 将使用与快照类似的方式将内存中的数据 以命令的方式保存到临时文件中,最后替换原来的持久化日志文件。

      

    两种持久化方式的优缺点

    1 、RDB持久化机制的优点

    (1)RDB会生成多个数据文件,每个数据文件都代表了某一个时刻中redis的数据,这种多个数据文件的方式,非常适合做冷备,可以将这种完整的数据文件发送到一些远程的安全存储上去,比如说Amazon的S3云服务上去,在国内可以是阿里云的ODPS分布式存储上,以预定好的备份策略来定期备份redis中的数据

    (2)RDB对redis对外提供的读写服务,影响非常小,可以让redis保持高性能,因为redis主进程只需要fork一个子进程,让子进程执行磁盘IO操作来进行RDB持久化即可

    (3)相对于AOF持久化机制来说,直接基于RDB数据文件来重启和恢复redis进程,更加快速

    2、RDB持久化机制的缺点

    (1)如果想要在redis故障时,尽可能少的丢失数据,那么RDB没有AOF好。一般来说,RDB数据快照文件,都是每隔5分钟,或者更长时间生成一次,这个时候就得接受一旦redis进程宕机,那么会丢失最近5分钟的数据

    (2)RDB每次在fork子进程来执行RDB快照数据文件生成的时候,如果数据文件特别大,可能会导致对客户端提供的服务暂停数毫秒,或者甚至数秒

    3、AOF持久化机制的优点

    (1)AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据

    (2)AOF日志文件以append-only模式写入,所以没有任何磁盘寻址的开销,写入性能非常高,而且文件不容易破损,即使文件尾部破损,也很容易修复

    (3)AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。因为在rewrite log的时候,会对其中的指导进行压缩,创建出一份需要恢复数据的最小日志出来。再创建新日志文件的时候,老的日志文件还是照常写入。当新的merge后的日志文件ready的时候,再交换新老日志文件即可。

    (4)AOF日志文件的命令通过非常可读的方式进行记录,这个特性非常适合做灾难性的误删除的紧急恢复。比如某人不小心用flushall命令清空了所有数据,只要这个时候后台rewrite还没有发生,那么就可以立即拷贝AOF文件,将最后一条flushall命令给删了,然后再将该AOF文件放回去,就可以通过恢复机制,自动恢复所有数据

    4、AOF持久化机制的缺点

    (1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大

    (2)AOF开启后,支持的写QPS会比RDB支持的写QPS低,因为AOF一般会配置成每秒fsync一次日志文件,当然,每秒一次fsync,性能也还是很高的

    (3)以前AOF发生过bug,就是通过AOF记录的日志,进行数据恢复的时候,没有恢复一模一样的数据出来。所以说,类似AOF这种较为复杂的基于命令日志/merge/回放的方式,比基于RDB每次持久化一份完整的数据快照文件的方式,更加脆弱一些,容易有bug。不过AOF就是为了避免rewrite过程导致的bug,因此每次rewrite并不是基于旧的指令日志进行merge的,而是基于当时内存中的数据进行指令的重新构建,这样健壮性会好很多。

    RDB和AOF到底该如何选择

    (1)不要仅仅使用RDB,因为那样会导致你丢失很多数据

    (2)也不要仅仅使用AOF,因为那样有两个问题,第一,你通过AOF做冷备,没有RDB做冷备,来的恢复速度更快; 第二,RDB每次简单粗暴生成数据快照,更加健壮,可以避免AOF这种复杂的备份和恢复机制的bug

    (3)综合使用AOF和RDB两种持久化机制,用AOF来保证数据不丢失,作为数据恢复的第一选择; 用RDB来做不同程度的冷备,在AOF文件都丢失或损坏不可用的时候,还可以使用RDB来进行快速的数据恢复

  • 相关阅读:
    Spring进阶—如何用Java代码实现邮件发送(一)
    如何在Apache中使用PHP处理PHP文件
    最“高大上”的Spring测试:Spring Test
    【编程直播】来约吗?
    【PaPaPa】实现缓存决策
    【PaPaPa】系统架构搭建浅析
    【PaPaPa】集成B/S主流技术的MVC5项目
    【轮子狂魔】手把手教你自造Redis Client
    【轮子狂魔】抛弃IIS,打造个性的Web Server
    【轮子狂魔】抛弃IIS,向天借个HttpListener
  • 原文地址:https://www.cnblogs.com/fengkunangel/p/8970206.html
Copyright © 2011-2022 走看看