Redis数据库持久化

Posted 礁之

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis数据库持久化相关的知识,希望对你有一定的参考价值。

文章目录

一、Redis概述

  • Redis是一种高级键值对的非关系型数据库,同时也是一个高速缓存数据库

  • Redis和memcache很相似,不同的是,Redis的数据可以持久化,而且支持的数据类型很丰富

  • Redis的数据类型有字符串、列表、集合、有序集合,支持在服务器端计算集合的并、交和补(差)集,还支持多种排序功能,所以Redis也可以被看作是一个数据结构服务器

二、Redis的持久化

  • Redis的所有数据都是保存在内存中,如果没有配置持久化,Redis重启后数据就会丢失,所以需要开启Redis的持久化功能,将内存中的数据保存在硬盘上,在Redis重启之后,可以从硬盘中恢复数据到内存中,而这个过程是分为两种模式的:

半持久化模式:不定期的通过异步同步的方式把内存中的数据保存到硬盘上,也叫RDB模式

全持久化模式:把内存中每一次数据的变化都写入到一个append only file(AOF文件)里面,也叫AOF模式

(1)持久化过程

  1. 客户端向数据库服务器发送写操作,写的数据保存在客户端的内存中
  2. 数据库服务器接收到客户端写请求的操作,写操作的数据保存在服务器的内存中
  3. 服务器调用write这个系统进程,将内存中的数据往硬盘上写,数据会先到系统内存的缓冲区中
  4. 系统将缓冲区中的数据转移到磁盘控制器上,数据会到磁盘缓存中
  5. 磁盘控制器将数据写到磁盘的物理介质中,这个时候数据才是真正的保存到了磁盘中

上面的五个步骤是理想的数据保存流程,但是在大多数情况下,实际的服务器会有各种各样的故障,下面是出现故障后持久化成功的的两种情况

  1. Redis数据库发生故障,只需要完成上面的前三个步骤,那么就可以完成持久化,剩下的操作是由系统完成的
  1. 如果系统发生故障,就必须上面的五个步骤全部完成,数据才可以完成持久化

这两中情况只是说了保存过程中可能发生的故障,但是其实保存的数据也有可能发生损坏,需要一定的恢复机制

Redis有两种策略机制来实现持久化的五个步骤,分别是RDB和AOF,通过配置redis.conf主配置文件来配置两种持久化方式,两种持久化方式同时开启时,AOF的优先级高一点

(2)RDB机制

  • RDB的数据保存机制其实就是把数据以快照的形式保存在磁盘上,这个快照和虚拟机的快照的含义是相似的,需要注意的是每次生成的RDB文件会把旧的RDB文件顶掉,也就说只有一份RDB文件

  • RDB持久化是指在指定时间间隔内将内存中的数据集快照写入磁盘,也是Redis默认的持久化方式,这种方式就是将内存中的数据以快照的方式写入到二进制文件中,默认的文件名称为dump,rdb

  • 既然RDB的保存机制是指定时间间隔内把数据生成快照来保存,那么肯定会有一个触发机制,对于RDB来说,Redis提供了三种机制,分别是:save、bgsave、自动化

-save触发方式

当有一个客户端向Redis发送命令后,该命令会阻塞Redis服务器,在执行Save机制(保存数据到RDB文件)的过程中,Redis是不能执行其他命令的,直到保存完成后才可以

当Redis在保存RDB文件时,如果已经存在之前保存的RDB文件,那么Redis就会把新的文件顶替掉旧的文件,实际环境中,Redis接收到的客户端请求可能是几万甚至几十万,这种方式显然是不可取的

-bgsave触发方式

使用bgsave后,客户端发送的操作,Redis会在后台进行异步快照保存,而且Redis还可以继续接受其他客户端的操作

当客户端发送操作到Redis服务器时,在Redis执行操作后,会执行fork()操作创建子进程,RDB的持久化操作由子进程完成,在子进程完成操作后,会自动结束。这个过程中的阻塞只发生在子进程的阶段,基本上Redis内部所有的RDB操作都是采用bgsave完成的

-自动化

自动化也就是自动触发,是由Redis的主配置文件Redis.conf来完成的,可以配置如下选项:

  1. save:

这里是用来配置触发Redis的持久化条件的,也就是什么时候把内存中的数据保存到硬盘中,格式为save m n,当m秒之内发生了n个数据的变化,就把数据保存到硬盘中,并且采用机制是bgsave,如果不需要持久化可以把所有的save行注释掉来停用此功能

  1. stop-writes-on-bgsave-error:

此选项的默认配置为yes,意思是当启动了RDB并且在最后一次后台保存数据失败时,Redis是否停止接收数据,配置yes可以让管理人员意识到数据没有正确的持久化到硬盘上,否则配置no的话会使管理人员无法意识到事故发生。在停止接收数据后只需要重新启动Redis,就可以重新开始接收数据了

  1. rdbcompression

此选项的默认值为yes,意思是是否对存储到磁盘中的快照进行压缩存储

  1. rdbchecksum

