Redis
是将数据存储到内存中.我们在玩游戏的时候,通常会感到电脑卡.因为游戏占用了很多的内存.但是我们重启电脑后,电脑就不再卡了.是因为重启释放了内存资源.那我们将Redis
存储到内存中,如果不进行数据的持久化(说白了就是将内存的数据存储到硬盘中),重启计算机或者redis服务突然挂掉就会造成数据的丢失.
持久化方式
- 快照 : 相当于给数据库拍一张照片,将所有的数据都拷贝出来.做一个完整的备份.例如
mysql中的dump
,redis中的RDB
都类似于快照这种方式. - 记录日志 : 将数据库中的更新记录在日志中,将数据恢复的时候.只需要把日志拿出来.将日志的命令重新执行一遍.得到某时某店的完整数据变化.例如
mysql中的Binlog
,redis中的AOF
.
RDB
什么是RDB
在redis
执行命令将内存中完整的数据保存到一个二进制的RDB文件.redis
重启,可以通过夹在RDB文件进行数据的恢复.
触发机制
一共有六种触发机制,save
,bgsave
,自动生成
,主从复制
,debug reload
和shut down
.
save
通过命令save
开始进行数据备份.但是save是同步执行的
.也就是说当你开始进行save
后如果接着客户端get key
,必须等save
结束后才能继续执行后面的命令.
bgsave
通过命令bgsave
开始进行数据备份,bgsave
是异步任务.当执行命令后,会立刻返回ok
,然后redis通过linux的fork()开启新的子进程进行数据备份
.子进程去创建RDB文件,生成成功后会返回主进程dgsave successful
.执行fork
的速度是非常快的,所以相当于异步,但也不能完全算是异步.因为fork
如果慢的话也会阻塞主进程.此时访问redis
会正常放回结果,无需等待.
自动生成
在默认的redis.conf
中有默认的自动触发生成文件的配置.三条配置位save 900 1
,save 300 10
,`save 60 10000
.当满足上述任一一个条件后,会自动进行文件备份.当900s 改变了一条;当300s改变了10条,当60s改变了10000条.
是无法控制redis的修改量,因为请求/用户一多,必然会造成大批量的修改.也就是无法控制生成文件的频率.频繁对大文件写入文件肯定是非常消耗资源和硬盘的.不是一种很好的方式.
# 默认配置
save 900 1
save 300 10
save 10 10000
# rdb文件名
dbfilename dump.rbd
# 存放路径位当前路径
dir ./
# dbsave出现错误是否停止写入
stop-writes-on-bgsave-error yes
# rdb文件是否采用压缩格式
rdbcompression yes
# 是否对rdb文件进行检验
rdbchecksum yes
# 建议
1. 不配置save
2. 修改文件存放路径
主从复制
当redis进行主从复置的时候会.祝服务器会生成rdb文件.
debug reload
debug reload 不讲数据进行清空的重启
shutdown
shutdown 关闭会自动执行shutdown save生成rdb文件
save vs bgsave
IO类型 | 是否阻塞 | 优点 | 缺点 | |
---|---|---|---|---|
save | 同步 | 是 | 不消耗额外资源 | 阻塞客户端命令 |
bgsave | 异步 | 是(发生在fork) | 不阻塞客户端命令(fork不出问题) | 消耗额外资源 |
文件策略
save
和dbsave
生成的文件都会以新的替换旧的.在执行过程中会生成一个临时文件,执行完成后会替换掉老的文件.
测试
save
是否会阻塞# 修改新的配置 cp redis_6379.conf redis_rdb.conf vim redis_rdb.conf # 添加 # save 900 1 # save 300 10 # save 60 10000 stop-writes-on-bgsave-error yes rdbcompression yes rdbchecksum yes dbfilename dump-6379.rdb # 保存启动服务 redis-server redis_rdb.conf # 脚本批量生成1000万条数据 127.0.0.1:6379> dbsize (integer) 10000000 # 查看使用内存959.66MB 127.0.0.1:6379> info memory # Memory used_memory:1006277712 used_memory_human:959.66M # 设置qvbilam 127.0.0.1:6379> set qvbilam angel OK # 打开第二个端口执行save.第一个端口执行get # get和save都在等待...很慢... [root@bogon test]# redis-cli 127.0.0.1:6379> save OK (152.59s) 127.0.0.1:6379> get qvbilam "angel" (150.63s) # 可以看到等待了150s!!! # 文件压缩1006277712->317777896 -rw-r--r--. 1 root root 317777896 6月 27 11:42 dump-6379.rdb
bgsave
是否开启子进程.是否阻塞# 查看当前redis进程 [root@bogon data]# lsof -i:6379 COMMAND PID USER FD TYPE DEVICE redis-ser 62792 root 6u IPv6 3904775 redis-ser 62792 root 7u IPv4 3904776 redis-ser 62792 root 8u IPv4 3905341 redis-ser 62792 root 9u IPv4 3909079 redis-cli 62883 root 3u IPv4 3905340 redis-cli 63494 root 3u IPv4 3909078 # bgsave 立即返回 127.0.0.1:6379> bgsave Background saving started # 另一个client立刻返回 127.0.0.1:6379> get qvbilam "angel" # 多了一个进程 [root@bogon data]# lsof -i:6379 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME redis-ser 62792 root 6u IPv6 3904775 0t0 TCP *:6379 (LISTEN) redis-ser 62792 root 7u IPv4 3904776 0t0 TCP *:6379 (LISTEN) redis-ser 62792 root 8u IPv4 3905341 redis-ser 62792 root 9u IPv4 3909079 redis-cli 62883 root 3u IPv4 3905340 redis-cli 63494 root 3u IPv4 3909078 redis-ser 66969 root 8u IPv4 3905341 redis-ser 66969 root 9u IPv4 3909079 # 还在执行,可以看到临时文件还没有替换dump -rw-r--r--. 1 root root 317777896 6月 27 11:42 dump-6379.rdb -rw-r--r--. 1 root root 259260459 6月 27 11:59 temp-66969.rdb # 执行结束 -rw-r--r--. 1 root root 317777896 6月 27 11:59 dump-6379.rdb # 看日志 46 62792:M 27 Jun 2019 11:35:43.499 * DB loaded from disk: 0.722 seconds 47 62792:M 27 Jun 2019 11:35:43.500 * Ready to accept connections 48 62792:M 27 Jun 2019 11:42:16.608 * DB saved on disk 49 62792:M 27 Jun 2019 11:56:35.613 * Background saving started by pid 66969 50 66969:C 27 Jun 2019 11:59:30.522 * DB saved on disk 51 66969:C 27 Jun 2019 11:59:30.544 * RDB: 0 MB of memory used by copy-on-write 52 62792:M 27 Jun 2019 11:59:30.649 * Background saving terminated with success
save
自动生成配置文件# 修改save配置 vim config/redis_rdb.conf # 修改或添加 save 60 5 //50秒内修改5次自动保存 # 保存重启服务 redis-server config/redis_rdb.conf # 查看rdb文件时间 6月 27 11:59 dump-6379.rdb # 快速修改5条 127.0.0.1:6379> set q w OK 127.0.0.1:6379> set w e OK 127.0.0.1:6379> set e r OK 127.0.0.1:6379> set r t OK 127.0.0.1:6379> set t f OK # 查看日志满足5条,自动备份 12:13:36.875 * 5 changes in 60 seconds. Saving... 12:13:36.886 * Background saving started by pid 70373 # rdb文件时间 6月 27 12:14 temp-70373.rdb
RDB缺点
RDB
方式的缺点:耗时,耗性能,不可控制,数据容易丢失.例如:在第一步执行多个写入命令,第二步骤满足RDB自动创建条件,开始写文件,第三部再次执行多个写入命令个,第四部出现宕机.那么第三部到第四部之间的数据写入就会丢失.就算用脚本定时执行.也无法保证出现宕机的情况.
AOF
相当于记录每次的命令到日志.比如在客户端执行一条增删改命令,就在日志文件中追加该命令.当使用RDB
出现宕机的情况,就可以采用AOF
对数据进行完整的恢复.当redis
重启后,将AOF
文件载入从而进行数据的恢复.写文件的机制是将命令写到硬盘的缓冲区.redis再通过内部命令刷新到磁盘.从而提高写入的效率(因为直接写入到磁盘效率很慢).
三种策略
配置 | 说明 | 优点 | 缺点 |
---|---|---|---|
always | 每条命令都会刷新到磁盘中 | 不丢失数据 | IO开销很大 |
everysec(推荐) | 将每秒产生的命令刷新到磁盘中,默认值是1秒 | 每秒进行sync,只丢失一秒间产生的数据 | 丢一秒数据(如果一秒内写入量很大) |
No(不推荐) | 根据操作系统决定,不需要去管 | 不用管 | 不可控,也不知道丢多少数据 |
AOF重写
原生的AOF就是将每条命令都执行,假如有一个ke执行自增+1,一下加了1万次.那么在AOF中就相当于写了1万条的自增,这是非常占用资源,而且恢复速度也会因为执行1万次而变慢的.当使用了AOF重写
就解决了这样的问题.AOF重写
实现有两种方式.即gbrewirteaof
和AOF重写配置
.AOF重写并不是真的将原来的AOF文件进行归类重写.其实就是将内存的数据进行一次回溯,回溯成AOF文件
.
gbrewirteaof
实现方式:创建子进程对AOF重写的过程,类似于bgsave
重写RDB
.
重写配置说明
当达到两个条件才会进行AOF重写,必须是同时满足才会尽心!
- aof_corrent_size > auto-aof-rewrite-min-size,当前文件尺寸大于配置中设置的AOF文件最小大小.就满足条件1
- (aof_corrent_size - aof_base_size) / aof_base_size > auto-aof-rewrite-percentage,当前文件大小减去重启前(上次重写)的大小就等于增长了AOF的大小.再用增长的大小除以上次重写的大小就是增长率.当增长率大于配置中的增长率.就属于满足条件2.
配置名 | 说明 |
---|---|
auto-aof-rewrite-min-size | AOF文件大小,达到多少开始重写 |
auto-aof-rewrite-percentage | AOF文件增长多少倍后进行重写 |
统计名 | 说明 |
---|---|
aof_corrent_size | AOF当前大小(字节) |
aof_base_size | AOF上次启动和重写的尺寸 |
重写配置
# 开启AOF功能的使用,默认no
appendonly yse
# 设置AOF文件名
appendfilename "appendonly-6379.aof"
# 每秒同步策略
appendfsync everysec
# 在AOF操作时候是否不进行append,建议yse
# yes,对性能好.但是会造成数据丢失
# no,非常消耗性能
no-appendfsync-on-rewrite yes
# 设置重写增长率和最小尺寸
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 如果AOF不完整或有问题,重启加载是否忽略重写的错误
aof-load-truncated yes
测试
# redis启动不建议暂停服务再修改配置.
# 获取动态配置
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 rewrite
OK
# 执行字符串修改操作
127.0.0.1:6379> set name_zcx sb
OK
127.0.0.1:6379> set name_zcx pig
OK
127.0.0.1:6379> set name_zcx dog
OK
# 生成配置的文件
222 6月 27 17:32 appendonly-6379.aof
# 查看aof文件
$3
set
$8
name_zcx
$3
pig
*3
$3
set
$8
name_zcx
$3
dog
# $n 是指下面的操作有多少个字节
# *3 修改了三次
RDB vs AOF
当开启了RDB又开启了AOF.在redis挂掉重启后会优先加载APF.因为AOF数据级别高,保存的的数据比RDB更新.
RDB | AOF | |
---|---|---|
启动优先级 | 低 | 高 |
文件大小 | 小(压缩二进制文件) | 大(日志类型文件) |
恢复速度 | 快 | 慢 |
数据安全性 | 丢数据 | 根据配置的策略决定 |
操作轻重 | 重 | 轻 |
建议 | 关 | 开 |