Redis持久化

Redis数据持久化到硬盘失败
在项目中用到了redis缓存,数据量8.5G,服务器内存16G,但是在redis持久化数据到硬盘上时失败了


注意标记为红色处,此处的意思是说:
Redis被配置为保存数据库快照,但它目前不能持久化到硬盘。用来修改集合数据的命令不能用。请查看Redis日志的详细错误信息。

原因分析
日志信息中说,数据持久化到硬盘上失败了。那么我们首先来了解一下什么时Redis中的持久化。
持久化
通过持久化功能,Redis保证了即使在服务器重启的情况下也不会损失(或者少量损失)数据。Redis中的持久化有RDB和AOF俩种方式。
RDB
RDB持久化通过保存数据中的键值对来记录数据库状态的不同。将某个时间点上的数据库状态保存到一个RDB文件(经过压缩的二进制文件)中,通过这个文件可以还原数据库状态


RDB持久化可以手动执行,也可以根据配置定期执行。
有俩个的Redis命令可以生成RDB文件,一个时SAVE,另外的一个是BGSAVE
SAVE命令会阻塞服务器进程,是同步的,不能处理任何命令请求
BGSAVE会派生出一个子进程,是异步的,服务器进程继续处理命令请求
自动间隔性保存:通过配置选项,让服务器每隔一段时间自动执行一次BGSAVE命令。
BGSAVE会派生一个子进程执行RDB的持久化工作,当通过配置save选项设置多个保存条件,任意一个条件满足,服务器会自动执行BGSAVE命令。
Redis的服务器周期性操作函数serverCron默认每隔100毫秒会执行一次,对正在运行的服务器进行维护,它的其中一项工作就是检测save选项所设置的保存条件是否已经满足,如果满足就执行BGSAVE命令。
对于BGSAVE命令,在Redis中的配置如下:


当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:Redis 调用 fork() ,同时拥有父进程和子进程。子进程将数据集写入到一个临时 RDB 文件中。当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

对于使用BGSAVE命令,生成rdb文件,在Redis中的配置如下,配置成使用压缩:



AOF
AOF是持久化是通过保存Redis服务器所执行的写命令来记录数据库状态。关于AOF的持久化方式在这里不做过多的讨论。

redis的相关的配置文件如下:


相关配置解释如下:

appendonly no 默认情况下,redis会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁。如果发生诸如拉闸限电、拔插头等状况,那么将造成比较大范围的数据丢失,所以redis提供了另外一种更加高效的数据库备份及灾难恢复方式。开启appendonly模式之后,redis会把所接收到的每一次写操作请求都追加到appendonly.aof文件中。当redis重新启动时,会从该文件恢复出之前的状态,但是这样会造成appendonly.aof文件过大,所以redis还支持了BGREWRITEAOF指令对appendonly.aof 进行重新整理,你可以同时开启asynchronous dumps 和 AOF;

appendfilename appendonly.aof  AOF文件名称,默认为"appendonly.aof";

appendfsync everysec  支持三种同步AOF文件的策略: no代表不进行同步,系统去操作,always代表每次有写操作都进行同步,everysec代表对写操作进行累积,每秒同步一次,默认是"everysec",按照速度和安全折中这是最好的。

持久化到硬盘上失败的原因
个人感觉采用fork主进程的方式很拙劣,但似乎是唯一的方法。内存中的热数据随时可能修改,要在磁盘上保存某个时间的内存镜像必须要冻结。冻结就会导致假死。fork一个新的进程之后等于复制了当时的一个内存镜像,这样主进程上就不需要冻结,只要子进程上操作就可以了。

在小内存的进程上做一个fork,不需要太多资源,但当这个进程的内存空间以G为单位时,fork就成为一件很恐怖的操作。何况在16G内存的主机上fork 14G内存的进程呢?肯定会报内存无法分配的。更可气的是,越是改动频繁的主机上fork也越频繁,fork操作本身的代价恐怕也不会比假死好多少。

所以简单的来说,Redis在保存数据到硬盘时为了避免主进程假死,需要Fork一份主进程,然后在Fork进程内完成数据保存到硬盘的操作,如果主进程使用了4GB的内存,Fork子进程的时候需要额外的4GB,此时内存就不够了,Fork失败,进而数据保存硬盘也失败了。

解决方法
方法一
查看日志文件:



内核参数overcommit_memory,它是内存分配策略

可选值:0、1、2。

0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2, 表示内核允许分配超过所有物理内存和交换空间总和的内存

编辑/etc/sysctl.conf ,改vm.overcommit_memory=1

方法二
可以看到redis配置文件中有如下的配置:


那么你可以将这个设置改成no,但是这样可能会将一些其它的key干掉,但是最后还是不能够正确将数据写入到硬盘上。不建议使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱coding的同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值