此选项的默认值为yes,意思是在存储快照后,是否让redis使用crc64算法来进行数据校验,开启后会增加大约百分之十的性能消耗,如果需要redis达到最大性能,可以关闭此选项

  1. dbfilename

配置快照的文件名,默认是dump.rdb

  1. dir

设置快照保存的路径,这个路径必须是目录,而不是文件名,默认是保存到当前目录./

对比save和bgsave:

命令savebgsave
同步方式(IO类型)同步异步
是否阻塞阻塞阻塞(发生在子进程)
优点不会消耗额外内存不阻塞客户端,可以继续接收命令
缺点阻塞客户端命令需要子进程,消耗内存

-RDB的优势和劣势

  • 优势:
  1. RDB文件紧凑,并且是全量备份,非常适合用于备份和灾难恢复
  2. 在使用bgsave机制生成RDB文件的时候,redis主进程会新建一个子进程来处理所有的数据保存工作,主进程不需要进行任何的磁盘IO操作,并且可以继续接收其他客户端的操作
  3. RDB在恢复大数据集时的速度要比AOF快的
  • 劣势:
  1. 生成的RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,在存储上十分紧凑。
  2. 在进行快照持久化时,会开启一个子进程专门进行快照持久化,在这个期间主进程修改数据在子进程中是不会反应出来的,也就是说在数据持久化期间的数据不会被保存,可能会丢失数据。并且当数据集较大的时候,可以会导致整个服务器停止服务几百微秒甚至一秒

(3)AOF机制

  • 全量备份总是耗时的,而AOF提供了一种更为高效的方式,工作机制非常简单,redis会把收到的每一个写命令都通过write函数追加到指定的文件中,这个和mysql的二进制日志很是相似

  • AOF持久化方式:

每当Redis收到一条写命令时,Redis就会记录到AOF文件中

-文件重写

AOF的持久化方式也带来了一个问题,持久化的AOF文件会越来越大,为了压缩AOF持久化文件,Redis提供了bgrewriteaof命令,将当前内存中的数据以命令的方式保存到临时文件中时,同时会创建一个新的子进程来将文件重写到一个新的AOF文件中,这个方式有点类似于快照

-AOF的三种触发机制

  1. 每次修改都同步(always):同步持久化,每次数据发生变化时会被立刻记录到磁盘上,性能较差但是数据完整性好

  2. 每秒同步(everysec):异步同步,每秒都会记录,但是如果在一秒内Redis服务器宕机,那么就会丢失一秒的数据

  3. 从不同步(no):从不同步,这里指的是由系统决定什么时候同步

比对三种机制:

命令alwayseverysecno
优点不丢失数据每秒一次同步不用进行管理
缺点性能较差最多会丢失一秒的数据不可控制

-AOF的优点和缺点

  • 优点:
  1. AOF可以更好的保护数据不丢失,一般AOF会每隔一秒,然后通过一个后台线程执行一次同步操作,所以说最多丢失一秒的数据
  2. AOF日志文件没有任何磁盘寻址的开销(日志文件位置是自己指定的),写入性能非常高,文件不容易损坏
  3. AOF日志文件出现后台重写操作时,是不会影响客户端的读写的
  4. AOF日志文件是记录命令的,这个特性十分适合做灾难恢复性的误删除和紧急恢复,例如:某人不小心使用了flushall命令清空了所有数据,这个时候只要重写操作没有发生,就可以立即拷贝AOF文件,删除最后一条的flushall命令然后再把AOF文件放回去,就可以通过恢复机制,恢复数据库
  • 缺点:
  1. 对于同一份数据来说,AOF的文件通常要比RDB的快照文件更大
  2. AOF开启后,支持的写的QPS(每秒查询率)会比RDB写的QPS低,因为AOF一般都会配置成每秒同步一次文件,当然,每秒一次的同步,性能消耗也不会很高

(4)选择RDB还是AOF

  1. 愿意牺牲一些性能的,可以选择AOF
  2. 换取更高的缓存一致性,保证数据库最高可能的完整性,选择AOF
  3. 愿意写操作频繁的时候,不启用备份来换取更高的性能,在手动运行save的时候再做备份,选择RDB

通常来说两者一起使用效果是最好的,但是同时开启两种方式的话,只有AOF会生效,Redis默认使用RDB,AOF配合RDB时,两者开启可以手动运行save

三、RDB持久化配置

准备Reids:

[root@Centos7 ~]# vim /usr/local/redis/redis.conf 
。。。。。。
 217 
 218 save 900 1      #开启RDB后,在900秒内发生1个数据的变化就触发生成快照
 219 save 300 10
 220 save 60 10000
 221 
。。。。。。
 234 # permissions, and so forth.
 235 stop-writes-on-bgsave-error yes  #当RDM快照失败后,不影响用户得写操作
 236 
。。。。。。
 240 # the dataset will likely be bigger if you have compressible values or keys.
 241 rdbcompression yes  #是否将RDB快照文件压缩,关闭后会增加性能
 242 
