【Redis】Redis持久化

news2024/12/23 13:19:18

介绍

​ Redis是一个内存数据库,数据保存在内存中,但是我们都知道内存的数据变化是很快的,也容易发生丢失。Redis提供了持久化的机制,分别是RDB(Redis DataBase)和AOF(Append Only File)。

​ 既然redis的数据可以保存在磁盘上,那么这个流程是什么样的呢? 主要有下面五个过程:

  • (1)客户端向服务端发送写操作(数据在客户端的内存中)。
  • (2)数据库服务端接收到写请求的数据(数据在服务端的内存中)。
  • (3)服务端调用write这个系统调用,将数据往磁盘上写(数据在系统内存的缓冲区中)。
  • (4)操作系统将缓冲区中的数据转移到磁盘控制器上(数据在磁盘缓存中)。
  • (5)磁盘控制器将数据写到磁盘的物理介质中(数据真正落到磁盘上)。

在这里插入图片描述

RDB方式

RDB持久化:以指定的时间间隔执行数据集的时间点快照。

  • 在指定的时间间隔,执行数据集的时间点快照
  • 实现类似照片记录效果的方式,就是把某一时刻的数据和状态以文件的形式写到磁盘上,也就是快照。这样一来即使故障宕机,快照文件也不会丢失,数据的可靠性也就得到了保证。
  • 这个快照文件就称为RDB文件(dump.rdb),其中,RDB就是Redis DataBase的缩写。
  • 将内存数据全部保存到磁盘dump.rdb文加中

RDB在恢复时,将硬盘中的快照文件直接读取到内存中。

Redis的数据都在内存中,保存备份时执行的是全量快照,即将内存中的所有数据都记录到磁盘中。

自动触发

配置方法

redis默认的配置文件redis.conf,其中有一个自动触发RDB持久化的配置:

Redis7的。
################################ SNAPSHOTTING  ###########################        #####
    413 
    414 # Save the DB to disk.
    415 #
    416 # save <seconds> <changes> [<seconds> <changes> ...]
    417 #
    418 # Redis will save the DB if the given number of seconds elapsed and it
    419 # surpassed the given number of write operations against the DB.
    420 #
    421 # Snapshotting can be completely disabled with a single empty string argum        ent
    422 # as in following example:
    423 #
    424 # save ""
    425 #
    426 # Unless specified otherwise, by default Redis will save the DB:
    427 #   * After 3600 seconds (an hour) if at least 1 change was performed
    428 #   * After 300 seconds (5 minutes) if at least 100 changes were performed
    429 #   * After 60 seconds if at least 10000 changes were performed
    430 #
    431 # You can set these explicitly by uncommenting the following line.
    432 #
    433 # save 3600 1 300 100 60 10000

说明:

save 3600 1 300 100 60 10000表示一小时内有一次修改,5分钟内有至少100次修改,1分钟内至少有10000次修改,就会自动触发RDB持久化。

自动触发

  • 修改save配置为5秒钟2次修改

    # save 3600 1 300 100 60 10000
    save 5 2
    
  • 修改dump文件保存路径

    # The working directory.
    #
    # The DB will be written inside this directory, with the filename specified
    # above using the 'dbfilename' configuration directive.
    #
    # The Append Only File will also be created inside this directory.
    #
    # Note that you must specify a directory here, not a file name.
    #dir ./
    dir /opt/redis-7.0.10/myredis/dumpfiles
    # 注意该目录一定要存在,不会自动创建
    [root@192 myredis]# ll
    total 108
    drwxr-xr-x. 2 root root      6 Apr 23 06:23 dumpfiles
    
  • 修改dump文件名字

    # The filename where to dump the DB
    dbfilename dump6379.rdb
    
  • 查看修改后的值

    [root@192 myredis]# redis-cli -a 1
    Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
    127.0.0.1:6379> config get dir
    1) "dir"
    2) "/opt/redis-7.0.10/myredis/dumpfiles"
    
  • 5秒钟执行两次set命令,然后查看dumpfiles目录下是否生成文件

    127.0.0.1:6379> set k1 v1
    OK
    127.0.0.1:6379> set k2 v2
    OK
    
    [root@192 dumpfiles]# ll
    total 0
    [root@192 dumpfiles]# ll
    total 4
    -rw-r--r--. 1 root root 108 Apr 23 06:30 dump6379.rdb
    

    可知,dumpfiles目录下生成了rdb文件。

  • 执行一次set后,等待5秒钟后,查看rdb文件大小

    127.0.0.1:6379> set k3 v3
    OK
    
    [root@192 dumpfiles]# ll
    total 4
    -rw-r--r--. 1 root root 108 Apr 23 06:30 dump6379.rdb
    

    可见,rdb文件大小没有任何变化。

  • 5秒后,继续执行set命令,然后查看rdb文件大小

    127.0.0.1:6379> set k4 v4
    OK
    
    [root@192 dumpfiles]# ll
    total 4
    -rw-r--r--. 1 root root 122 Apr 23 06:34 dump6379.rdb
    

    可见,文件变大,存储成功。

