手记

使用AOF持久化文件实现还原Redis数据库并得到RDB持久化文件

1 编写本文的初衷

因为目前实习工作需求,需要把服务器环境中所有Redis数据进行初步简单分析,即统计其中存储的每一个key所占内存的大小,以便作出清理不重要缓存数据的决策。

 

但是,由于从线上环境获得持久化文件为AOF文件,而不是RDB文件。RDB文件可以通过Rdbtools工具,来分析具体数据。但是AOF文件不能这样操作。

 

因此,就给我带来一个问题:如何通过AOF文件获取指定的RDB持久化文件呢?

 

于是,我通过查阅网上文章,获取的一个解决思路:单独在Redis中开启一个未使用过的端口服务,使用已得到的AOF文件替换该端口服务下自动生成的AOF文件;然后,重启该端口指定的Redis服务,即可把新的AOF文件中数据加载到Redis数据库中,最后在该端口服务客户端执行save或者bgsave命令,即可在指定路径下得到对应的RDB持久化文件。

 

 


2 具体实施

2.1 Redis持久化概念简介

Redis数据库进行持久化有两种方式:RDB持久化和AOF持久化。

 

那么,什么是RDB持久化呢?

RDB(Redis Database)持久化:可以将Redis在内存中的数据库状态保存到磁盘里面,避免数据意外丢失。RDB持久化既可以手动执行,也可以根据服务器配置选项定期执行,该功能可以将某个时间点上的数据库状态保存到一个RDB文件中。(PS:手动执行保存时,在客户端执行SAVE命令或者BGSAVE即可把当前所有数据保存到dump.rdb文件中,如果在线上执行,建议使用BGSAVE命令)

 

RDB文件具体功能:用于保存和还原Redis服务器所有数据库中的所有键值对数据。

 

那么,什么是AOF持久化呢?

AOF(Append Only File)持久化:与RDB持久化通过保存数据库中的键值对来记录数据库状态不同,AOF持久化是通过保存Redis服务器所执行的写命令来记录数据库状态的。AOF持久化功能的实现可以分为命令追加(append)、文件写入、文件同步(sync)三个步骤。

 

AOF文件具体功能:通过保存所有修改数据库的写命令请求来记录服务器的数据库状态。

 

 


2.2 获取指定Redis的AOF持久化文件

一般情况,都是获取限制环境的AOF文件,那么如何在线上环境找到AOF文件呢?(PS:因为时间原因,可能忘记存储在哪里,所以以下提供一个搜索命令,方便操作)

sudo find / -name '*.aof'   # 此命令用于查找系统上所有以aof为后缀的文件

通过该命令,查看具体文件的路径信息,即可确认自己需要获取的AOF文件。

确定后,通过一下命令把指定AOF文件拷贝到本地主机上:

scp liuzhen@172.160.12.16:/home/liuzhen/prod_redis_data/redis/redis-appendonly.aof . # 从服务器复制远程文件到本地当前所在根目录

 


2.3 把Redis的持久化AOF文件转换为RDB文件

关于redis.conf文件中配置aof持久化操作信息简单介绍

(1)找到redis.conf文件,设置其中的字段属性:

appendonly no ——> appendonly yes

此处也可以在redis客户端,使用指令来完成修改:

redis 127.0.0.1:6379> config set appendonly yes  

OK  

redis 127.0.0.1:6379> BGREWRITEAOF   # 用于重写生成aof文件Background append only file rewriting started

此选项为aof功能的开关,默认为“no”,可以通过“yes”来开启aof功能  

只有在“yes”下,aof重写/文件同步等特性才会生效  

(2)在redis.conf文件中,指定aof文件的名称

appendfilename "appendonly.aof"  # 这是文件中默认的配置名称,也可以自己修改指定的文件名称

(3)在redis.conf文件中,确认 aof操作中文件同步策略

配置默认结果:

# appendfsync alwaysappendfsync everysec# appendfsync no

即选用everysec,具体意思:

1. no:表示等操作系统进行数据缓存同步到磁盘.

2. always:表示每次更新操作后手动调用fsync() 将数据写到磁盘.

