目录
aof
数据库写日志是写前日志(write ahead log,wal),先把修改的数据写到日志里,然后故障时恢复,AOF日志是写后日志,redis先执行命令,然后记录日志。
传统的数据库日志,redo日志记录的是修改后的数据,而AOF是redis收到的每条命令。
写后日志得好处:
- 可以避免额外的语法检查开销
- 不会阻塞当前写操作。
风险:
- 如果刚执行完就宕机,如果只是用做缓存,还可以从数据库读取,但是如果直接用作数据库,则会造成数据丢失。
- aof日志也是在主线程执行,如果日志文件写入磁盘时,磁盘写压力大,会导致写盘很慢,导致后续操作阻塞。
写回策略
写回时机 | 优点 | 缺点 | |
---|---|---|---|
always | 同步回写,每个命令执行完,立刻写回磁盘 | 基本不会丢数据 | 免会影响主线程性能. |
everySec | 每秒写回:每个命令执行完,只是先把日志写到aof文件缓冲区,每隔1s把缓冲区中的内容写入磁盘 | 在避免数据丢失和避免影响主线程之间做了折中 | 宕机1s内的数据会丢失. |
no | 操作系统控制写回,每个命令执行完,把写日志写到aof文件的缓冲区,由操作系统决定何时将缓冲区内容写回磁盘. | 性能好 | 一旦宕机,丢失较多数据. |
日志太大与aof重写
aof重写机制就是在重写时,redis根据数据库现状创建新的aof文件.将反复操作一个键值对的命令合并成一个.
aof重写过程
每次执行重写时,主线程fork出bgrewriteaof
,fork会把主线程内存拷贝一份给bgreriteaof
子进程.然后bgrewriteaof
在不影响主线程的情况,逐一把拷贝到的数据写成操作,记入重写日志.
重写过程中,主线程仍然可以处理新来的操作,仍然会使用aof日志操作,这个操作也会写到重写日志的缓冲区.等待拷贝数据的所有记录重写完成后,重写日志记录的这些最新操作也写入新的aof文件,保证数据库最新状态的记录.之后可以用新的aof文件代替旧文件.
fork流程
fork出bgrewriteaof
进程时会阻塞主线程,fork采用操作系统提供的写时复制(copy on write
),为了避免一次性拷贝大量内存数据给子进程造成的长时间阻塞问题,但fork子进程需要拷贝进程必要的数据结构(内存页表,虚拟内存和物理内存的映射索引表),阻塞时间取决于整个实例的内存大小.但是拷贝完毕后,子进程,父进程仍然指向相同的内存地址空间.写实复制时发生在写时,才会真正拷贝真正的数据.有可能造成父进程阻塞. fork出的子进程指向与父进程相同的内存空间,此使子进程可以进行aof重写,把内存的数据写入到aof文件中,但是父进程仍然会有流量写入,如果父进程操作得是一个已经存在的key,那么这个时候父进程就会拷贝这个key对应的内存数据,申请新的内存空间,逐渐的进行数据分离,内存分配是以页为单位进行分配,默认4k,如果父进程此使操作得是一个bigkey,重新申请大块内存耗时会变长,可能会产生阻塞风险.如果操作系统开启了大页机制(huge page,2M),那么父进程申请内存时阻塞概率会大大提高,所以redis机器上需要关闭huge page 机制,redis每次fork生成rdb或aof重写完成后,都可以在redis log中看到父进程重新申请了多大的内存空间.
如果某个程序总是喜欢用fork,也建议关闭huge page机制
aof重写时机
AOF文件大小同时超出下面这两个配置项时,会触发AOF重写。
auto-aof-rewrite-min-size
,运行aof重写时文件的最小大小auto-aof-rewrite-percentage
,当前AOF文件大小和上一次重写后AOF文件大小的差值,再除以上一次重写后AOF文件大小。也就是当前AOF文件比上一次重写后AOF文件的增量大小,和上一次重写后AOF文件大小的比值。
1 |
|
rdb
RDB(Redis DataBase):记录某一时刻的数据.执行的是全量快照.
rdb文件的生成
redis提供了两个命令生成rdb文件,save与bgsave
- save:主线程执行,会阻塞
- bgsave:创建一个子进程,专门用来写入rdb文件,避免主线程的阻塞,redis rdb文件生成的默认配置.
混合持久化
开启参数
1 | aof-use-rdb-preamble yes |