备份恢复

1、将备份文件修改名字,如下:

ot@192 dumpfiles]# ll
total 4
-rw-r--r--. 1 root root 122 Apr 23 06:34 dump6379.rdb.bak

2、使用flushdb命令,清空redis,并查看dumpfiles目录。

127.0.0.1:6379> keys *
1) "k4"
2) "k3"
3) "k2"
4) "k1"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> keys *
(empty array)

[root@192 dumpfiles]# ll
total 8
-rw-r--r--. 1 root root  89 Apr 23 06:37 dump6379.rdb
-rw-r--r--. 1 root root 122 Apr 23 06:34 dump6379.rdb.bak

可以看到,dumpfiles目录下又生成了rdb文件,说明当执行类似flushdb/flushall/shutdown这样的提交命令时,redis也会自动触发RDB持久化

3、shutdown退出后,重新进入redis。

127.0.0.1:6379> shutdown
not connected> quit
[root@192 myredis]# redis-server redis7.conf
[root@192 myredis]# redis-cli -a 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> keys *
(empty array)

可见,没有恢复。

4、将之前的RDB文件恢复

[root@192 dumpfiles]# ll
total 8
-rw-r--r--. 1 root root  89 Apr 23 06:42 dump6379.rdb
-rw-r--r--. 1 root root 122 Apr 23 06:34 dump6379.rdb.bak
[root@192 dumpfiles]# rm -rf dump6379.rdb
[root@192 dumpfiles]# mv dump6379.rdb.bak dump6379.rdb
[root@192 dumpfiles]# ll
total 4
-rw-r--r--. 1 root root 122 Apr 23 06:34 dump6379.rdb

5、重新进入redis

[root@192 myredis]# redis-server redis7.conf
[root@192 myredis]# redis-cli -a 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"
4) "k4"
127.0.0.1:6379> 

可以看到已经恢复了。

注意:不可以将备份文件dump.rdb和生产redis服务器放在同一台机器,必须分开各自存储,以防生产机物理损坏之后备份文件丢失。

手动触发

save命令(不建议使用)

save命令是一个同步操作,执行该命令后,RDB持久化是在主进程中进行的,这样会阻塞当前redis服务,直到RDB持久化完成后,客户端才能正常连接redis服务。

img

bgsave命令(默认)

bgsave命令是对save命令的一个优化,是一个异步操作。执行该命令后,redis主进程会通过fork操作创建一个子进程,RDB持久化是由子进程操作,完成后自动结束。这个过程中,主进程不阻塞,可以继续接收客户端的访问。因此,redis内部所有涉及RDB持久化的操作都是采用的bgsave方式,save命令基本已经废弃。

img

127.0.0.1:6379> set k5 v5
OK
[root@192 dumpfiles]# ll
total 4
-rw-r--r--. 1 root root 122 Apr 23 06:34 dump6379.rdb

127.0.0.1:6379> bgsave
Background saving started
[root@192 dumpfiles]# ll
total 4
-rw-r--r--. 1 root root 129 Apr 23 06:54 dump6379.rdb

127.0.0.1:6379> lastsave
(integer) 1682258078
# LASTSAVE 命令用于查看 BGSAVE 命令是否执行成功。

img

优点

RDB 数据持久化适合于大规模的数据恢复,并且还原速度快,如果对数据的完整性不是特别敏感(可能存在最后一次丢失的情况),那么 RDB 持久化方式非常合适。

缺点

在 RDB 持久化的过程中,子进程会把 Redis 的所有数据都保存到新建的 dump.rdb 文件中,这是一个既消耗资源又浪费时间的操作。因此 Redis 服务器不能过于频繁地创建 rdb 文件,否则会严重影响服务器的性能。

RDB 持久化的最大不足之处在于,最后一次持久化的数据可能会出现丢失的情况。可以这样理解,在持久化进行过程中,服务器突然宕机了,这时存储的数据可能并不完整,比如子进程已经生成了 rdb 文件,但是主进程还没来得及用它覆盖掉原来的旧 rdb 文件,这样就把最后一次持久化的数据丢失了。

如果数据集比较大的时候,fork可以能比较耗时,造成服务器在一段时间内停止处理客户端的请求。

数据丢失案例

1、正常录入k1k2,并查看RDB文件

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK
[root@192 dumpfiles]# ll
total 4
-rw-r--r--. 1 root root 108 Apr 23 07:02 dump6379.rdb

2、录入k3,然后kill -9杀掉redis服务,并查看RDB文件

127.0.0.1:6379> set k3 v3
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k1"
3) "k3"

[root@192 dumpfiles]# ps -ef | grep redis
root      35233      1  0 06:44 ?        00:00:00 redis-server *:6379
root      35238   2815  0 06:44 pts/0    00:00:00 redis-cli -a 1
root      35563  34926  0 07:02 pts/1    00:00:00 grep --color=auto redis
[root@192 dumpfiles]# kill -9 35233
[root@192 dumpfiles]# ll
total 4
-rw-r--r--. 1 root root 108 Apr 23 07:02 dump6379.rdb #大小没有变化

