草庐IT

redis的持久化存储

gy001 2023-03-28 原文

  Redis虽然是一个内存级别的缓存程序,也就是redis是使用内存进行数据的缓存的,但是其可以将内存的数据按照一定的策略保存到硬盘中,这样的话就可以实现持久保存的目的;目前的话redis支持的两种不同方式的数据持久化保存机制,分别是RDB和AOF,这两种方式的话很类似于MySQL数据库的dump和二进制日志的方式。

1、RBD模式 

1.1、RDB模式的工作原理

 

RDB(Redis DataBase):基于时间的快照,其默认只保留当前最新的一次快照,特点是执行速度比较快,缺点是可能会丢失从上次快照到当前的时间点未做快照的数据。

1.2、RDB bgsave实现快照的具体过程

 

Redis从master主进程先fork出一个子进程,使用写时复制机制,子进程将内存的数据保存为一个临时文件,比如dump.rdb,当数据保存完后在将上一次保存的RDB文件替换掉,然后就会关掉子进程,这样可以保证每一次做RDB快照保存的数据都是完整的;因为直接替换RDB文件的时候,可能会出现突然断电等问题,从而导致RDB文件还没有保存完整就因为突然关机停止保存,并会出现导致数据丢失的情况。后续的话是可以手动将每次生成的RDB文件进行备份,这样的话就可以最大化的来保存历史数据。

1.3、RDB的相关配置

#在配置文件中的 save 选项设置多个保存条件,只有任何一个条件满足,服务器都会自动执行 BGSAVE 命令
save 900 1         #900s内修改了1个key即触发保存RDB
save 300 10        #300s内修改了10个key即触发保存RDB
save 60 10000      #60s内修改了10000个key即触发保存RDB
dbfilename dump.rdb
dir ./             #编泽编译安装时默认RDB文件存放在Redis的工作目录,此配置可指定保存的数据目录
stop-writes-on-bgsave-error yes  #当快照失败是否仍允许写入,yes为出错后禁止写入,建议为no
rdbcompression yes
rdbchecksum yes

1.4实现RBD的方法

  • save: 同步,不推荐使用,使用主进程完成快照,因此会阻赛其它命令执行
  • bgsave: 异步后台执行,不影响其它命令的执行,会开启独立的子进程,因此不会阻赛其它命令执行
  • 配置文件实现自动保存: 在配置文件中制定规则,自动执行bgsave

 1.4、自动备份的方式

  • 使用自动备份方式的话是需要在redis配置文件中指定规则,当在redis配置中规则后,触发了规则后就会自动执行。
[root@node1 ~]#grep '^save' /apps/redis/etc/redis.conf
save 900 1   #900秒内更改一条及以上信息即自动备份
save 300 10 #300秒内更改十条及以上信息即自动备份
save 60 10000 #60秒内更改一万条及以上信息即自动备份

1.5、RDB模式的优缺点

RDB模式优点:

  • RDB快照保存了某个时间点的数据,可以通过脚本执行redis指令bgsave(非阻塞,后台执行)或者save(会阻塞写操作,不推荐)命令自定义时间点备份,可以保留多个备份,当出现问题可以恢复到不同时间点的版本,很适合备份,并且此文件格式也支持有不少第三方工具可以进行后续的数据分析;比如: 可以在最近的24小时内,每小时备份一次RDB文件,并且在每个月的每一天,也备份一个RDB文件。这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。
  • RDB可以最大化Redis的性能,父进程在保存 RDB文件时唯一要做的就是fork出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。
  • RDB在大量数据,比如几个G的数据,恢复的速度要比AOF的快。

RDB模式缺点:

  • 不能实时保存数据,可能会丢失上次执行RDB备份到当前的内存数据。当你需要实时保存数据时,那么你就要尽量避免在服务器故障时丢失数据,这样的话RDB就不适合使用了。虽然Redis允许设置不同的保存点(save point)来控制保存RDB文件的频率,但是,因为RDB文件需要保存整个数据集的状态,所以它并不是一个轻松快速的操作。因此一般会超过5分钟以上才保存一次RDB文件。在这种情况下,一旦发生故障停机,你就可能会丢失好几分钟的数据。
  • 当数据量非常大时,从父进程fork子进程进行保存至RDB文件是需要一点时间的,可能是毫秒或者是秒,这个是取决于磁盘的IO性能。在数据集比较庞大时,fork()可能会非常耗时,造成服务器在一定时间内停止处理客户端﹔如果数据集非常巨大,并且CPU时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒或更久。虽然AOF重写也需要进行fork(),但无论AOF重写的执行间隔有多长,数据的持久性都不会有任何损失。

2、AOF模式