。。。。。。
 250 rdbchecksum no   #关闭RDB快照的检查校验,会增加性能
 251  
 252 # The filename where to dump the DB
 253 dbfilename dump.rdb  #快照的名称
 254 
。。。。。。
 262 # Note that you must specify a directory here, not a file name.
 263 dir /usr/local/redis/rdb   #快照的存放路径
 264 
。。。。。。
#保存退出
[root@Centos7 ~]# mkdir /usr/local/redis/rdb
[root@Centos7 ~]# /etc/init.d/redis start   #开启redis
/var/run/redis_6379.pid exists, process is already running or crashed
Redis is running...
[root@Centos7 ~]# redis -h 192.168.100.202 -p 6379  #进入redis写数据
192.168.100.202:6379> auth 123123
OK
192.168.100.202:6379> set aaa bbb
OK
192.168.100.202:6379> set bbb ccc
OK
192.168.100.202:6379> keys *
1) "aaa"
2) "bbb"
192.168.100.202:6379> exit
[root@Centos7 ~]# /etc/init.d/redis restart   #重启redis
Stopping ...
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Redis stopped
Starting Redis server...
1073:C 05 Jun 2021 21:54:27.156 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1073:C 05 Jun 2021 21:54:27.156 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1073, just started
1073:C 05 Jun 2021 21:54:27.156 # Configuration loaded
Redis is running...
[root@Centos7 ~]# redis -h 192.168.100.202 -p 6379  #再次进入查看数据还在不在
192.168.100.202:6379> auth 123123
OK
192.168.100.202:6379> keys * 
1) "aaa"
2) "bbb"
 #发现数据存在,redis的数据是存放到内存的,不配置持久化的话,重启redis数据就会丢失,但是开启了RDB持久化机制,并且配置文件中配置了每600秒发生一次数据的变化就拍摄快照,刚才写了两个数据,写完之后Redis其实已经拍摄完快照并且保存在指定路径下,所以在重启Redis后数据还是存在的
 192.168.100.202:6379> exit
[root@Centos7 ~]# ll /usr/local/redis/rdb/
总用量 4
-rw-r--r-- 1 root root 115 65 21:54 dump.rdb

四、AOF持久化配置

[root@Centos7 ~]# vim /usr/local/redis/redis.conf 
。。。。。。
 217 
 218 #save 900 1     #把save向全部注释表示关闭RDB持久化方式
 219 #save 300 10
 220 #save 60 10000
 221 
。。。。。。
 262 # Note that you must specify a directory here, not a file name.
 263 dir /usr/local/redis/rdb   #这个同时也是AOF文件的存放路径
 264 
。。。。。。
 698 
 699 appendonly yes  #开启AOF持久化方式
 700 
 701 # The name of the append only file (default: "appendonly.aof")
 702 
 703 appendfilename "appendonly.aof"  #设置持久化的文件
 704 
。。。。。。
 728 # appendfsync always
 729 appendfsync everysec  #设置AOF持久化的方式,默认就是everysec每秒一次
 730 # appendfsync no
 731 
。。。。。。
 750 
 751 no-appendfsync-on-rewrite no  #如果设置为yes,则redis执行的命令会存放到缓冲区,等待系统自动同步到硬盘,no就可以
 752 
。。。。。。
 769 
 770 auto-aof-rewrite-percentage 100  #若当前写入的AOF文件达到了上次重写文件的大小的100%的话,就触发重写
 771 auto-aof-rewrite-min-size 64mb  #设置AOF持久化重写文件大小的最小值,当达到64MB并且符合100%时,就触发重写操作
 772 
。。。。。。
#保存退出
[root@Centos7 ~]# /etc/init.d/redis restart 
Stopping ...
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Redis stopped
Starting Redis server...
1122:C 05 Jun 2021 22:08:19.456 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
1122:C 05 Jun 2021 22:08:19.456 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=1122, just started
1122:C 05 Jun 2021 22:08:19.456 # Configuration loaded
Redis is running...
[root@Centos7 ~]# redis -h 192.168.100.202 -p 6379
192.168.100.202:6379> auth 123123
OK
192.168.100.202:6379> keys *
(empty list or set)
192.168.100.202:6379> set aaa bbb
OK
192.168.100.202:6379> keys *
1) "aaa"
192.168.100.202:6379> set bbb ccc
OK
192.168.100.202:6379> keys *
1) "bbb"
2) "aaa"
192.168.100.202:6379> exit
[root@Centos7 ~]# cat /usr/local/redis/rdb/appendonly.aof   #可以看到AOF文件中全部都是执行过的命令
*2
$6
SELECT
$1
0
*3
$3
set
$3
aaa
$3
bbb
*3
$3
set
$3
bbb
$3
ccc

以上是关于Redis数据库持久化的主要内容,如果未能解决你的问题,请参考以下文章

大厂面试06期谈一谈你对Redis持久化的理解?

8. Redis 持久化对生产环境的灾难恢复的意义

Redis主从复制机制详解

带你走进Redis的世界 - Redis的持久化

Redis持久化磁盘IO方式及其带来的问题   有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是基于快照方式持

redis-- redis的持久化(作为数据库)