127.0.0.1:6379> keys * #执行该命令时,显示已经被杀掉了。
Error: Server closed the connection
not connected> quit

可以看到,执行完set k3 v3后,在内存中存在,但是没有保存到RDB文件中,此时杀掉redis服务后,RDB文件大小并没有变化。

3、重新进入redis,查看

[root@192 myredis]# redis-server redis7.conf
[root@192 myredis]# redis-cli -a 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k3
(nil)

可以看到,k3并没有值,也就是最后一次操作丢失了

检查和修复RDB文件

当RDB文件遇到状况时,需要进行检查并且修复。

[root@192 ~]# cd /usr/local/bin
[root@192 bin]# ll
total 74708
-rwxr-xr-x. 1 root root 54453847 Apr 15 18:24 docker-compose
-rwxr-xr-x. 1 root root  5197776 Apr 16 00:39 redis-benchmark
lrwxrwxrwx. 1 root root       12 Apr 16 00:39 redis-check-aof -> redis-server
lrwxrwxrwx. 1 root root       12 Apr 16 00:39 `redis-check-rdb -> redis-server`
-rwxr-xr-x. 1 root root  5411112 Apr 16 00:39 redis-cli
lrwxrwxrwx. 1 root root       12 Apr 16 00:39 redis-sentinel -> redis-server
-rwxr-xr-x. 1 root root 11429256 Apr 16 00:39 redis-server

执行如下命令进行检查和修复:

redis-check-rdb /opt/redis-7.0.10/myredis/dumpfiles/dump6379.rdb

[root@192 bin]# redis-check-rdb /opt/redis-7.0.10/myredis/dumpfiles/dump6379.rdb 
[offset 0] Checking RDB file /opt/redis-7.0.10/myredis/dumpfiles/dump6379.rdb
[offset 27] AUX FIELD redis-ver = '7.0.10'
[offset 41] AUX FIELD redis-bits = '64'
[offset 53] AUX FIELD ctime = '1682258526'
[offset 68] AUX FIELD used-mem = '1054608'
[offset 80] AUX FIELD aof-base = '0'
[offset 82] Selecting DB ID 0
[offset 108] Checksum OK
[offset 108] \o/ RDB looks OK! \o/
[info] 2 keys read
[info] 0 expires
[info] 0 already expired

禁用快照

动态停止RDB保存规则

redis-cli config set save ""

快照禁用

在配置文件中,按照如下修改:

# Snapshotting can be completely disabled with a single empty string argument
# as in following example:
#
# save ""

其他配置项

配置项作用
stop-writes-on-bgsave-error默认yes,配置成no,表示不在乎数据不一致,在快照写入失败时,确保redis继续接受新的写请求
rdbcompression默认yes,对于存储到磁盘中的快照,是否进行压缩存储。
rdbchecksum默认yes,在存储快照后,使用CRC64算法进行数据校验,会增加约10%的性能消耗。
rdb-del-sync-files默认no,在没有持久性的情况下删除复制中使用的RDB文件启用。

AOF方式

全量备份总是耗时的,Redis为我们提供了一种更加高效的持久化方式,即AOF(appendonlyfile)。此方式工作机制很简单,redis会将每一个收到的写命令都通过write函数追加到aof文件中。默认情况下Redis没有开启AOF方式的持久化。在redis服务器重启时,会读取并加载aof文件,达到恢复数据的目的。

开启AOF持久化后,每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件,这一过程显然会降低Redis的性能,但大部分情况下这个影响是能够接受的,另外使用较快的硬盘可以提高AOF的性能。

工作流程

在这里插入图片描述

1、Client是命令的来源,会有多个源头以及请求命令

2、在这些命令到达Redis Server之后,不是直接写入AOF文件,将这些命令存放到AOF缓存中进行保存,当这些命令达到一定量之后写入磁盘,避免频繁的磁盘IO操作。

3、AOF缓存会根据AOF缓存区同步文件的三种写回策略将命令写入磁盘上的AOF文件。

4、随着写入AOF内容的增加,为避免文件膨胀,会根据规则进行命令的合并(AOF重写),从而起到AOF文件压缩的目的。

5、当Redis Server服务器重启的时候,将从AOF文件载入数据。

写回策略

appendfsync always

客户端对redis服务器的每次写操作都写入AOF日志文件。这种方式是最安全的方式,但每次写操作都进行一次磁盘IO,非常影响redis的性能,所以一般不使用这种方式。

appendfsync everysec

每秒刷新一次缓冲区中的数据到AOF文件。这种方式是redis默认使用的策略,是考虑数据完整性和性能的这种方案,理论上,这种方式最多只会丢失1秒内的数据。

appendfsync no

redis服务器不负责将数据写入到AOF文件中,而是直接交给操作系统去判断什么时候写入。这种方式是最快的一种策略,但丢失数据的可能性非常大,因此也是不推荐使用的。

配置

配置文件:redis.conf

# 可以通过修改redis.conf配置文件中的appendonly参数开启
appendonly yes

