redis--AOF
- RDB 将数据库的快照( snapshot)以二进制的方式保存到磁盘中。
- 相当于MySQL binlog 的 raw模式
- AOF 则以协议文本的方式,将所有对数据库进行过写入的命令(及其参数)记录到 AOF
- 相当于MySQL binlog 的 satement模式
.png)
- 命令传播:
- Redis将执行完的命令、命令的参数、命令的参数个数等信息发送到AOF程序中。
- 缓存追加:
- AOF程序根据接收到的命令数据,将命令转换为网络通讯协议的格式,然后将协议内容追加到服务器的AOF缓存中。
- 文件写入和保存:
- AOF缓存中的内容被写入到AOF文件末尾,如果设定的AOF保存条件被满足的话,
- fsync函数或者fdatasync函数会被调用,将写入的内容真正地保存到磁盘中
if (execRedisCommand(cmd, argv, argc) == EXEC_SUCCESS):
if aof_is_turn_on():
# 传播命令到 AOF 程序
propagate_aof(cmd, argv, argc) if replication_is_turn_on():
# 传播命令到 REPLICATION 程序
propagate_replication(cmd, argv, argc)
- 接受命令、命令的参数、以及参数的个数、所使用的数据库等信息
- 将命令还原成 Redis 网络通讯协议
- 将协议文本追加到 aof_buf ( Redis 中 AOF 缓存)末尾
- WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF文件
- AOF 文件相当于MySQL redo log 缓存,然后使用一些策略,提升持久化到磁盘的效率
- 因为AOF 是后台进程,此时AOF 文件 是后台进程的 缓存
- SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。
- Redis 被关闭
- AOF功能被关闭
- 系统的写缓存被刷新(可能是缓存已经被写满,或者定期保存操作被执行)
- 子线程正在执行 SAVE ,并且:
- 1. 这个 SAVE 的执行时间未超过 2 秒,那么程序直接返回,并不执行 WRITE 或新的SAVE 。
- 在情况 1 中发生故障停机,那么用户最多损失小于 2 秒内所产生的所有数据。
- 2. 这个 SAVE 已经执行超过 2 秒,那么程序执行 WRITE ,但不执行新的 SAVE 。
- 注意,因为这时 WRITE 的写入必须等待子线程先完成(旧的) SAVE ,因此这里WRITE 会比平时阻塞更长时间
- 在情况 2 中发生故障停机,那么用户损失的数据是可以超过 2 秒的。
- 子线程没有在执行 SAVE ,并且:
- 3. 上次成功执行 SAVE 距今不超过 1 秒,那么程序执行 WRITE ,但不执行 SAVE 。
- 4. 上次成功执行 SAVE 距今已经超过 1 秒,那么程序执行 WRITE 和 SAVE 。
.png)
- 每次执行完一个命令之后,WRITE 和 SAVE 都会被执行。
- 另外,因为 SAVE 是由 Redis 主进程执行的
- 所以在SAVE执行期间,主进程会被阻塞,不能接受命令请求
- 不保存( AOF_FSYNC_NO):
- 写入和保存都由主进程执行,两个操作都会阻塞主进程。
- 每一秒钟保存一次( AOF_FSYNC_EVERYSEC):
- 写入操作由主进程执行,阻塞主进程。
- 保存操作由子线程执行,不直接阻塞主进程,但保存操作完成的快慢会影响写入操作的阻塞时长。
- 每执行一个命令保存一次( AOF_FSYNC_ALWAYS):和模式 AOF_FSYNC_NO 一样。
.png)
- 创建一个不带网络连接的伪客户端( fake client)。
- 读取 AOF 所保存的文本,并根据内容还原出命令、命令的参数以及命令的个数。
- 根据命令、命令的参数和命令的个数,使用伪客户端执行该命令。
- 执行 2 和 3 ,直到 AOF 文件中的所有命令执行完毕。
def READ_AND_LOAD_AOF():
# 打开并读取 AOF 文件
file = open(aof_file_name)
while file.is_not_reach_eof():
# 读入一条协议文本格式的 Redis 命令
cmd_in_text = file.read_next_command_in_protocol_format()
# 根据文本命令,查找命令函数,并创建参数和参数个数等对象
cmd, argv, argc = text_to_command(cmd_in_text)
# 执行命令
execRedisCommand(cmd, argv, argc)
# 关闭文件
file.close()
SADD animal cat // {cat}
SADD animal dog panda tiger // {cat, dog, panda, tiger}
SREM animal cat // {dog, panda, tiger}
SADD animal cat lion // {cat, lion, dog, panda, tiger}
def AOF_REWRITE(tmp_tile_name):
f = create(tmp_tile_name)
# 遍历所有数据库
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.write_command("SET " + key + value)
elif key.type == List:
# 用 RPUSH key item1 item2 ... itemN 命令来保存列表键
item1, item2, ..., itemN = get_item_from_list(key)
f.write_command("RPUSH " + key + item1 + item2 + ... + itemN)
elif key.type == Set:
# 用 SADD key member1 member2 ... memberN 命令来保存集合键
member1, member2, ..., memberN = get_member_from_set(key)
f.write_command("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.write_command("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 + member + 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()
- 子进程进行 AOF 重写期间,主进程可以继续处理命令请求
- 子进程带有主进程的数据副本,使用子进程而不是线程,可以在避免锁的情况下,保证数据的安全性。
- 数据不一致性
- 因为子进程在进行AOF重写期间,主进程还需要处理命令
- 这就可能造成数据库当前数据和重写后的AOF文件数据不一致
- Redis增加了一个AOF重写缓存,这个缓存在fork出子进程之后开始启用。
- Redis主进程在接到新的写命令之后,处理会将这个命令的协议内容追加AOF重写缓存
- 追加到现有AOF文件,就是遵循原本逻辑 命令传递->追加缓存->文件保存和写入
- 还会追加到这个缓存中:
.png)
- 现有的AOF功能会继续执行
- 所有对数据库进行修改的命令都会被记录到AOF重写缓存中。
- 将AOF重写缓存中的内容全部写入到新AOF文件中
- 完成之后,现有AOF文件,新AOF文件和数据库三者的状态完全一致
- 对新的AOF文件进行改名,覆盖原有的AOF文件。
- 程序完成新旧两个AOF文件交替
- 记录当前 AOF 文件大小的变量 aof_current_size
- 记录最后一次 AOF 重写之后,AOF 文件大小的变量 aof_rewirte_base_size
- 增长百分比变量 aof_rewirte_perc
- 没有 BGSAVE 命令在进行。
- 没有 BGREWRITEAOF 在进行
- 当前 AOF 文件大小大于 server.aof_rewrite_min_size (默认值为 1 MB)
- 当前 AOF 文件大小和最后一次 AOF 重写后的大小之间的比率大于等于指定的增长百分比。
- AOF 文件通过保存所有修改数据库的命令来记录数据库的状态。
- AOF 文件中的所有命令都以 Redis 通讯协议的格式保存。
- 不同的 AOF 保存模式对数据的安全性、以及 Redis 的性能有很大的影响。
- AOF 重写的目的是用更小的体积来保存数据库状态,整个重写过程基本上不影响 Redis主进程处理命令请求。
- AOF 重写是一个有歧义的名字,实际的重写工作是针对数据库的当前值来进行的,程序既不读写、也不使用原有的 AOF 文件。
- AOF 可以由用户手动触发,也可以由服务器自动触发。
redis--AOF的更多相关文章
- 深入剖析 redis AOF 持久化策略
本篇主要讲的是 AOF 持久化,了解 AOF 的数据组织方式和运作机制.redis 主要在 aof.c 中实现 AOF 的操作. 数据结构 rio redis AOF 持久化同样借助了 struct ...
- Redis AOF文件
[Redis AOF文件] 1.关于AOF AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集. AOF 文件中的命令全部以 Redis 协议的格式来保存 ...
- Redis AOF 全持久化
简介: Redis AOF 持久化,将每次接收到更改 redis 数据的操作都记录到一个 aof 文件,当服务器意外宕机或 redis 服务器非法关闭时,不会丢失数据. 可以做到数据安全化,但是性能会 ...
- redis AOF保存机制
网上说AOF有三种保存方式,不自动保存.每秒自动保存.每命令自动保存. 其中每秒自动保存这个看起来很美好,但是可能会被各种IO的时间所延迟,所以究竟是怎么判断每秒保存的,并不是太明白,故有此文. AO ...
- 解决redis aof文件过大的问题
执行BGREWRITEAOF命令对redis的AOF进行重写 redis-cli BGREWRITEAOF 相关解释: Redis的AOF机制有点类似于Mysql binlog,是Redis的提供的一 ...
- redis:aof恢复与rdb服务器间迁移
1. aof恢复与rdb服务器间迁移: 1.1. Aof恢复: 如果不小心执行了flushdb或flushall了怎么办? (1)立马执行命令:shutdown nosave 关闭服务器,为了防止其他 ...
- REdis AOF文件结构分析
REdis-4.0之前的AOF文件没有文件头,而从REdis-4.0开始AOF文件带有一个文件头,文件头格式和RDB文件头相同. REdis-4.0版本,如果开启aof-use-rdb-preambl ...
- redis aof和rdb区别
转自https://blog.csdn.net/m0_38110132/article/details/76906422 1.前言 最近在项目中使用到Redis做缓存,方便多个业务进程之间共享数据.由 ...
- redis AOF 和RDB
AOF定义:以日志的形式记录每个操作,将Redis执行过的所有指令全部记录下来(读操作不记录),只许追加文件但不可以修改文件,Redis启动时会读取AOF配置文件重构数据 换句话说,就是Redis重启 ...
- redis aof文件过大问题
http://www.itnose.net/detail/6682725.html 最近新安装了一台redis,版本为redis-3.2.5 数据盘用的是固态硬盘. 之前用的是普通硬盘,redis日志 ...
随机推荐
- HDU 4741 Save Labman No.004 ( 三维计算几何 空间异面直线距离 )
空间异面直线的距离直接套模板. 求交点:求出两条直线的公共法向量,其中一条直线与法向量构成的平面 与 另一条直线 的交点即可.还是套模板o(╯□╰)o 1.不会有两条线平行的情况. 2.两条直线可能相 ...
- python 常见的错误类型 和 继承关系
BaseException +-- SystemExit #系统结束 +-- KeyboardInterrupt #键盘中断 ctrl+D +-- GeneratorExit #主动结束 +-- Ex ...
- FOJ Problem 1015 土地划分
Problem 1015 土地划分 Accept: 823 Submit: 1956Time Limit: 1000 mSec Memory Limit : 32768 KB Probl ...
- HDU 1709 母函数天平问题 可出现减法的情况 The Balance
The Balance Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- Java并发容器--ConcurrentLinkedQueue
概述 ConcurrentLinkedQueue是一种基于链表实现的无界非阻塞线程安全队列,遵循先入先出规则. 线程安全队列有两种实现方式: 阻塞方式:对入队和出队操作加锁.阻塞队列. 非阻塞方式:通 ...
- 一种机制,与js类似
我们知道,当两个条件进行逻辑与操作的时候,其中任何一个条件为假,则表达式的结果为假.所以,遇到(A 且 B)这种表达式,如果A为假的话,B是不是真假都无所谓了,当遇到一个假条件的时候,程序也就没有必要 ...
- 培训补坑(day2:割点与桥+强联通分量)
补坑ing... 好吧,这是第二天. 这一天我们主要围绕的就是一个人:tarjan......创造的强联通分量算法 对于这一天的内容我不按照顺序来讲,我们先讲一讲强联通分量,然后再讲割点与桥会便于理解 ...
- andrio
## 以eclipse -clean命令从命令行启动 eclipse ## 配置Android模拟器 点击上图右边的按钮(像个手机一样的),打开AVD管理器后,点击 New 新建一个模拟器,输入Nam ...
- cocos2d programming guide 翻译 引导页(完结)
http://bbs.tairan.com/article-25-1.html Cocos2d官方入门指导 原文地址:http://www.cocos2d-iphone.org/wiki/doku. ...
- IOS-NSDate之今天,昨天,这周,这个月,上个月
http://blog.csdn.net/xdrt81y/article/details/8425727 今天跟大家讨论日期的用法,相信大家在项目中,经常会设置一个默认时间段,比如一周前到今天.下面教 ...