一、Redis概述
Redis是一种高级键值对的非关系型数据库,同时也是一个高速缓存数据库
Redis和memcache很相似,不同的是,Redis的数据可以持久化,而且支持的数据类型很丰富
Redis的数据类型有字符串、列表、集合、有序集合,支持在服务器端计算集合的并、交和补(差)集,还支持多种排序功能,所以Redis也可以被看作是一个数据结构服务器
二、Redis的持久化
Redis的所有数据都是保存在内存中,如果没有配置持久化,Redis重启后数据就会丢失,所以需要开启Redis的持久化功能,将内存中的数据保存在硬盘上,在Redis重启之后,可以从硬盘中恢复数据到内存中,而这个过程是分为两种模式的:
半持久化模式:不定期的通过异步同步的方式把内存中的数据保存到硬盘上,也叫RDB模式
全持久化模式:把内存中每一次数据的变化都写入到一个append only file(AOF文件)里面,也叫AOF模式
(1)持久化过程
- 客户端向数据库服务器发送写操作,写的数据保存在客户端的内存中
- 数据库服务器接收到客户端写请求的操作,写操作的数据保存在服务器的内存中
- 服务器调用write这个系统进程,将内存中的数据往硬盘上写,数据会先到系统内存的缓冲区中
- 系统将缓冲区中的数据转移到磁盘控制器上,数据会到磁盘缓存中
- 磁盘控制器将数据写到磁盘的物理介质中,这个时候数据才是真正的保存到了磁盘中
上面的五个步骤是理想的数据保存流程,但是在大多数情况下,实际的服务器会有各种各样的故障,下面是出现故障后持久化成功的的两种情况
Redis数据库发生故障,只需要完成上面的前三个步骤,那么就可以完成持久化,剩下的操作是由系统完成的
如果系统发生故障,就必须上面的五个步骤全部完成,数据才可以完成持久化
这两中情况只是说了保存过程中可能发生的故障,但是其实保存的数据也有可能发生损坏,需要一定的恢复机制
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来完成的,可以配置如下选项:
save:
这里是用来配置触发Redis的持久化条件的,也就是什么时候把内存中的数据保存到硬盘中,格式为save m n,当m秒之内发生了n个数据的变化,就把数据保存到硬盘中,并且采用机制是bgsave,如果不需要持久化可以把所有的save行注释掉来停用此功能
stop-writes-on-bgsave-error:
此选项的默认配置为yes,意思是当启动了RDB并且在最后一次后台保存数据失败时,Redis是否停止接收数据,配置yes可以让管理人员意识到数据没有正确的持久化到硬盘上,否则配置no的话会使管理人员无法意识到事故发生。在停止接收数据后只需要重新启动Redis,就可以重新开始接收数据了
rdbcompression
此选项的默认值为yes,意思是是否对存储到磁盘中的快照进行压缩存储
rdbchecksum
此选项的默认值为yes,意思是在存储快照后,是否让redis使用crc64算法来进行数据校验,开启后会增加大约百分之十的性能消耗,如果需要redis达到最大性能,可以关闭此选项
dbfilename
配置快照的文件名,默认是dump.rdb
dir
设置快照保存的路径,这个路径必须是目录,而不是文件名,默认是保存到当前目录./
对比save和bgsave:
命令 | save | bgsave |
同步方式(IO类型) | 同步 | 异步 |
是否阻塞 | 阻塞 | 阻塞(发生在子进程) |
优点 | 不会消耗额外内存 | 不阻塞客户端,可以继续接收命令 |
缺点 | 阻塞客户端命令 | 需要子进程,消耗内存 |
-RDB的优势和劣势
- 优势:
- RDB文件紧凑,并且是全量备份,非常适合用于备份和灾难恢复
- 在使用bgsave机制生成RDB文件的时候,redis主进程会新建一个子进程来处理所有的数据保存工作,主进程不需要进行任何的磁盘IO操作,并且可以继续接收其他客户端的操作
- RDB在恢复大数据集时的速度要比AOF快的
- 劣势:
生成的RDB快照是一次全量备份,存储的是内存数据的二进制序列化形式,在存储上十分紧凑。
在进行快照持久化时,会开启一个子进程专门进行快照持久化,在这个期间主进程修改数据在子进程中是不会反应出来的,也就是说在数据持久化期间的数据不会被保存,可能会丢失数据。并且当数据集较大的时候,可以会导致整个服务器停止服务几百微秒甚至一秒
(3)AOF机制
- 全量备份总是耗时的,而AOF提供了一种更为高效的方式,工作机制非常简单,redis会把收到的每一个写命令都通过write函数追加到指定的文件中,这个和mysql的二进制日志很是相似
- AOF持久化方式:
每当Redis收到一条写命令时,Redis就会记录到AOF文件中
-文件重写
AOF的持久化方式也带来了一个问题,持久化的AOF文件会越来越大,为了压缩AOF持久化文件,Redis提供了bgrewriteaof命令,将当前内存中的数据以命令的方式保存到临时文件中时,同时会创建一个新的子进程来将文件重写到一个新的AOF文件中,这个方式有点类似于快照
-AOF的三种触发机制
每次修改都同步(always):同步持久化,每次数据发生变化时会被立刻记录到磁盘上,性能较差但是数据完整性好
每秒同步(everysec):异步同步,每秒都会记录,但是如果在一秒内Redis服务器宕机,那么就会丢失一秒的数据
从不同步(no):从不同步,这里指的是由系统决定什么时候同步
比对三种机制:
命令 | always | everysec | no |
优点 | 不丢失数据 | 每秒一次同步 | 不用进行管理 |
缺点 | 性能较差 | 最多会丢失一秒的数据 | 不可控制 |
-AOF的优点和缺点
优点:
AOF可以更好的保护数据不丢失,一般AOF会每隔一秒,然后通过一个后台线程执行一次同步操作,所以说最多丢失一秒的数据
AOF日志文件没有任何磁盘寻址的开销(日志文件位置是自己指定的),写入性能非常高,文件不容易损坏
AOF日志文件出现后台重写操作时,是不会影响客户端的读写的
AOF日志文件是记录命令的,这个特性十分适合做灾难恢复性的误删除和紧急恢复,例如:某人不小心使用了flushall命令清空了所有数据,这个时候只要重写操作没有发生,就可以立即拷贝AOF文件,删除最后一条的flushall命令然后再把AOF文件放回去,就可以通过恢复机制,恢复数据库
缺点:
对于同一份数据来说,AOF的文件通常要比RDB的快照文件更大
AOF开启后,支持的写的QPS(每秒查询率)会比RDB写的QPS低,因为AOF一般都会配置成每秒同步一次文件,当然,每秒一次的同步,性能消耗也不会很高
(4)选择RDB还是AOF
- 愿意牺牲一些性能的,可以选择AOF
- 换取更高的缓存一致性,保证数据库最高可能的完整性,选择AOF
- 愿意写操作频繁的时候,不启用备份来换取更高的性能,在手动运行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 6月 5 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