# Redis6:AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的。
dir /opt/redis-7.0.10/myredis
# Redis7:在dir只下生成一个appendonlydir目录,存放aof文件
dir /opt/redis-7.0.10/myredis
appenddirname "appendonlydir"

# 默认的文件名是appendonly.aof,可以通过appendfilename参数修改
# - appendonly.aof.1.base.rdb as a base file.基础文件
# - appendonly.aof.1.incr.aof, appendonly.aof.2.incr.aof as incremental files.增量文件,写操作命令记录
# - appendonly.aof.manifest as a manifest file.清单文件
appendfilename appendonly.aof

# 写回策略
# appendfsync always
appendfsync everysec
# appendfsync no

正常恢复

1、启动redis

127.0.0.1:6379> SHUTDOWN
not connected> quit
[root@192 myredis]# redis-server redis7.conf
[root@192 myredis]# redis-cli -a 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> 

[root@192 myredis]# ll
total 108
drwxr-xr-x. 2 root root    103 Apr 23 07:51 appendonlydir
drwxr-xr-x. 2 root root     26 Apr 23 07:51 dumpfiles
-rw-r--r--. 1 root root 106580 Apr 23 07:51 redis7.conf
[root@192 myredis]# cd appendonlydir/
[root@192 appendonlydir]# ll
total 8
-rw-r--r--. 1 root root 89 Apr 23 07:51 appendonly.aof.1.base.rdb
-rw-r--r--. 1 root root  0 Apr 23 07:51 appendonly.aof.1.incr.aof
-rw-r--r--. 1 root root 88 Apr 23 07:51 appendonly.aof.manifest

2、正常录入k1,k2,k3,查看aof文件并备份,并删除RDB文件排除rdb的影响。

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> set k2 v2
OK

[root@192 myredis]# ll
total 112
drwxr-xr-x. 2 root root    103 Apr 23 07:51 appendonlydir
-rw-r--r--. 1 root root    108 Apr 23 07:53 dump6379.rdb
drwxr-xr-x. 2 root root     26 Apr 23 07:51 dumpfiles
-rw-r--r--. 1 root root 106580 Apr 23 07:51 redis7.conf
[root@192 myredis]# rm -rf dump6379.rdb 
[root@192 myredis]# rm -rf dumpfiles/
[root@192 myredis]# ll
total 108
drwxr-xr-x. 2 root root    103 Apr 23 07:51 appendonlydir
-rw-r--r--. 1 root root 106580 Apr 23 07:51 redis7.conf
[root@192 myredis]# cp -a appendonlydir/ appendonlydir_bak
[root@192 myredis]# ll
total 108
drwxr-xr-x. 2 root root    103 Apr 23 07:51 appendonlydir
drwxr-xr-x. 2 root root    103 Apr 23 07:51 appendonlydir_bak
-rw-r--r--. 1 root root 106580 Apr 23 07:51 redis7.conf
[root@192 myredis]# cd appendonlydir/
[root@192 appendonlydir]# ll
total 12
-rw-r--r--. 1 root root 89 Apr 23 07:51 appendonly.aof.1.base.rdb
-rw-r--r--. 1 root root 81 Apr 23 07:53 appendonly.aof.1.incr.aof
-rw-r--r--. 1 root root 88 Apr 23 07:51 appendonly.aof.manifest

3、执行flushdb清空,然后删除rdb文件,并进行恢复。

# 执行flushdb
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> SHUTDOWN
not connected> quit
# 删除rdb文件,排除rdb的干扰
[root@192 myredis]# ll
total 112
drwxr-xr-x. 2 root root    103 Apr 23 07:51 appendonlydir
drwxr-xr-x. 2 root root    103 Apr 23 07:51 appendonlydir_bak
-rw-r--r--. 1 root root     89 Apr 23 08:02 dump6379.rdb
-rw-r--r--. 1 root root 106580 Apr 23 07:51 redis7.conf
[root@192 myredis]# rm -rf dump6379.rdb 
[root@192 myredis]# cd appendonlydir
[root@192 appendonlydir]# ll
total 12
-rw-r--r--. 1 root root 89 Apr 23 07:51 appendonly.aof.1.base.rdb
-rw-r--r--. 1 root root 98 Apr 23 08:02 appendonly.aof.1.incr.aof
-rw-r--r--. 1 root root 88 Apr 23 07:51 appendonly.aof.manifest
# 重启redis,恢复
[root@192 myredis]# redis-server redis7.conf
[root@192 myredis]# redis-cli -a 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> keys *
(empty array)

可见,flushdb也是写操作命令,也会写入到aof文件中,导致恢复时会恢复到flushdb的时候。

4、将bak目录恢复,重新恢复

[root@192 myredis]# mv appendonlydir_bak/ appendonlydir
[root@192 myredis]# ll
total 108
drwxr-xr-x. 2 root root    103 Apr 23 07:51 appendonlydir
-rw-r--r--. 1 root root 106580 Apr 23 07:51 redis7.conf