2.1、AOF模式工作原理

 

  • AOF:AppendOnylFile,按照操作顺序依次将操作追加到指定的日志文件末尾
  • AOF和RDB一样使用了写时复制机制,AOF默认为每秒钟 fsync一次,即将执行的命令保存到AOF文件当中,这样即使redis服务器发生故障最多只丢失1秒钟之内的数据,也可以设置不同的fsync策略always,即设置每次执行命令的时候执行fsync,fsync会在后台执行线程,所以主线程可以继续处理用户的正常请求而不受到写入AOF文件的I/O影响
  • 同时启用RDB和AOF,进行恢复时,默认AOF文件优先级高于RDB文件,即会使用AOF文件进行恢复

 

 注意事项:AOF模式默认是关闭的,第一次开启AOF后,并重启服务生效后,会因为AOF的优先级高于RDB,而AOF默认没有数据文件存在,从而导致所有数据丢失,因此所以要使用正确的方法来开启AOF,以防数据丢失。

2.2、AOF相关配置

appendonly no #是否开启AOF日志记录,默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了,但是redis如果中途宕机,会导致可能有几分钟的数据丢失(取决于dump数据的间隔时间),根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性,Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。默认不启用此功能

appendfilename "appendonly.aof" #文本文件AOF的文件名,存放在dir指令指定的目录中

appendfsync everysec #aof持久化策略的配置
#no表示由操作系统保证数据同步到磁盘,Linux的默认fsync策略是30秒,最多会丢失30s的数据
#always表示每次写入都执行fsync,以保证数据同步到磁盘,安全性高,性能较差
#everysec表示每秒执行一次fsync,可能会导致丢失这1s数据,此为默认值,也生产建议值
dir /path

#rewrite相关
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes

2.2.1动态设置(建议使用的方式)

#这时aof是没有开启的
[root@node1 ~]#grep '^append' /apps/redis/etc/redis6379.conf
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec

#把data文件夹所有者所有组设为redis
[root@node1 ~]#ll /apps/redis/data
total 1452
drwxr-xr-x 2 redis redis    4096 Nov  2 13:13 ./
drwxr-xr-x 7 redis redis    4096 Oct 31 15:41 ../
-rw-r--r-- 1 redis redis 1477882 Nov  2 13:13 dump6379.rdb
[root@node1 ~]#systemctl restart redis6379.service

#进入客户端设置
[root@node1 ~]#redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> dbsize
(integer) 100000
127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "no"
127.0.0.1:6379> config set appendonly yes
OK
127.0.0.1:6379> config get appendonly
1) "appendonly"
2) "yes"    

 

 

 2.3、AOF rewrite重写

 将一些重复的、可以合并的、过期的数据重新写入一个新的AOF文件,这样的话可以节约AOF备份占用的硬盘空间,也是可以加速恢复过程。可以手动执行bgrewriteaof触发AOF,第一次开启AOF功能,或定义自动rewrite策略。

 

 

 2.4、AOF模式的优缺点

AOF模式的优点:

  • 数据安全性相对较高,根据所使用的fsync策略(fsync是同步内存中redis所有已经修改的文件到存储设备),默认是appendfsync everysec,即每秒执行一次fsync,在这种配置下,Redis仍然可以保持良好的性能,并且就算发生故障停机,也最多只会丢失一秒钟的数据(fsync会在后台线程执行,所以主线程可以继续努力地处理命令请求)
  • 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中不需要seek, 即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,可以通过redis-check-aof工具来解决数据一致性的问题。
  • Redis可以在AOF文件体积变得过大时,自动地在后台对AOF进行重写,重写后的新AOF文件包含了恢复当前数据集所需的最小命令集合。整个重写操作是绝对安全的,因为Redis在创建新AOF文件的过程中,append模式不断的将修改数据追加到现有的 AOF文件里面,即使重写过程中发生停机,现有的 AOF文件也不会丢失。而一旦新AOF文件创建完毕,Redis就会从旧AOF文件切换到新AOF文件,并开始对新AOF文件进行追加操作。

  • AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,也可以通过该文件完成数据的重建;
    AOF文件有序地保存了对数据库执行的所有写入操作,这些写入操作以Redis协议的格式保存,因此 AOF文件的内容非常容易被人读懂,对文件进行分析(parse)也很轻松。导出(export)AOF文件也非常简单:举个例子,如果不小心执行了FLUSHALL.命令,但只要AOF文件未被重写,那么只要停止服务器,移除 AOF文件末尾的FLUSHAL命令,并重启Redis,就可以将数据集恢复到FLUSHALL执行之前的状态。

AOF模式缺点:

  • 即使有些操作是重复的也会全部记录,AOF的文件大小要大于RDB格式的文件;
  • AOF在恢复大数据集时的速度比RDB的恢复速度要慢;
  • 根据fsync策略不同,AOF速度可能会慢于RDB;
  • bug出现的可能性会更多

