Redis高级篇

分布式缓存,多级缓存,底层原理

Redis高级篇

Redis持久化

RDB(RedisDatabase)

RDB 会在指定的时间间隔(比如每 5 分钟)对 Redis 的内存数据进行一次“拍照”,生成一个二进制文件(dump.rdb)。这个文件可以自己设置名称,默认为dump.rdb.这个文件包含了当时的所有数据状态。

如果 Redis 崩溃了,重启时会加载最近的dump.rdb来恢复数据。

如果使用命令save可以直接保存rdb文件

每次启动Redis的时候Redis就会访问这个rdb文件来获取以前的数据

每次关闭Redis服务端的时候都会生成一个新的dump.rdb

文件就在这里

如果只是关机的时候使用,万一什么时候Redis宕机了,就无法恢复数据了,这时候得用间隔保存了,这时候只需要打开Redis配置文件,修改如下字段

# save ""表示注释掉了 Redis 的默认 RDB 持久化策略(即禁用默认的自动快照生成)。

下面的意思是900秒内有1次操作就保存一次,300秒内10次操作就自动保存一次,60秒内有10000次操作就保存一次.

fork 子进程:Redis 调用 fork() 创建一个子进程,子进程与主进程共享内存数据。

COW(Copy-On-Write):

  • 子进程开始快照操作时,主进程仍可处理客户端请求并修改数据。
  • 当主进程修改某个数据页时,操作系统会将该页复制一份(写时复制),子进程看到的仍是修改前的数据。
  • 子进程将所有数据页写入磁盘生成 .rdb 文件,而主进程不影响快照的一致性。

COW有缺点就是,如果我的Redis已经占用了很高的内存,此时我要修改的数据也很多,复制的数据非常多会导致内存溢出

并且修改次数多,导致复制次数也多,开销也很大

修改次数少的时候如果宕机就会导致大部分数据丢失

AOF(Append-Only File)

AOF则是记录每一次操作Redis的命令,把命令记录在磁盘中,如果后面需要恢复就再执行一次所有Redis命令,下面的就是AOF文件

只有修改了redis.conf中的如下文件后才能使用

有如下三种记录频率

第一个是每写一次命令,执行完后就写入磁盘,然后返回信息,这样就很慢了,和直接操作数据库没有区别,第二个方法是隔了一秒后进行,实现了异步处理,顶多丢失1秒的数据,最后一种由操作系统判断什么时候写回磁盘,推荐使用第二种.

下面是AOF文件中的内容

如果我写三个如下命令

1
2
3
4
5
6
127.0.0.1:6379> set name111 dinglz
OK
127.0.0.1:6379> set name111 wfg
OK
127.0.0.1:6379> set name111 666
OK

这样直接写入aof文件会比较占内存,可以使用如下命令来重写AOF文件

1
BGREWRITEAOF

重写后的文件如下

直接就看不懂了,但是这样确实简化了AOF文件,不用连续设置三次才得到最终数据.

1
2
3
127.0.0.1:6379> bgrewriteaof
Background append only file rewriting started
127.0.0.1:6379>

可以看到这个命令甚至是在后台执行的

通常情况下是两种持久化机制一起使用,可以保证数据的稳定性

Redis主从同步

主从同步示例要三个Redis,我们可以使用windows本地复制三个Redis文件,然后修改配置文件,端口号6379,6380,6381,或者直接用docker,pull下redis的最新版本,然后创建三个实例.

分别启动三个Redis的服务端,然后再Redis-cli的6380上输入如下名令

1
slaveof 127.0.0.1 6379

意思是Redis6380要成为6379的从节点

也可以使用如下命令

1
replicaof 127.0.0.1 6379

这时候6380就是6379的从节点了

当我们在6379上使用set命令

1
2
3
127.0.0.1:6379> set number 111
OK
127.0.0.1:6379>

那么从节点上也可以看到被修改了

1
2
3
4
5
6
 ~  .\redis-cli.exe -p 6381 -h localhost
localhost:6381> replicaof localhost 6379
OK
localhost:6381> get number
"111"
localhost:6381>

这就实现了主从同步

全量同步

在我们输入slaveof host port之后,slave向master发送了自己的replid和offset,id和master肯定不一样,这时候就告知master这时候得做全量同步,清空slave本地缓存,把master生成的RDB发给slave进行数据同步.

并且在建立主从关系后,master会把自己的命令都交给slave去做数据同步,增量同步.

增量同步

repl_baklog是记录了RDB期间的所有命令的一个文件,是环状读写的,每次做增量同步的时候slave都会发送自己的offset,master在自己的repl_baklog表中查找offset,如果找到的话就把offset后面的数据交给master.下图红绿交接就是offset

如果slave宕机了,而且时间还挺长,master写repl_baklog文件已经覆盖了offset,那此时只能做一个全量同步.

可以从以下几个方面来优化Redis主从就集群:

  • 在master中配置repl-diskless-syncyes启用无磁盘复制,避免全量同步时的磁盘IO。

  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO

  • 适当提高repl baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力,可以直接从其他slave上直接读取数据,而不是都找master

哨兵模式

哨兵的工作原理

Redis的哨兵(Sentinel)是一个监控和故障转移系统,用于管理Redis主从复制架构中的高可用性。它在Redis 2.8版本中被引入,主要目的是解决当主节点出现故障时,如何自动完成故障发现和故障转移的问题。以下是关于Redis哨兵的一些

哨兵每一秒广播发送一次ping命令,告诉所有节点,自己没有宕机

如果某个节点在指定时间内没有响应,则会被标记为“主观下线”。如果主节点被标记为主观下线,哨兵会询问其他哨兵实例,根据多数哨兵的意见决定是否将其标记为“客观下线”。

客观下线后就会触发主从交换,选出一个offset最大的slave,向其发送slaveof no one,让其成为master节点,然后强制修改原主节点的配置文件,让那个redis slave of新的master,然后让所有节点都执行slaveof新master.

Licensed under CC BY-NC-SA 4.0