[root@192 myredis]# redis-server redis7.conf
[root@192 myredis]# redis-cli -a 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> keys *
1) "k1"
2) "k2"

成功。

异常恢复

当redis写命令写了一半,redis服务突然down了,这时,aof文件中就会出现一些问题。

1、手动写坏aof文件内容

$3
set
$2
k4
$2
v4
sadfasdfasdfdasfsadfsdafdsfdgfdhdfh

2、重新启动redis

[root@192 myredis]# redis-server redis7.conf
[root@192 myredis]# redis-cli -a 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
Could not connect to Redis at 127.0.0.1:6379: Connection refused
not connected> 

3、修复aof文件

redis-check-aof --fix appendonly.aof.1.incr.aof

[root@192 appendonlydir]# redis-check-aof appendonly.aof.1.incr.aof 
Start checking Old-Style AOF
AOF appendonly.aof.1.incr.aof format error
AOF analyzed: filename=appendonly.aof.1.incr.aof, size=170, ok_up_to=133, ok_up_to_line=32, diff=37
AOF appendonly.aof.1.incr.aof is not valid. Use the --fix option to try fixing it.
[root@192 appendonlydir]# redis-check-aof --fix appendonly.aof.1.incr.aof 
Start checking Old-Style AOF
AOF appendonly.aof.1.incr.aof format error
AOF analyzed: filename=appendonly.aof.1.incr.aof, size=170, ok_up_to=133, ok_up_to_line=32, diff=37
This will shrink the AOF appendonly.aof.1.incr.aof from 170 bytes, with 37 bytes, to 133 bytes
Continue? [y/N]: y
Successfully truncated AOF appendonly.aof.1.incr.aof

4、重启redis

[root@192 myredis]# redis-server redis7.conf
[root@192 myredis]# redis-cli -a 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> keys *
1) "k4"
2) "k1"
3) "k2"

成功。

优点

在这里插入图片描述

缺点

在这里插入图片描述

文件重写

既然AOF是通过日志追加的方式来存储redis的写指令,那么当我们对同一个key做多次写操作时,就会产生大量针对同一个key操作的日志指令,导致AOF文件会变得非常大,恢复数据的时候会变得非常慢。因此,redis提供了重写机制来解决这个问题。redis通过重写AOF文件,保存的只是恢复数据的最小指令集。

手动触发重写

bgrewriteaof

示例
127.0.0.1:6379> set k1 11111111111111111111111111111111111
OK
127.0.0.1:6379> set k1 v22
OK
127.0.0.1:6379> BGREWRITEAOF
Background append only file rewriting started

[root@192 appendonlydir]# ll
total 8
-rw-r--r--. 1 root root 53 Apr 23 08:40 appendonly.aof.3.base.aof
-rw-r--r--. 1 root root  0 Apr 23 08:40 appendonly.aof.3.incr.aof
-rw-r--r--. 1 root root 88 Apr 23 08:40 appendonly.aof.manifest

[root@192 appendonlydir]# vi appendonly.aof.3.base.aof 
*2
$6
SELECT
$1
0
*3
$3
SET
$2
k1
$3
v22

自动触发重写

配置文件:redis.conf

auto-aof-rewrite-percentage 100 #当文件的大小达到原先文件大小(上次重写后的文件大小,如果没有重写过,那就是redis服务启动时的文件大小)的两倍。
auto-aof-rewrite-min-size 64mb #文件重写的最小文件大小,即当AOF文件低于64mb时,不会触发重写。【同时满足】
示例

1、修改配置,并关闭混合

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 1kb
aof-use-rdb-preamble no

2、去除干扰项

[root@192 myredis]# ll
total 112
drwxr-xr-x. 2 root root    103 Apr 23 08:13 appendonlydir
-rw-r--r--. 1 root root    115 Apr 23 08:27 dump6379.rdb
-rw-r--r--. 1 root root 106578 Apr 23 08:30 redis7.conf
[root@192 myredis]# rm -rf dump6379.rdb 
[root@192 myredis]# cd appendonlydir/
[root@192 appendonlydir]# ll
total 12
-rw-r--r--. 1 root root  89 Apr 23 07:51 appendonly.aof.1.base.rdb
-rw-r--r--. 1 root root 133 Apr 23 08:16 appendonly.aof.1.incr.aof
-rw-r--r--. 1 root root  88 Apr 23 07:51 appendonly.aof.manifest
[root@192 appendonlydir]# rm -rf *
[root@192 appendonlydir]# ll
total 0

3、重新启动redis,查看aof文件

[root@192 myredis]# redis-server redis7.conf
[root@192 myredis]# redis-cli -a 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> 

[root@192 appendonlydir]# ll
total 4
-rw-r--r--. 1 root root  0 Apr 23 08:31 appendonly.aof.1.base.aof
-rw-r--r--. 1 root root  0 Apr 23 08:31 appendonly.aof.1.incr.aof
-rw-r--r--. 1 root root 88 Apr 23 08:31 appendonly.aof.manifest

4、执行set k1 1查看aof文件是否正常。

