RDB存在的问题
耗时、耗性能
Redis将数据dump到硬盘当中,形成一个RDB文件。
- 首先是计较耗时的,它会将所有数据进行一个dump,是一个耗时为 O(n) 的过程,它的写会消耗很多CPU。
- 其次是内存的消耗,bgsave要做一个 fork() 的过程,fork() 会生成一个Redis的子进程,虽然不会进行一个完整的内存拷贝,而是类似于copy-on-write 的策略,假如写的量非常大,任然会产生很大的内存消耗。
- 最后就是IO消耗,本身就是把数据从内存写道硬盘当中,假如RDB文件非常大,写盘将会有很大的硬盘消耗。
不可控、丢失数据
时间戳 | save |
---|---|
T1 | 执行多个写命令 |
T2 | 满足RDB自动创建的条件 |
T3 | 再次执行多个写命令 |
T4 | 宕机 |
- 假如在T1时间点执行了很多写命令;
- 在T2时间点发现了一个满足RDB自动创建的条件;
- 在T3时间点再次执行一个写命令;
- 如果T4时间点发现宕机了,那么在T3~T4之间的一个数据写入就会丢失;
- 即是使用save、bgsave做一个定时策略也会出现上面的问题。
什么是AOF
AOF运行原理-创建
对于Redis来说,客户端执行一条命令Redis就会在日志中追加一次命令记录,当然命令会根据AOF日志的格式进行定义。
AOF运行原理-恢复
当Redis发生宕机之后,可以使用AOF对数据进行完整的恢复,恢复基本是实时的。
AOF三种策略
Redis在执行写命令先写在硬盘的缓冲区中,缓冲区会根据策略来刷新到磁盘当中。这样是为了提高写入的效率(直接写入磁盘将会比较慢)。
always
每条命令都fsync到磁盘。
everysec
每秒把缓冲区fsync到硬盘,默认值是1s。
no
根据操作系统决定fsync。
三种策略选择
命令 | always | everysec | no |
---|---|---|---|
优点 | 不丢失数据 | 每秒一次fsync丢失1s数据 | 不用管 |
缺点 | IO开销较大,一般的sata盘只有几百TPS | 丢1s数据 | 不可控 |
AOF重写
AOF出现重写的原因
- AOF策略可以将每条命令都写到AOF文件当中,随着命令逐步的写入AOF文件也会逐步的变大。
- 使用AOF来恢复将会非常的慢,如果文件无限制的增大,对硬盘的管理和命令的写入速度都会有一定的影响。
AOF重写的原理
就是把过期的、无用的、重复的、以及一些可以优化的命令都进行一个化简,化简成一个很小的AOF文件。
AOF重写的作用
- 减少磁盘的占用量
- 加速恢复速度
例如在做一个计数的服务,有很多自增的操作incr、incrby;若有有一个key自增到1亿,对于AOF文件来说就是1亿次incr,这样AOF文件的体量是非常大的,将会占用很多的磁盘空间。
如果做了AOF重写,磁盘的占有量将会减少;对于文件的恢复来说也是一样的。
AOF重写实现的两种方式
bgrewriteaof命令
客户端发送bgrewriteaof命令,Redis生成子进程进行AOF重写。这里的AOF重写不是生成新的AOF文件,而是对AOF文件进行修正。
AOF重写配置
配置:
配置名 | 含义 |
---|---|
auto-aof-rewrite-min-size | AOF文件重写需要的尺寸,默认为1MB(AOF文件多大的时候才开始AOF的重写) |
auto-aof-rewrite-percentage | AOF文件增长率,默认为100%(当前AOF文件大小和最后一次重写后的大小之间的比率等于或者等于指定的增长百分比) |
统计:
统计名 | 含义 |
---|---|
aof_current_size | 记录当前AOF文件大小的变量(单位:字节) |
aof_base_size | AOF上次启动和重写的尺寸(单位:字节) |
自动触发时机
同时满足
- aof_current_size > auto-aof-rewrite-min-size
- aof_current_size - aof_base_size / aof_base_size > auto-aof-rewrite-percentage
AOF重写流程
配置
# 开启aof,默认是no
appendonly yes
# aof文件命名
appendfilename "appendonly-${port}.aof"
# 设置aof策略
appendfsync everysec
# aof文件存储路径
dir /bigdiskpath
#yes : 在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。
#no : 在日志重写时,命令追加操作照常进行
no-appendfsync-on-rewrite yes
#AOF文件增长率,默认为100%
auto-aof-rewrite-percentage
#AOF文件重写需要的尺寸,默认为1MB
auto-aof-rewrite-min-size
验证
AOF配置
[root@localhost ~]# redis-cli
redis> dbsize
(integer) 5000000
redis> exit
[root@localhost ~]# vi redis-6379.conf
# 开启aof,默认是no
appendonly yes
# aof文件命名
appendfilename "appendonly-${port}.aof"
# 设置aof策略
#appendfsync always
appendfsync everysec
#appendfsync no
# aof文件存储路径
dir /bigdiskpath
#yes : 在日志重写时,不进行命令追加操作,而只是将其放在缓冲区里,避免与命令的追加造成DISK IO上的冲突。
#no : 在日志重写时,命令追加操作照常进行
no-appendfsync-on-rewrite yes
#AOF文件增长率,默认为100%
auto-aof-rewrite-percentage 100
#AOF文件重写需要的尺寸,默认为1MB
auto-aof-rewrite-min-size 64mb
#指redis在恢复时,会忽略最后一条可能存在问题的指令。
#默认值yes。即在AOF写入时,可能存在指令写错的问题(突然断电,写了一半),这种情况下,yes会log并继续,而no会直接恢复失败。
aof-load-truncated yes
动态设置AOF配置
- 执行 redis-cli 进入客户端。
- 执行 config get appendonly 命令查看 AOF 配置开启情况。
- 执行 config set appendonly yes 命令设置 AOF 配置开启。
- 执行 config rewrite 命令重写下配置。
- 执行 set、incr、rpush 等命令为创建 AOF 文件做准备。
- 在文件存储目录下执行 ll 命令查看 appendonly.aof 文件是否创建成功。
- 执行 more appendonly.aof 命令看下文件中的内容。
[root@localhost ~]# redis-cli
redis> config get appendonluy
1) "appendonly"
2) "no"
redis> config set appendonly yes
OK
reids> config rewrite
OK
redis> exit
[root@localhost ~]# redis-cli
redis> set hello world
OK
redis> set hello java
OK
redis> set hello redis
OK
redis> incr counter
(integer) 1
redis> incr counter
(integer) 2
redis> rpush list a
(integer) 1
redis> rpush list b
(integer) 2
redis> rpush list c
(integer) 3
redis> exit
[root@localhost ~]# ll
total 56
-rw-r--r-- 1 carlosfu staff 16K 10 7 22:28 6379.log
-rw-r--r-- 1 carlosfu staff 243B 10 7 22:29 appendonly.aof
-rw-r--r-- 1 carlosfu staff 18B 10 7 22:19 dump-6379.rdb
[root@localhost ~]# more appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$5
hello
$5
world
*3
$3
set
$5
hello
$5
redis
*2
...
[root@localhost ~]# head appendonly.aof
*2 #*2:表示下面的命令有两条参数SELECT、0,说明选择了0号数据库
$6 #$6:代表下面的SELECT该字符有6个字节
SELECT
$1
0
*3 #*3:表示下面的命令有yi条参数set、hello、world
$3 #$3:代表下面的set该字符有3个字节
set
$5
hello
$5
world
AOF的重写
- 执行 redis-cli 进入客户端。
- 执行 bgrewriteaof 命令,进行重写;返回 Backgrounp append only file rewriting started。
- 在文件存储目录下执行 ll 命令查看 appendonly.aof 文件,发现文件大小从 243B 降到了 137B。
[root@localhost ~]# redis-cli
redis> bgrewriteaof
Backgrounp append only file rewriting started
redis> exit
[root@localhost ~]# redis-cli
redis> dbsize
(integer) 3
redis> exit
[root@localhost ~]# ll
total 56
-rw-r--r-- 1 carlosfu staff 17K 10 7 22:33 6379.log
-rw-r--r-- 1 carlosfu staff 137B 10 7 22:33 appendonly.aof
-rw-r--r-- 1 carlosfu staff 18B 10 7 22:19 dump-6379.rdb