面试官:今天要不来聊聊Redis的持久化机制吧?
+ H! h0 c- h/ a# z" r, t5 r候选者:嗯,没问题的! |% o3 p' u) k& o# c, [' H9 S
候选者:在上一次面试已经说过了Redis是基于内存的% u( [9 w6 y" c4 d+ u( _9 Z! t" x7 j
候选者:假设我们不做任何操作,只要Redis服务器重启(或者中途故障挂掉了),那内存的数据就会没掉$ i/ ^; p2 o# p
候选者:我们作为使用方,肯定是不想Redis里头的数据会丢掉
: ]- Q4 Y& T; T候选者:所以Redis提供了持久化机制给我们用,分别是RDB和AOF1 V8 r; `7 |' f( w7 z
2 h9 Z7 S" I3 L4 j/ a
B" }' y! _8 i. O5 Y
, Q! t9 B: h9 J$ p候选者:RDB指的就是:根据我们自己配置的时间或者手动去执行BGSAVE或SAVE命令,Redis就会去生成RDB文件$ R. G' b6 |' \/ v$ f
候选者:这个RDB文件实际上就是一个经过压缩的二进制文件,Redis可以通过这个文件在启动的时候来还原我们的数据# M# u# M5 i4 Y$ J! @& X0 r' v8 c) h
候选者:而AOF则是把Redis服务器接收到的所有写命令都记录到日志中! B+ N: z, O0 g$ ~3 d+ B R: k
候选者:Redis重跑一遍这个记录下的日志文件,就相当于还原了数据2 v7 U5 `! q5 ?
) f0 H2 @7 L4 L, R: U& B
1 F/ c8 S" R, v; w' K$ }, P5 }! e
! g% w# I) A/ P# M: }% o6 ?0 }$ d/ @面试官:那我就想问了,你上次不是说Redis是单线程吗
6 y# o/ }& b: U/ L面试官:那比如你说的RDB,它会执行SAVE或BESAVE命令,生成文件) J; s. x# i3 z4 V0 W
面试官:那不是非常耗时的吗,那如果只有一个线程处理,那其他的请求不就得等了?
4 p4 X. H) e/ A/ ~5 m候选者:嗯,没错,Redis是单线程的。
2 C" h. |8 `8 U( o5 O候选者:以RDB持久化的过程为例,假设我们在配置上是定时去执行RDB存储
* }$ ~( V7 c I& v候选者:Redis有自己的一套事件处理机制,主要处理文件事件(命令请求和应答等等)和时间事件(RDB定时持久化、清理过期的Key等的)
) P: v8 ~% v: k; H! N, f; X/ Y候选者:所以,定时的RDB实际上就是一个时间事件: m5 @' t- k+ W- i" u# h+ Y
候选者:线程不停地轮询就绪的事件,发现RDB的事件可执行时,则调用BGSAVE命令6 i5 }' p7 U0 { W
候选者:而BGSAVE命令实际上会fork出一个子进程来进行完成持久化(生成RDB文件)
( D5 c# O; b1 ?# t2 Y4 i+ k- j! q& g: a% Z0 ~# O/ S
; ^% v& I1 K8 b+ l# L
- A8 k. A9 C+ j$ x) a) p
候选者:在fork的过程中,父进程(主线程)肯定是阻塞的。
% Q$ F: H4 P3 \候选者:但fork完之后,是fork出来的子进程去完成持久化。处理请求的进程该干嘛的就干嘛! l. f9 [* D/ H' z$ `
候选者:所以说啊,Redis是单线程,理解是没错的,但没说人家不能fork进程来处理事情呀,对不对
- u0 \& N( e2 E% v* M1 R# g& k3 _! s候选者:还有就是,其实Redis在较新的版本中,有些地方都使用了多线程来进行处理4 ^$ o! a8 a! ] G# Y4 i9 u
候选者:比如说,一些删除的操作(UNLINK、FLUSHALL ASYNC等等)还有Redis 6.x 之后对网络数据的解析都用了多线程处理了。
* K" X) L2 v1 M& R/ M3 Z候选者:只不过,核心的处理命令请求和响应还是单线程。7 g4 O' z5 i" C
, V! v6 B7 h7 M7 |6 J' i0 I5 m
; {0 z; u6 D. J! x0 A0 g, r" L1 h% F! x! n' ^5 H
面试官:那AOF呢?AOF不是也要写文件吗?难道也是fork 了个子进程去做的?
0 W9 D: }8 _+ X! Q; v5 _2 Y候选者:emm,不是的。AOF是在命令执行完之后,把命令写在buffer缓冲区的(直接追加写)8 U* i: I8 G0 t
候选者:那想要持久化,肯定得存盘嘛。Redis提供了几种策略供我们选择什么时候把缓冲区的数据写到磁盘6 I" B, _ I4 u j8 s! s7 X7 [
候选者:我记得有:每秒一次/每条命令都执行/从不存盘;一般我们会选每秒一次4 E; e! I* V N* [) b
候选者:Redis会启一个线程去刷盘,也不是用主线程去干的
- Q; U! L, c8 C) ]/ C! h& U6 z8 Z面试官:那如果把执行过的命令都存起来
' K3 A R' q1 i: A2 O面试官:等启动的时候是可以再把这些写命令再执行一遍,达到恢复数据的效果4 B U) b7 Q* n# {3 z3 s ^% _1 n
面试官:这样会有什么样的问题吗?
' R; f" O0 I1 W$ W3 N1 z# ]/ [$ C2 ~( ~候选者:嗯,问题就是,如果这些写入磁盘的「命令集合」不做任何处理,那该「命令集合」就会一直膨胀) g2 h# F6 {0 m1 M6 Z
候选者:其实就是该文件会变得非常大
6 j' v) n6 q j# d5 \候选者:Redis当然也考虑了这一点,它会fork个子进程会对「原始」命令集合进行重写
$ M/ t% P1 n) D0 J- n% y" i8 J0 b候选者:说白了就是会压缩,压缩完了之后只要替换原始文件就好了
0 l7 m" z6 i2 ~% H9 N
@5 g, n% J" _: F( X: |
8 G2 P! h% g: U* j7 }" h7 a4 J) e
0 D6 W" J. }. E: y面试官:那我又想问了,既然它是fork一个进程来对AOF进行重写的
$ {- }7 d& d7 Y) G5 C, K; [" v6 E' n面试官:前面你也提到了再fork时,主进程是阻塞的,但fork后,主进程会继续接收命令
2 O4 D; }# ?6 J' c+ W0 V2 [0 I6 A3 y面试官:你是说重写完(压缩)会进行文件覆盖
3 z* t8 O. z! J! p: @& d4 ~面试官:那这样不会丢数据吗?毕竟主进程在fork之后是一直会接收命令的7 X2 L2 Q5 Z7 E& t
候选者:哦,我明白你的意思了。
3 z3 L. s0 t) c5 q# }9 b" o候选者:其实做法很简单啊,在fork子进程之后,把新接收到命令再写到另一个缓冲区不就好了吗
, R: X% T0 D" n/ N' D+ l面试官:可以, s$ J1 ?7 Q j0 r4 k+ s
面试官:那AOF和RDB用哪一个呢?) P( H) p5 ^& `
候选者:主要是看业务场景吧,我们这边是基于Redis自研了一套key-value存储$ E% H8 Y# f, K& R
面试官:自研的?你们的Redis架构是什么?
7 {! w0 M- g7 ]# e5 Z% D候选者:别别别,当我没说。就是开源的,开源的。我们回到RDB和AOF上吧。
" d2 b8 n, c. D, q1 q候选者:在新增namespace(实例) 的时候也会让你选择对应的使用场景; v. C, l& V% L0 B. a1 i3 x7 w
候选者:就是会让你通过不同的应用场景进行配置选择' e0 b) N: Q" [2 X& R
候选者:比如说,业务上是允许重启时部分数据丢失的,那RDB就够用了(:4 |; o4 b) |& E2 o+ }
候选者:RDB在启动的时候恢复数据会比AOF快很多- ` Y5 t& c e* b
候选者:在Redis4.0以后也支持了AOF和RDB混合; i, |! V K3 D: `- U/ h# v$ a
' q3 o- {! Q# F Y: t8 B6 @
& {2 \% [9 l8 I0 t; |/ I9 x
" r& U6 Q0 _1 K) w3 c1 d
候选者:在官网是不建议仅仅只使用AOF的,如果对数据丢失容忍度是有要求的,建议是开启AOF+RDB一起用2 k, [1 [3 [( Q! K/ g$ k
候选者:总的来说,不同的场景使用不同的持久化策略吧( [7 ^! J, Y. Y8 {6 U
面试官:了解/ I( C; q" u# [( X7 `3 X0 u
面试官:顺便我想问下,假如Redis的内存满了,但业务还在写数据,会怎么样?
/ K3 N- a2 \/ H1 b* ]2 U& W$ I/ o候选者:嗯,这个问题我也遇到过
0 x9 v' T& {4 H7 {% J t候选者:一般来说,我们会淘汰那些「不活跃」的数据,然后把新的数据写进去0 Z# f5 M% i7 q, c- B
候选者:更多情况下,还是做好对应的监控和容量的考量吧
/ \' L( B$ \8 V/ U# B候选者:等容量达到阈值的时候,及时发现和扩容
. j e$ |% Y5 T* x面试官:你这懂得有点多啊
" O+ W5 ~2 t5 G% T1 A6 T2 o本文总结:
2 X& [5 A7 m! ?, ?0 G
. Q6 G2 g1 V$ G1 k) z& T/ N- Redis持久化机制:RDB和AOF
5 d- H& ~( j4 p' Q8 @7 g - RDB持久化:定时任务,BGSAVE命令 fork一个子进程生成RDB文件(二进制)9 W& y: Q, \) F
- AOF持久化:根据配置将写命令存储至日志文件中,顺序写&&异步刷盘(子线程),重写AOF文件也是需要 fork 子进程。Redis4.0之后支持混合持久化,用什么持久化机制看业务场景
. k# D# V- M) L" b ) C3 }% J: G( t: d
9 D# y" M. Z" j
我最近一直在连载《对线面试官》系列,目前已经连载38篇啦!一个说人话的面试系列!& X! y6 s0 c+ H: x2 U
. ~1 G- _. z( ], k. Q0 Z
- 【对线面试官】HTTP
1 f$ L# c/ l5 o& W4 [' o- F2 p/ t - 【对线面试官】Java注解1 p5 `& h/ C( S: ]$ H. l
- 【对线面试官】Java泛型
# |% Z/ z; I7 ?& i - 【对线面试官】 Java NIO
! B$ n: c0 h8 Q' b - 【对线面试官】Java反射 && 动态代理+ j8 o! A0 r7 U$ L. s& @) L
- 【对线面试官】多线程基础
9 S h; w* N, R9 ^' x# i - 【对线面试官】 CAS
3 W4 u7 V1 ^; k; m% p; a - 【对线面试官】synchronized
$ j$ G8 e( e+ ^% F5 l% n0 V2 _8 k - 【对线面试官】AQS&&ReentrantLock
" G1 u; e" A3 H# q: Q5 W" L& @& N - 【对线面试官】线程池( o3 D( z% P7 M; H Z# R
- 【对线面试官】ThreadLocal
0 N6 s5 w$ x, B& j. e7 N - 【对线面试官】CountDownLatch和CyclicBarrier+ B/ b: |8 f- u/ W
- 【对线面试官】为什么需要Java内存模型?" H! T, u1 u0 j" }9 M2 b+ c' W& H
- 【对线面试官】深入浅出 Java 内存模型, O T y1 R2 h& |+ o+ @7 W! x9 E: X
- 【对线面试官】Java从编译到执行,发生了什么?* t9 i' ]/ K1 [' }8 j# j" n6 r
- 【对线面试官】双亲委派机制% ~5 N; `$ o) }# Z# [ E i: B
- 【对线面试官】JVM内存结构
3 L0 P: C/ P( ?" K. `/ `/ t" Z( Q - 【对线面试官】垃圾回收机制" q8 j4 Z+ b' g/ C2 P+ `
- 【对线面试官】CMS垃圾回收器
+ Y& C4 ?0 s- I8 F - 【对线面试官】G1垃圾收集器
1 S H2 T* x: w# I2 ~+ \4 C - 【对线面试官】JVM调优
3 Q& X+ I8 W3 U - 【对线面试官】List
; O w5 j2 K& ?3 I - 【对线面试官】Map
% |- d& `6 H& i+ j3 d. W* V - 【对线面试官】SpringMVC
! Z. T/ d: b0 V% D8 ^# V - 【对线面试官】Spring基础( s/ b5 d# e0 f H4 u
- 【对线面试官】SpringBean生命周期
5 I( L0 ^8 q1 ]/ }9 }1 H - 【对线面试官】Redis基础
. a( [" T* s) i m1 A - 【对线面试官】Redis持久化" u. N) p: |$ _
- 【对线面试官】Redis主从架构
) h/ `4 p! f; k: T5 p2 @ - 【对线面试官】Redis分片集群; d, V2 E6 |1 }
- 【对线面试官】Kafka基础+ m( y. V; o/ V) q, F2 o7 [" g" R( M
- 【对线面试官】使用Kafka会考虑什么问题?
& x, V& R; Q- A0 p9 ` - 【对线面试官】MySQL索引7 v2 ^: l0 _& r) ?- o0 z
- 【对线面试官】MySQL 事务&&锁机制&&MVCC
8 K5 F. z. H0 P0 M - 【对线面试官】MySQL调优; R! u/ }" E' J8 ]
- 【对线面试官】如何实现幂等和去重?. l) t1 P5 I/ }- D* Z& Q, d
- 【对线面试官】系统需求多变时,如何设计3 ~- z, P0 H6 g, B. O! V. y
- 【对线面试官】设计模式
3 N# J N' Z Q% R, E3 ?" ^ - ...
( t6 y3 S: L# i" d 【大厂面试知识点】、【简历模板】、【原创文章】电子书,共有1263页! F* m: Y! F3 ^7 |( I8 C1 q
我把这些上传到网盘,你们有需要直接下载就好了。做到这份上了,不会还想白嫖吧?点赞和转发又不用钱。) }- i+ p9 r/ E* C' [% T( {. L' n* M
2 O# I7 g$ h/ G( z4 a
5 u [8 q0 K- B) E
, h9 a# K: b* L7 @; I链接:pan.baidu.com/s/1pQTuKBYs… 密码:3wom+ o2 {6 o: Z7 p
不会有人刷到这还想白嫖吧?不会吧?点赞对真的我很重要!要不加个关注? @Java3y |