127.0.0.1:6379> set k1 1
OK
127.0.0.1:6379> get k1
"1"

[root@192 appendonlydir]# ll
total 8
-rw-r--r--. 1 root root  0 Apr 23 08:31 appendonly.aof.1.base.aof
-rw-r--r--. 1 root root 51 Apr 23 08:32 appendonly.aof.1.incr.aof
-rw-r--r--. 1 root root 88 Apr 23 08:31 appendonly.aof.manifest

5、重复执行set k1 111111111111111111操作,直到aof文件大小达到1024.

127.0.0.1:6379> set k1 11111111111111111111111111111111111
OK
127.0.0.1:6379> set k1 11111111111111111111111111111111111
OK
127.0.0.1:6379> set k1 11111111111111111111111111111111111
OK

[root@192 appendonlydir]# ll
total 8
-rw-r--r--. 1 root root   0 Apr 23 08:31 appendonly.aof.1.base.aof
-rw-r--r--. 1 root root 933 Apr 23 08:35 appendonly.aof.1.incr.aof
-rw-r--r--. 1 root root  88 Apr 23 08:31 appendonly.aof.manifest
[root@192 appendonlydir]# cat appendonly.aof.1.incr.aof
……
*3
$3
set
$2
k1
$35
11111111111111111111111111111111111
*3
$3
set
$2
k1
$35
11111111111111111111111111111111111

#继续执行set,查看aof文件
[root@192 appendonlydir]# ll
total 12
-rw-r--r--. 1 root root 86 Apr 23 08:36 appendonly.aof.2.base.aof
-rw-r--r--. 1 root root 86 Apr 23 08:36 appendonly.aof.2.incr.aof
-rw-r--r--. 1 root root 88 Apr 23 08:36 appendonly.aof.manifest
#可见,aof文件变成2了。

6、查看base.aof的内容

*2
$6
SELECT
$1
0
*3
$3
SET
$2
k1
$35
11111111111111111111111111111111111

只保留了最后一次的命令。

重写流程

(1)bgrewriteaof触发重写,判断是否存在bgsave或者bgrewriteaof正在执行,存在则等待其执行结束再执行;

(2)主进程fork子进程,防止主进程阻塞无法提供服务;

(3)子进程遍历Redis内存快照中数据写入临时AOF文件,同时会将新的写指令写入aof_buf和aof_rewrite_buf两个重写缓冲区,前者是为了写回旧的AOF文件,后者是为了后续刷新到临时AOF文件中,防止快照内存遍历时新的写入操作丢失;

(4)子进程结束临时AOF文件写入后,通知主进程;

(5)主进程会将上面的aof_rewirte_buf缓冲区中的数据写入到子进程生成的临时AOF文件中;

(6)主进程使用临时AOF文件替换旧AOF文件,完成整个重写过程。

img

伪代码

def AOF_REWRITE(tmp_tile_name):
f = create()
# 遍历所有数据库
for db in redisServer.db:
# 如果数据库为空,那么跳过这个数据库
if db.is_empty(): continue
# 写入 SELECT 命令,用于切换数据库
f.write_command("SELECT " + db.number)
# 遍历所有键
for key in db:
# 如果键带有过期时间,并且已经过期,那么跳过这个键
if key.have_expire_time() and key.is_expired(): continue
if key.type == String:
# 用 SET key value 命令来保存字符串键
value = get_value_from_string(key)
f.("SET " + key + value)
elif key.type == List:
# 用 RPUSH key item1 item2 ... itemN 命令来保存列表键
item1, item2, ..., itemN = get_item_from_list(key)
f.("RPUSH " + key + item1 + item2 + ... + itemN)
elif key.type == Set:
# 用 SADD key member1 member2 ... memberN 命令来保存集合键
member1, member2, ..., memberN = get_member_from_set(key)
f.("SADD " + key + member1 + member2 + ... + memberN)
elif key.type == Hash:
# 用 HMSET key field1 value1 field2 value2 ... fieldN valueN 命令来保存哈希键
field1, value1, field2, value2, ..., fieldN, valueN =\
get_field_and_value_from_hash(key)
f.("HMSET " + key + field1 + value1 + field2 + value2 +\
... + fieldN + valueN)
elif key.type == SortedSet:
# 用 ZADD key score1 member1 score2 member2 ... scoreN memberN
# 命令来保存有序集键
score1, member1, score2, member2, ..., scoreN, memberN = \
get_score_and_member_from_sorted_set(key)
f.write_command("ZADD " + key + score1 + member1 + score2 + member2 +\
... + scoreN + memberN)
else:
raise_type_error()
# 如果键带有过期时间,那么用 EXPIREAT key time 命令来保存键的过期时间
if key.have_expire_time():
f.write_command("EXPIREAT " + key + key.expire_time_in_unix_timestamp())
# 关闭文件
f.close()

实际为了避免执行命令时造成客户端输入缓冲区溢出,重写程序在处理list hash set zset时,会检查键所包含的元素的个数。

