Redis数据持久化

最近项目重启的时候,redis出现了一个错误:Failed opening the RDB file crontab (in server root dir /etc) for saving:Permission denied的问题,导致redis缓存中的数据全部丢失了,项目中查询redis缓存数据全部失效,这里先说出来解决方法是给redis设置密码即可解决。

主要是对报错信息比较感兴趣, RDB file crontab这个是什么文件呢,root dir /etc这个dir又是做什么的呢,为什么会提示没有权限呢? 经典的夺命三连,哈哈哈,现在我们就一起来解决这些疑问。

首先第一个问题主要涉及到redis日志文件

  1. 关于redis数据的持久化问题

随着redis的广泛流行,基本上redis在项目中用来存储热点数据是大家都比较钟爱的选择,而redis的快是它的最大优势,而这个快就体现在redis的数据在存储在内存中的,不需要经过磁盘io,从而节省很多磁盘寻址的时间,提高数据访问的速度,但是在内存中的数据始终容易丢失,服务重启或者某些不可控因素都会使得redis数据丢失,所以redis的数据的持久化是很值得我们去了解和学习的,保证线上数据能够得到持久化的访问。

在redis数据的持久化中,用到的和mysql一样的日志逻辑,通过将每一次对redis的操作用日志记录下来,写入磁盘,这样,当服务器重启时候,会从磁盘中读取redis的日志文件,从而来恢复redis中的热点数据。

redis的备份方式主要有两种,AOF日志和RDB快照,我们来看看两者的异同

AOF日志

我们知道mysql的日志文件是写前日志,在实际写入数据之前,先把对应的操作写到日志,而redis则是写后日志,先把数据写到内存中,然后再把数据写到日志文件中,我们知道mysql的redolog日志存储的是物理修改语句,比喻什么字段修改成了xx值(这里后面会详细介绍一下mysql的日志,比如 undolog,redolog,binlog),而AOF日志存储的是每次redis接收到的名宁语句,比如 set xx xx,这里有一个非常重要的一点,就是AOF日志为了避免检查的开销,不会对写入的命令进行检查,如果是写前日志,那么在宕机恢复的时候,可能会读到错误的命令,所以AOF写后日志的好处就是可以保证写到日志的命令都是正确的,这样在数据恢复的时候不会出错。而且redis是在写操作之后才写日志,这样也不会阻塞当前的写操作。

但是AOF日志也有两个潜在风险。

第一,如果服务器在redis写入内存后就宕机了,数据此时是没有写到日志的,那么在服务重启,数据恢复的时候,可能会造成数据的丢失。

第二,之前说了,写后日志不会阻塞当前写操作,但是会阻塞后续的操作,应为写入日志的线程也是在主线程之中的,如果磁盘io的压力过大,就会阻塞后续的redis操作。

上面两个情况都是和磁盘写入的时机相关的,我们来看看redis关于这方面的设计方式

  • Alway(同步写回):每个写命令执行完,就会把相应命令写到磁盘。
  • Everysec(每秒写回):每个写命令执行完,会把当前的日志写到内存缓冲区,然后每隔一秒钟将数据将数据写到磁盘。
  • NO(系统写回):每个写命令执行完,会把当前的日志写到内存缓冲区,由系统来决定合适将数据写到磁盘。

通过上面三种方式,我们知道都不能把保证数据不丢失,可以根据项目中的时间情况来选择使用哪一种方式。

在这里插入图片描述

其实不知道大家有没有想到一个问题,随着AOF日志文件越来越大,日志写入磁盘的效率也会降低,同时在恢复数据的时候,过大的AOF日志会导致数据恢复的时间线拉长,所以AOF日志有一个重写机制。

重写机制是指把多个redis命令整合成一个命令来减少AOF日志文件的大小,那么这个整合又是什么意思呢,因为AOF日志是采用追加的方式,对于一行数据,可能经历过了多次的修改,那么在日志文件中就会有多个命令,但其实只需要记住当前最后一条命令即可,所以重写机制就是读取当前redis的所有数据,然后用set命令对每条数据进行记录,用新的AOF日志来替换旧的AOF日志,这样就减少了AOF日志文件的大小。

那么AOF日志重写会阻塞主线成么?

其实是不会的,和写入AOF日志在主线程进行不同,重写机制是redis专门fork一个子线程来进行的,所以不会阻塞主线程,而且在重写的同时,新的AOF日志会由主线程卸载缓冲区,不会造成数据日志的丢失。

RDB快照

相比于AOF日志存储的是redis的操作命令,当AOF文件过大时会造成数据恢复的时间线拉长,而RDB快照则是记录redis某一时刻的数据,并将其写入磁盘,这样在宕机数据恢复时,只需要把RDB文件读入内存即可。

