分布式缓存之Redis持久化

单点Redis的问题:
1.Redis是内存存储, 服务重启 可能会丢失数据
2.单节点Redis并发能力虽然不错,但也 无法满足如618这样的高并发场景
3.如果Redis 宕机,则服务不可用,需要一种自动的故障恢复手段。
4.Redis基于内存, 单节点能存储的数据量难以满足海量数据需求
解决:
1.数据丢失问题: 实现数据持久化,将数据写入磁盘
2.并发能力问题: 搭建主从集群,实现读写分离
3.故障恢复问题: 利用Redis哨兵,实现健康检测和自动恢复
4.存储能力问题: 搭建分片集群,利用插槽机制实现动态扩容

1.RDB持久化

       RDB全称Redis Database Backup file( Redis数据备份文件),也被叫做 Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后,从磁盘读取快照文件,恢复数据。
       快照文件称为RDB文件,默认保存在当前运行目录。

1.如何启动RDB:直接redis-cli -> save

注意:由Redis主进程来完成,但Redis是单线程的,RDB是将数据写到磁盘,磁盘的IO比较慢,如果数据量又很大就要耗时很久,在此期间,无法处理其他的请求,只适合停机时使用。(不推荐)


2.bgsave

运行那一刻就返回结果,在后台异步执行保存操作。主进程不受影响,可以正常处理请求。


3.主动停机时会自动进行一次RDB,在运行目录生成dump.rdb文件。

./redis-cli -a 密码 shutdown:如果redis是后台启动可以这样关闭。
       如果要查看Redis输出日志需要在redis.conf中找到logfile "",后面填写路径(绝对路径),loglevel是日志等级默认notice,有debug,verbose,notice,warning.

问题1

redis会在自己正常停机时保存,但如果redis是宕机的就不会保存了。

解决

每隔一段时间,数据就备份一次。


4.Redis内部有触发RDB的机制,可以在redis.conf文件中找到


存入一个值后在日志中就可以看到这样一个日志

实现了每隔一段时间保存一次。RDB的时间不能设置过长(没有持久化,在这段时间宕机的话数据会丢失),也不能过短(频率过高,来不及处理),一般就默认。所以还要有其他持久化方案来弥补RDB方案。


5.RDB的其他配置


RDB如何实现异步持久化

bgsave开始时会fork主进程得到子进程,子进程共享主进程的内存数据。完成fork后读取内存数据并写入RDB文件。 
    问题2

主进程的子进程是异步执行的,但fork是主进程执行的会堵塞其他请求

解决:尽量缩短fork的时间

fork底层实现

        在Linux系统中所有的进程度无法直接操作物理内存,而是操作系统给每个进程分配虚拟内存,主进程只能操作虚拟内存,而操作系统会维护一个虚拟内存与物理内存之间的映射关系表,这个表称之为页表。所以主进程操作于虚拟内存,而虚拟内存基于页表的映射关系到物理内存真正的存储位置。这样就能实现对物理内存数据的读写。

执行fork时,会去创建一个子进程拷贝主进程的页表,也就是把映射关系拷贝给子进程。而子进程有了和主进程一样的映射关系,当子线程在操作自己的虚拟内存时,由于映射关系和主进程一样,所以可以映射到相同的物理内存区域,这样就实现了子进程和主进程内存空间的共享

这样就无需拷贝内存中的数据,直接实现内存共享,这个速度就会变得非常快,堵塞的时间就尽可能缩短了,而后子进程就可以读取自己的数据了,而后写入磁盘的文件中去。这样异步持久化就实现了。


问题3

子进程在写数据到磁盘中的时候,主进程是可以接收请求修改内存中的数据的,这样可能会出现脏数据。

解决

fork采用的是copy-on-write技术:

1.当主进程执行读操作时,访问共享内存;

     2.当主进程执行写操作时,则会拷贝一份数据,执行写操作;


fork会将主进程和子进程共享的数据标记成read-only(只读模式),如果主进程要写的话就需要先将数据拷贝出来再执行写操作。如果执行了拷贝,主进程以后读也要到拷贝出来的地方读。


问题4

在极端情况下可能会发生子进程写得比较慢,耗时比较久,而在写的过程中,不断有新的请求来修改共享数据,导致所有的数据都修改了,那么这种情况下所有数据都要拷贝一份新的导致内存翻倍。

解决

一般情况下Redis都要预留一些内存空间,防止在做RDB时有内存溢出问题


RDB总结

1.RDB方式bgsave的基本流程

1.fork主进程得到一个子进程,共享内存空间

      2.子进程读取内存数据并写入新的RDB文件

      3.用新RDB文件替换旧的RDB文件

2.RDB的执行时间

  1. 默认是服务停止时。(save)

  1. 满足配置文件中save条件时(bgsave)

3.RDB的缺点

  1. RDB执行间隔时间长,两次RDB之间写入数据有丢失的风险

  1. fork子进程,压缩,写出RDB文件都比较耗时


2.AOF持久化

AOF全称为Append Only File( 追加文件)。Redis处理的每一个写命令都会记录在AOF文件, 可以看做是命令日志文件

注意:AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF


注意:AOF的命令记录的频率也可以通过redis.conf来配置

appendfsync always:     主进程立即将接收到的命令写到内存再记录AOF文件。
appendfsync everysec:将接收到的命令写到内存,再放到缓冲区,每隔一秒将缓冲区的内容写到AOF文件, 不是主进程往磁盘里写,性能得到了提高(内存方式的读写)

配置项

刷盘时机

优点

缺点

Always

同步刷盘

可靠性高,几乎不丢失数据

性能影响大

everysec

每秒刷盘

性能适中

最多丢失1秒数据

no

操作系统控制

性能最好

可靠性较差,可能丢失大量数据


更改配置后重启

1.输入写命令后会生成AOF文件

2.关闭redis时会有AOF数据的再次检查

3.重启后数据会从AOF文件做一次加载

这样就实现了持久化和故障恢复


问题5

RDB记录的是文件的值,而AOF记录的是操作,如果对同一个值做多次修改操作,RDB记录的只是最后的值,而AOF会记录每次的值,这样的话会导致AOF文件比RDB文件大很多。并且前面的操作都是多余的。

解决

   因为是记录命令,AOF文件会比RDB文件大得多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到同样的效果。


注意

Redis也会在触发阈值时自动去重写AOF文件。阈值可以在redis.conf中配置


3.RDB和AOF的区别

RDB和AOF各自有自己的优缺点,如果对数据安全性要求较高,在实际开发中往往会结合两者来使用。

RDB

AOF

持久化方式

定时对整个内存做快照

记录每一次执行的命令

数据完整性

不完整,两次备份之间会丢失

相对完整,取决于刷盘策略

文件大小

会有压缩,文件体积小

记录命令,文件体积很大

宕机恢复速度

很快

数据恢复优先级

低,因为数据完整性不如AOF

高,因为数据完整性更高

系统资源占用

高,大量CPU和内存消耗

低,主要是磁盘IO资源,但AOF重写时会占用大量CPU和内存资源

使用场景

可以容忍数分钟的数据丢失,追求更快的启动速度

对数据安全性要求较高常见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值