如果元素的数量超过了redis.h/REDIS_AOF_REWRITE_ITEMS_PER_CMD常量的值,那么重写程序会使用多条命令来记录键的值,而不是单使用一条命令。该常量默认值是64,即每条命令设置的元素的个数是最多64个,重写程序使用多条命令实现集合键中元素数量超过64个的键。

RDB和AOF混合持久化

在同时开启RDB和AOF持久化时,重启只会加载aof文件,不会加载rdb文件。

在这里插入图片描述

在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,
因为在通常情况下AOF文件保存的数据集要比RDB文件保存的数据集要完整.

问题:RDB的数据不实时,同时使用两者时服务器重启也只会找AOF文件。那要不要只使用AOF呢?
建议不要,因为RDB更适合用于备份数据库(AOF在不断变化不好备份),留着rdb作为一个万一的手段。

配置

开启混合方式配置

aof-use-rdb-preamble yes

yes表示开启,设置为no表示禁用。

RDB镜像做全量持久化,AOF做增量持久化。

先使用RDB进行快照存储,然后使用AOF持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的RDB记录。这样的话,重启服务的时候会从RDB和AOF两部分恢复数据,既保证了数据完整性,又提高了恢复数据的性能。简单来说:混合持久化方式产生的文件一部分是RDB格式,一部分是AOF格式。----》AOF包括了RDB头部+AOF混写。

同时关闭RDB和AOF

save ""

禁用rdb持久化,可以使用命令save和bgsave生成rdb文件。

appendonly no

禁用aof持久化模式,可以使用bgrewriteaof生成aof文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/455304.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STL : 栈 stack 与 队列 queue

Stack #include<stack> using namespace std; 栈&#xff1a;LIFO&#xff0c;先进后出&#xff1b; 不允许遍历&#xff0c;仅仅一个出口&#xff0c;只有栈顶元素可被访问到。 Member functions NameRoleNotice&#xff08;constructor&#xff09;基本构造函数指…

ChatGLM-6B 中文对话模型复现、调用模块、微调及部署实现(更新中)

ChatGLM-6B-PT 一、前言 近期&#xff0c;清华开源了其中文对话大模型的小参数量版本 ChatGLM-6B&#xff08;GitHub地址&#xff1a;https://github.com/THUDM/ChatGLM-6B&#xff09;。其不仅可以单卡部署在个人电脑上&#xff0c;甚至 INT4 量化还可以最低部署到 6G 显存的…

从零开始写一个 即时通讯程序

即时通信&#xff08;IM&#xff09;是指能够即时发送和接收互联网消息等的业务。自1998年面世以来&#xff0c;特别是近几年的迅速发展&#xff0c;即时通信的功能日益丰富&#xff0c;逐渐集成了电子邮件、博客、音乐、电视、游戏和搜索等多种功能。即时通信不再是一个单纯的…

谁说不能用中文写代码?

入门教程、案例源码、学习资料、读者群 请访问&#xff1a; python666.cn 大家好&#xff0c;欢迎来到 Crossin的编程教室 &#xff01; 现代计算机和编程的起源和推动力量主要源自美国&#xff0c;再加上26个字母很便于表示&#xff08;算上大小写&#xff0c;6位bit就够了&am…

32岁阿里P7,把简历改成不知名小公司,学历改成普通本科,工作内容不变,投简历全挂!...

hr靠什么来招人&#xff1f; 一位猎头讲述了自己和朋友打赌的故事&#xff1a; 朋友在阿里云&#xff0c;32岁&#xff0c;P7&#xff0c;他把简历上的公司改成不知名&#xff0c;学历改成普通本科&#xff0c;工作内容不变&#xff0c;结果投其他公司&#xff08;比如京东&…

ThinkPHP6之数据库操作下

ThinkPHP6之数据库操作下 前言一&#xff0c;查询表达式1.1 where1.2table和name1.3field1.4limit1.5page1.6 order 二&#xff0c; 聚合查询三&#xff0c;分页查询总结 前言 数据库操作除了增&#xff0c;删&#xff0c;查&#xff0c;改&#xff0c;这四个基本操作外&#x…

【C++】二叉搜索树(概念、实现、应用以及OJ题详解)

前言&#xff1a; 此前我们在C语言实现数据结构的时候学习过二叉树&#xff0c;但是那个时候我们没有深入学习二叉搜索树。本章重提二叉树并详解二叉搜索树有下面两个原因&#xff1a; 1、为我们下一章学习set和map做准备&#xff1b;2、详解我们进阶一点的二叉树的面试OJ题&a…

120名顶级技术专家用GPT-4搞出的脑洞发明大赏

文 | 智商掉了一地 黑客松&#xff08;Hackathon&#xff09;是一种聚集程序员、设计师等技术人才&#xff0c;共同在短短几天的时间内合作进行软件开发、解决问题的活动。参与者可分为个人和团队形式参与&#xff0c;他们将利用这段时间内的集中创作和多学科合作&#xff0c;迅…

Java网络编程系列之NIO