3、RDB模式和AOF模式的选择

  • 如果注意是来充当缓存功能,或者可以承受短暂时间的数据丢失,通常生产环境一般只需要开启RDB就可以了,启用RDB也是默认值。
  • 如果数据需要持久化保存,有点也不可以丢失的话,就可以选择开启RDB和AOF。
  • 一般不会只开启AOF的,这样操作也是不建议的。

 

有关redis的持久化存储的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  3. ruby - Rack:如何将 URL 存储为变量? - 2

    我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.

  4. ruby-on-rails - 为什么在 Rails 5.1.1 中删除了 session 存储初始化程序 - 2

    我去了这个website查看Rails5.0.0和Rails5.1.1之间的区别为什么5.1.1不再包含:config/initializers/session_store.rb?谢谢 最佳答案 这是删除它的提交:Setupdefaultsessionstoreinternally,nolongerthroughanapplicationinitializer总而言之,新应用没有该初始化器,session存储默认设置为cookie存储。即与在该初始值设定项的生成版本中指定的值相同。 关于

  5. ruby-on-rails - 尝试设置 Amazon 的 S3 存储桶 : 403 Forbidden error & setting permissions - 2

    我正在关注Hartl的railstutorial.org并已到达11.4.4:Imageuploadinproduction.我做了什么:注册亚马逊网络服务在AmazonIdentityandAccessManagement中,我创建了一个用户。用户创建成功。在AmazonS3中,我创建了一个新存储桶。设置新存储桶的权限:权限:本教程指示“授予上一步创建的用户读写权限”。但是,在存储桶的“权限”下,未提及新用户名。我只能在每个人、经过身份验证的用户、日志传送、我和亚马逊似乎根据我的名字+数字创建的用户名之间进行选择。我已经通过选择经过身份验证的用户并选中了上传/删除和查看权限的框(而不

  6. ruby - 如何打印出 Mechanized 存储的 cookie? - 2

    我正在使用mechanize登录网站,然后检索页面。我遇到了一些问题,我怀疑这是由于cookie中的某些值造成的。当Mechanize登录网站时,我假设它存储了cookie。如何通过Mechanize打印出存储在cookie中的所有数据? 最佳答案 代理有一个cookie方法。agent=Mechanize.newpage=agent.get("http://www.google.com/")agent.cookiesagent.cookies.to_scookie返回一个Mechanize::Cookiesobject

  7. ruby-on-rails - 闪存消息存储在哪里? - 2

    我以为它们存储在cookie中-但不,检查cookie没有任何结果。session也不存储它们。那么,我在哪里可以找到它们?我需要这个来直接设置它们(而不是通过flashhash)。 最佳答案 它们存储在inyoursessionstore.自rails2.0以来的默认设置是cookie存储,但请检查config/initializers/session_store.rb以检查您是否使用默认设置以外的东西。 关于ruby-on-rails-闪存消息存储在哪里?,我们在StackOverf

  8. ruby-on-rails - 在 Rails 中存储(结构化)配置数据的位置 - 2

    对于我正在编写的Rails3应用程序,我正在考虑从本地文件系统上的XML、YAML或JSON文件中读取一些配置数据。重点是:我应该把这些文件放在哪里?Rails应用程序中是否有用于存储此类内容的默认位置?附带说明一下,我的应用程序部署在Heroku上。 最佳答案 我经常做的是:如果文件是通用配置文件:我在目录/config中创建一个YAML文件,每个环境有一个上层key如果我为每个环境(大项目)创建一个文件:我为每个环境创建一个YAML并将它们存储在/config/environments/然后我在加载YAML的地方创建了一个初始化

  9. ruby - 如何存储和读取 RubyVM::InstructionSequence? - 2

    有没有办法将RubyVM::InstructionSequence存储到文件中并稍后读取?我尝试了Marshal.dump但没有成功。我收到以下错误:`dump':no_dump_dataisdefinedforclassRubyVM::InstructionSequence(TypeError) 最佳答案 是的,有办法。首先,您需要使InstructionSequence的load方法可访问,默认情况下该方法是禁用的:require'fiddle'classRubyVM::InstructionSequence#RetrieveR

  10. ruby-on-rails - 如何解析位于 Amazon S3 存储桶中的 CSV 文件 - 2

    下面是我用来从应用程序中解析CSV的代码,但我想解析位于AmazonS3存储桶中的文件。当推送到Heroku时它也需要工作。namespace:csvimportdodesc"ImportCSVDatatoInventory."task:wiwt=>:environmentdorequire'csv'csv_file_path=Rails.root.join('public','wiwt.csv.txt')CSV.foreach(csv_file_path)do|row|p=Wiwt.create!({:user_id=>row[0],:date_worn=>row[1],:inven

随机推荐