3. everysec:表示每秒同步一次.一般用everysec

(4)在redis.conf文件中,确认 aof-rewrite期间,appendfsync是否暂缓文件同步

配置默认结果:

no-appendfsync-on-rewrite no

具体意思:

"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no”  

(5)在redis.conf文件中,确认 aof文件rewrite触发的最小文件尺寸(mb,gb),以及 相对于“上一次”rewrite,本次rewrite触发时aof文件应该增长的百分比

配置默认结果:

auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb

 

 

具体实施步骤:

(1) 创建一个新的redis.conf文件,该文件命名可采用redis_port.conf形式,例如:redis_6391.conf。该文件中内容起初完全何Redis默认的redis.conf文件中内容一致

(2) 修改redis_6391.conf指定的port值,在文件中搜索port把默认的6379修改为6391

(3) 修改redis_6391指定的dir值,在文件中搜索dir把默认的".\"改为自己要存放文件的具体路径。该路径用于存放RDB文件和AOF文件

(4) 修改redis_6391指定的appendfilename值,在文件中搜索appendfilename把默认的"appendonly.aof"改为自己想要定义的文件名称,该文件即为AOF文件的最终名称

(5) 修改redis_6391指定的dbfilename值,在文件中搜索dbfilename把默认的"dump.rdb"改为自己想要定义的文件名称,该文件即为RDB文件的最终名称

(6) 此步骤最重要,修改redis_6391指定的appendonly值,在文件中搜索appendonly把默认的"no"改为"yes"。这句配置意思是Redis服务重启后,默认不加载AOF持久化文件恢复数据,而是去找RDB持久化文件恢复;如果修改为"yes"后,发现有AOF文件,会首先加载AOF文件恢复数据

以下给出我本机修改后的redis_6391.conf文件中具体配置代码:

 redis_6391.conf源码

(7) 重启指定端口的服务,例如此处在Redis按照src目录下,运行./redis-server redis_6391.conf即可启动服务,待服务完成启动成功后,即可把指定的AOF文件数据加载进去(PS:此步骤需要先确认指定目录下的AOF文件已被替换成目标AOF文件,期间可以多次重启实现具体AOF文件加载)

以下给出我本机使用Redis加载启动大小为1.7G的aof文件,由于文件比较大,所以加载的时间有点长,此处是加载了60秒。

liuzhen@liuzhen-ubuntu:~/redis-2.8.17/src$ ./redis-server redis_6391.conf

