聊一聊Redis持久化开与关

vincent0809
发布于 2022-4-14 21:33
浏览
0收藏

经常能碰到这样的问题:

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

Redis的持久化功能被夸大和误解了,这个问题我解释过无数遍了,早就想写个说明了,今天“忍不了”,和大家聊聊我的一些认知,欢迎大佬们吐槽。

 

一、Redis”3“种持久化方式

 

1. RDB


简单来说,对Redis做一个快照(利用fork)保存在磁盘上

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

(1) 优点:

 

 • 结构紧凑体积小,加载速度快(相比AOF)
 • 可以做定期备份:例如低峰期(顺便搞个数据分析也行)


(2) 缺点:

 

 • 动作大、消耗大:全量操作对于磁盘、CPU、内存等均有消耗
 • 无法做到"实时"备份
 • 格式多变(Redis 3 4 5 6版本多次修改)


2. AOF


简单说把Redis的每条写操作记录到日志中,例如set hello world

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

简单说,落盘策略有三种:

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

(1) 优点:

 

 • RESP标准格式:无版本兼容性问题
 • 实时性更高且成本较小


(2) 缺点:

 

 • 体积大:协议 + 明文
 • 加载慢:利用fakeclient做回放
 • AOF重写还是动作不小(本文不讨论AOF重写)


3. RDB-AOF混合


持久化文件全量使用RDB,增量使用AOF,保证体积、实时性、加载速度。(Redis 4提供,本文不讨论)

 

二、开AOF性能会差多少?(注:AOF重写也是资源消耗大头,这里不讨论)

 

1.测试环境:


 • CPU: Intel(R) Xeon(R) Gold 6248 CPU @ 2.50GHz
 • 机械磁盘
 • Redis版本:4.0.14(未测试Redis 6多线程)
 • 压测工具:redis-benchmark
 • AOF策略:appendfsync everysec


2.压测方法:


测试Redis在”开和关“AOF情况下,在不同size(64字节、128字节、512字节)的OPS和耗时

 

(1) d=64字节

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

 

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

(2) d=128字节

 

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

(3) d=512字节

聊一聊Redis持久化开与关-鸿蒙开发者社区聊一聊Redis持久化开与关-鸿蒙开发者社区

 

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

3. 总结说明:(注意此处没有考虑AOF重写,只能更差)


(1) 开启AOF后,Redis的写性能下降了8~25%,读性能未下降(注意此处测试为非读写混合场景)

 

(2) 开启AOF后,随着数据量的增加相关读写性能会下降。

 

(3) 开启AOF后,实际测试中发现单核CPU也会少量上涨。

 

三、一些问题的讨论?


1. aof刷盘策略改为always能保证不丢数据吗?


(1) 答案


会丢。Redis执行一条写入命令时,会将数据写入aof_buf,但写入aof_buf和刷盘还是存在一次事件时间差。

 

(2) 原理:


Redis处理命令(server.c)processCommand->call(执行命令),其中包含

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

每次文件事件前的beforesleep(ae.c)

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

其中beforesleep包含了aof_buf落盘(server.c)

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

flushAppendOnlyFile利用操作系统的write和fsync(加上aof的三种策略)完成落盘:

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

2.Redis是什么一致性?


最终一致性。客户端写主后,不等从写完。(为什么这样?Redis设计目标是什么?快!)

 

3.master节点故障后Redis怎么恢复?

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

(1) 关闭AOF:B节点晋升成主节点,对外提供服务。A节点恢复后变为slave,依赖全量复制获取全部数据

 

(2) 开启AOF:同上...(只不过A节点全量复制后做一次AOF重写)

 

所以看起来此模式下,对于故障恢复持久化没什么用!

 

4.我就不想丢理论上最少的数据,怎么办?


开启always,不用主从切换,等待A节点恢复,重新加载AOF在提供服务,老哥这个现实吗???

 

五、最佳实践?


1.RDB最佳


(1) 自动save:关、关、关(性能杀手)

 

(2) save命令:同步,忘记它(除非你一点内存没有了,还需要RDB)

 

(3) bgsave命令:备份可以用,请关注fork时间(info stats可查)

 

(4) 关闭掉:做不到,因为全量复制默认会用。

 

2.AOF最佳


(1) always不要用(主线程执行、以及IO影响)

 

(2) everysec、no按需使用,如果仅仅想不丢数据,AOF做不到。

 

(3) 除非怕主从都挂了,可以考虑。

 

不要忘记AOF臭名昭著的:

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

3.单机多实例:你玩得起吗?


以一个80 core,500G内存的机器为例子,出于成本考虑至少要部署80~90个* memory(5G)的实例。在此场景下CPU、内存、网络的开销基本还能控制,但如果开了AOF,用普通的磁盘,行不行?

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

4. "旁门左道"用法


(1) RDB:

 

定期备份(例如低峰期)、数据分析(分析出bigkey、hotkey、idlekey等)(阿里云的做法)

 

(2) AOF

 

原生AOF语义太弱,如果想做类似binlog功能可以对Redis内核进行修改,多机房同步会用上。

聊一聊Redis持久化开与关-鸿蒙开发者社区

 

六、总结


Redis的持久化功能是一个重要功能,但如果想指望它实现“不丢数据”、“一致性”,那可能带来的就是:低性能、高成本。

 

 

文章转自公众号:Redis开发运维实战

分类
标签
收藏
回复
举报
回复
    相关推荐