这里快照的生成又会产生很多问题,比什么时候去产生快照呢,产生快照的时候是否会阻塞主线程呢,同时在产生快照的时候,修改的数据又该怎么操作呢?

产生快照的频率我们很难把握,确实,快照频率越高,那么我们丢失数据的风险是最小的,但是产生快照是需要时间的。

在redis中提供两个命令来生成RDB文件

save:在主线程中执行,会造成主线程阻塞

bgsave:专门创建一个子线程来生成RDB快照,不会阻塞主线程,这也是redis默认生成快照的方式。

有人可能会说,那我用bgsave来生成快照不就好了,这样不会阻塞主线程而且数据丢失的风险也不高,这里确实bgsave子线程不会阻塞主线程,但是这个线程是主线程fork的,频繁的fork子线程也是会对主线程有影响的。

所以为了防止在生成RDB快照的时候,不能对此时修改的数据进行维护,redis有一个写时复制的操作,就是在生成快照时,如果对其中的键值修改了,会创建这个键值的副本,这个时候写操作会继续进行,同时会把这个复制的副本写到RDB快照。
在这里插入图片描述

在redis4.0版本中,采用的是RDB快照和AOF日志混合使用的方式,采用一定频率来生成RDB快照,同时用AOF日志来记录在生成快照期间redis修改的数据。

在这里插入图片描述

这样的话,既可以享受用RDB快照来快速恢复数据,同时又可以通过AOF日志方式来保存修改的数据,而且快照的方式就可以不用AOF日志的重写日志,两者互补,这种策略是非常推荐的。

2.redis的配置.

关于 dir目录是用来做什么的,这个指的是本地数据库的存放目录,就是因为线上的redis将这个目录修改的,导致数据全部都读取不到。redis其余相关数据,网上都可以查到,这里就不做相应介绍了。

3.redis安全设置

一般redis安装完成之后,会使用默认的端口号6379,并且是没有设置密码,这样redis就会接收任何的请求来源,会遭到恶意的攻击。所以我们要把redis设置密码,文章最开始提示没有权限,如果你把 /etc 的权限完全开放的话,而且redis没有设置密码,那么可能会被人在文件下加入挖矿病毒。切记,redis暴漏在外网下,一定要设置密码,防止恶意攻击。

设置密码的方式:

docke-compose:

  isafety-redis:
    image: redis:latest
    container_name: isafety-redis
    restart: always
    privileged: true
    command: redis-server --requirepass zxm10***
    ports:
      - "6379:6379"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - "${REDIS_DIR}/data:/data"                                  # 挂载数据目录
      - "${REDIS_DIR}/config/redis.conf:/etc/redis/redis.conf"     # 挂载配置文件目录

docker直接启动方式:

docker run --name redis -p 6379:6379 redis-test --requirepass [yourpassword]

挂载配置文件,直接下修改 conf文件 requirepass [yourpassword] 然后重启即可

这次的问题主要扩展了一下redis数据持久化的设计方式,redis的配置文件中也有相关的设置,比如是否开启修改数据后立刻写入日志,数据日志的save的方式等等,小伙伴们可以自行查看一下配置文件的相关注释来了解一下啦。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Redis数据持久化有两种方式:快照持久化RDB)和写日志持久化(AOF)。 RDB持久化是通过将Redis数据集在指定的时间间隔内保存到硬盘上的快照,以二进制形式存储。这种方式的缺点是耗时和耗性能,因为需要经常fork子进程来保存数据集到硬盘上。当数据集很大时,fork的过程会非常耗时,可能导致Redis在一些毫秒级内不能响应客户端请求。另外,如果Redis意外停止工作,可能会丢失一些数据。 AOF持久化是把每一个对Redis服务器的修改操作都记录到一个日志文件中。这种方式的优点是可以保证数据的耐久性,因为每个写操作都会被写入日志文件。当Redis重启时,会通过重新执行日志文件中的命令来恢复数据。但AOF持久化相对于RDB持久化来说,会占用更多的磁盘空间,并且写操作会造成额外的I/O开销。 为了更好地控制数据持久化的行为,你可以通过配置文件设置Redis在指定条件下自动进行数据集保存操作。例如,你可以设置当数据集在N秒内至少有M个改动时,自动进行数据集保存操作。 综上所述,RDB持久化适用于对数据集的完整性要求不高、对性能要求较高的场景,而AOF持久化则适用于对数据耐久性要求较高的场景。根据具体需求和性能要求,可以选择适合的持久化方式。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Redis持久化详解(简单易懂)](https://blog.csdn.net/GSl0408/article/details/126742048)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值