[68180] 19 Jul 15:02:07.997 * Increased maximum number of open files to 10032 (it was originally set to 1024).

                _._                                                  

           _.-``__ ''-._                                             

      _.-``    `.  `_.  ''-._           Redis 2.8.17 (00000000/0) 64 bit

  .-`` .-```.  ```\/    _.,_ ''-._                                   

 (    '      ,       .-`  | `,    )     Running in stand alone mode

 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6391

 |    `-._   `._    /     _.-'    |     PID: 68180
  `-._    `-._  `-./  _.-'    _.-'                                   

 |`-._`-._    `-.__.-'    _.-'_.-'|                                  

 |    `-._`-._        _.-'_.-'    |           http://redis.io        

  `-._    `-._`-.__.-'_.-'    _.-'                                   

 |`-._`-._    `-.__.-'    _.-'_.-'|                                  

 |    `-._`-._        _.-'_.-'    |                                  

  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       

          `-._        _.-'                                           
              `-.__.-'                                               
 [68180] 19 Jul 15:02:08.011 # Server started, Redis version 2.8.17[68180] 19 Jul 15:05:12.843 * DB loaded from append only file: 184.831 seconds

[68180] 19 Jul 15:05:12.843 * The server is now ready to accept connections on port 6391[68180] 19 Jul 15:05:13.008 * 10000 changes in 60 seconds. Saving...

[68180] 19 Jul 15:05:13.084 * Background saving started by pid 68228[68228] 19 Jul 15:05:47.548 * DB saved on disk

[68228] 19 Jul 15:05:47.613 * RDB: 23 MB of memory used by copy-on-write

[68180] 19 Jul 15:05:47.717 * Background saving terminated with success

[68180] 19 Jul 15:07:54.064 * DB saved on disk

[68180] 19 Jul 15:08:58.096 * Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis.

[68180] 19 Jul 16:49:14.515 * Background saving started by pid 90980[90980] 19 Jul 16:56:56.883 * DB saved on disk

[90980] 19 Jul 16:56:56.966 * RDB: 4 MB of memory used by copy-on-write

[68180] 19 Jul 16:56:57.418 * Background saving terminated with success

(8)打开Redis客户端,运行./redis-cli -p 6391,客户端启动成功后,运行命令save,等待命令运行成功后,即可得到本步骤最终目标的RDB持久化文件(PS:此处如果是在线上环境尝试,建议采用bgsave命令)

此处给出,使用AOF文件还原数据后,查看具体数据信息的结果:

liuzhen@liuzhen-ubuntu:~/redis-2.8.17/src$ ./redis-cli -p 6391

127.0.0.1:6391> info# Serverredis_version:2.8.17redis_git_sha1:00000000redis_git_dirty:0

redis_build_id:4ba260b6ab802599

redis_mode:standalone

os:Linux 4.13.0-39-generic x86_64

arch_bits:64multiplexing_api:epoll

gcc_version:5.4.0

process_id:68180run_id:97cddc494e3924885bacb03776dfe09e8fa055f9

tcp_port:6391uptime_in_seconds:9400uptime_in_days:0

hz:10lru_clock:5266472config_file:/home/liuzhen/redis-2.8.17/src/redis_6391.conf 

# Clientsconnected_clients:1client_longest_output_list:0

client_biggest_input_buf:0

blocked_clients:0 

# Memoryused_memory:2239514040used_memory_human:2.09G

used_memory_rss:330895360used_memory_peak:2272377648used_memory_peak_human:2.12G

used_memory_lua:38912mem_fragmentation_ratio:0.15mem_allocator:jemalloc-3.6.0 

# Persistenceloading:0

rdb_changes_since_last_save:0

rdb_bgsave_in_progress:0

rdb_last_save_time:1531990617rdb_last_bgsave_status:ok

rdb_last_bgsave_time_sec:463rdb_current_bgsave_time_sec:-1aof_enabled:1aof_rewrite_in_progress:0

aof_rewrite_scheduled:0

aof_last_rewrite_time_sec:-1aof_current_rewrite_time_sec:-1aof_last_bgrewrite_status:ok

aof_last_write_status:ok

aof_current_size:1700508277aof_base_size:1699947297aof_pending_rewrite:0

aof_buffer_length:0

aof_rewrite_buffer_length:0

aof_pending_bio_fsync:0

aof_delayed_fsync:1 

# Statstotal_connections_received:2total_commands_processed:281instantaneous_ops_per_sec:0

rejected_connections:0

sync_full:0

sync_partial_ok:0

sync_partial_err:0

expired_keys:9290evicted_keys:0

keyspace_hits:1065050keyspace_misses:0

pubsub_channels:0

pubsub_patterns:0

latest_fork_usec:101807 

# Replicationrole:master

connected_slaves:0

master_repl_offset:0

repl_backlog_active:0

repl_backlog_size:1048576repl_backlog_first_byte_offset:0

repl_backlog_histlen:0 

# CPUused_cpu_sys:46.01used_cpu_user:189.71used_cpu_sys_children:134.11used_cpu_user_children:79.12 

# Keyspacedb1:keys=1146336,expires=51965,avg_ttl=276142509

127.0.0.1:6391>

 

备注:在Redis指定端口服务加载给定的AOF文件时,如果AOF文件过大,系统可能会报如下错误:

 Can't save in background: fork: Cannot allocate memory

解决办法:

修改系统/etc/sysctl.conf文件,并添加以下内容:

vm.overcommit_memory=1

在 FreeBSD上:

sudo /etc/rc.d/sysctl reload

在 Linux上:

sudo sysctl -p /etc/sysctl.conf

 

 

 


参考资料:

 

原文出处


0人推荐
随时随地看视频
慕课网APP