Java网络编程系列之NIO 1.Java NIO概述1.1 阻塞IO1.2 非阻塞IO1.3 NIO概述1.3.1 Channels1.3.2 Buffer1.3.3 Selector 2.Java NIO(Channel)2.1Channel概述2.2 Channel实现2.3 FileChannel 介绍与示例2.4 FileChannel 操作详解2.4.1 打开FileChannel2.4.2 从FileChannel读取数据…

带你一步步实现代码开发平台——概述、实现模式、整体框架

概述 低代码开发平台是一种开发工具&#xff0c;它允许用户使用图形界面和少量编码来创建应用程序。这种平台的目的是加快应用程序开发速度&#xff0c;减少开发成本和技能门槛。目前&#xff0c;市场上有许多低代码开发平台可供选择&#xff0c;包括Microsoft Power Apps、Ou…

学系统集成项目管理工程师(中项)系列11a_沟通管理(上)

1. 基本概念 1.1. 构成 1.1.1. 接收者和发送者 1.1.1.1. 参与者既发送信息&#xff0c;又接收反馈&#xff0c;是一体的 1.1.2. 信息&#xff08;Message&#xff09; 1.1.2.1. 多个参与者之间需要分享的信息&#xff0c;表达思想和情感的组成物 1.1.2.2. 信息的存在方式…

虚拟化技术 — Libvirt 异构虚拟化管理组件

目录 文章目录 目录Libvirtlibvirt API 函数库libvirtd Daemon软件架构权限模式运行模式XML 格式 virsh CLI Libvirt QEMU-KVM 环境部署HostOS 配置优化&#xff08;可选的&#xff09;开启 KVM Nested 嵌套虚拟化安装 CentOS GNOME 图形界面安装 Libvirt QEMU-KVM Libvirt 的…

C语言ctype.h头文件中2类好用的库函数

本篇博客会讲解C语言ctype.h这个头文件中的2类好用的库函数&#xff0c;分别是字符分类函数和字符转换函数。 字符分类函数 字符分类函数&#xff0c;指的是判断一个字符是不是属于某个类别&#xff0c;如果属于这个类别&#xff0c;返回非0数&#xff1b;如果不属于这个类别…

性能测试工具 IxChariot:Tcl脚本调用方法介绍

ixChariot是一款功能强大的性能测试软件&#xff0c;可用来测试有线和无线性能&#xff0c;可以模拟真实应用程序流量&#xff0c;并提供关键性能指标&#xff0c;包括吞吐量、丢包、抖动、延迟、MOS等。本文简单介绍如何使用IxChariot Tcl API来实现自动化跑流。 目录 IxChari…

RK3399平台开发系列讲解(调试篇)断言的使用

🚀返回专栏总目录 文章目录 一、什么是断言二、静态断言三、运行时断言沉淀、分享、成长,让自己和他人都能有所收获!😄 📢断言为我们提供了一种可以静态或动态地检查程序在目标平台上整体状态的能力,与它相关的接口由头文件 assert.h 提供。 一、什么是断言 在编程中…

浏览器状态同步和路由-SSR和单页面应用的分析 【单页面应用和服务端渲染】

目录 单页面应用&#xff08;优缺点&#xff09;&#xff08;Single Page Application&#xff09; 优点&#xff1a; SPA的缺点&#xff1a; 服务端渲染&#xff08;Server Side Rendering&#xff09; SSR示例&#xff08;一个ssr小引擎&#xff09; SSR优缺点分析 总结…

Opencv+Python笔记(八)轮廓检测

目录 一、轮廓的检测和绘制1.读入图像2.将读入图像转化为灰度图3.对灰度图进行二值化 [图像的阈值化处理](https://blog.csdn.net/Ggs5s_/article/details/130301816?spm1001.2014.3001.5501)4.进行轮廓检测5.在原图中显示轮廓 二、轮廓层级关系1.RET_LIST2.RETR_EXTERNAL3. R…

座椅内饰如何「跟上」智能电动?这款智能概念座舱看到未来

进入智能电动汽车时代&#xff0c;理想的车内空间应该是怎样的&#xff1f;作为“内饰空间创造者”、全球三大汽车座椅及内饰厂商之一&#xff0c;丰田纺织在2023上海车展上给出了一系列解决方案。 4月19日&#xff0c;丰田纺织携诸多产品亮相本次上海车展&#xff0c;包括面向…

【速卖通】 AliExpress(速卖通)关键词搜索结果采集

采集场景 在AliExpress(速卖通) 首页中 http://www.aliexpress.com 中输入关键词&#xff0c;采集关键词搜索后得到的商品列表信息。 采集字段 关键词、标题、商品id、商品图片地址、商品详情链接、价格、免费退送货、星级、已出售数量、店铺名 采集结果 采集结果可导出为E…

C语言入门篇——函数篇

1、什么是函数 首先&#xff0c;什么是函数&#xff1f;函数(function)是完成特定任务的独立程序代码。单元语法规则定义了函数的结构和使用方式。虽然C中的函数和其他语言中的函数、子程序、过程作用相同&#xff0c;但是细节上略有不同。 为什么使用函数&#xff1f; 首先…