了解Redis数据持久化(上)

7 篇文章 0 订阅
5 篇文章 0 订阅

        Redis常用作缓存,提高读取相应性能。Redis如果宕机可以从后端数据库里恢复数据,但是会出现的问题:

  1. 数据是从慢速数据库里获取数据,速度比不上从Redis缓存中获取。
  2. 频繁访问数据库会给数据库造成压力。

        处理宕机的方法就是,将数据持久化

1.Redis怎么进行数据持久化?

        Redis持久化有两种方法:

  • RDB 快照(snapshot) - 将存在于某一时刻的所有数据都写入到硬盘中。(内存快照,设定定时间内落盘)
  • 只追加文件(append-only file,AOF日志 )- 它会在执行写命令时,将被执行的写命令复制到硬盘中。写后日志的方式记录(先执行命令,然后将数据写入内存,然后记录日志)

2.宕机了,Redis 如何避免数据丢失?

        AOF通过追加的方式记录命令,避免数据丢失。但是当数据需要恢复的时候,需要逐一的执行命令,如果数据量过大的话,执行的时间就会过长,Redis恢复数据的过程缓慢,就会影响到正常的使用。AOF记录的是命令不是真实的数据。

        RDB记录的是某一个时刻的数据,在Redis恢复数据的时候只需要将数据写入内存,就能恢复数据了。

3.RDB 内存快照,让宕机快速恢复

3.1RDB的说明

        RDB其实就是Redis DataBase的缩写,所谓内存快照就是Redis内存中某一个时刻的数据状态。Redis将某一刻的数据拍下来,以文件的形式写入磁盘中。就像是拍照,记录下某一时刻的瞬间画面完全记录下来。Redis在进行写操作的时候,内存数据是一直在变化的。

3.2RDB给那些数据做快照?

        RDB给那些数据做快照?Redis的数据都在内存中,为了提供所有数据的可靠性保证,它执行的是全量快照,也就是说,把内存中的所有数据都记录到磁盘中,这就类似于给100个人拍合影,把每一个人都拍进照片里。这样做的好处是,一次性记录了所有数据,一个都不少。

        当你给一个人拍照时,只用协调一个人就够了,但是,拍100人的大合影,却需要协调100个人的位置、状态,等等,这当然会更费时费力。同样,给内存的全量数据做快照,把它们全部写入磁盘也会花费很多时间。而且,全量数据越多,RDB文件就越大,往磁盘上写数据的时间开销就越大。

        Redis 当作缓存使用,所以即使 Redis 没有保存全部数据,还可以通过数据库获取,所以 Redis 不会保存所有的数据, Redis 的数据持久化使用了「RDB 数据快照」的方式来实现宕机快速恢复。

        Redis通过定时RDB内存快照,不必每次都执行【写】指令写入磁盘,只需要在内存快照的时候写入磁盘,既保持了速度快,又对数据进行了持久化,宕机也能快速的恢复数据。

        直接将RDB数据读入内存,进行数据恢复。

图1 内存快照 

3.3生成 RDB 策略

        对于Redis而言,它的单线程模型就决定了,我们要尽量避免所有会阻塞主线程的操作。Redis生成RDB两方式:

  • save:主线程执行,会被阻塞。
  • bgsave:创建一个子进程,专门用于写入RDB文件,避免了主线程的阻塞,这也是Redis生成RDB的默认设置。调用glibc的函数fork产生一个子进程用于写入RDB文件,快照持久化完全交给子进程处理,父进程继续处理客户端请求,生产RDB默认配置文件。bgsave 子进程可以共享主线程的所有内存数据,读取主线程的数据并写入到 RDB 文件。

        共同:当进行save或者bgsave创建一个新的RDB文件时,程序会对数据库进行检查,已经过期的键不会被写入RDB中。

3.4在进行快照的时候数据可以被修改吗?

        Redis在进行RDB的时候,虽然主线程没有阻塞,为了保持数据的一致性,在进行RDB的时候只能进行读操作,不能进行写操作,不能修改正在执行快照的数据。

        举个例子。我们在时刻t给内存做快照,假设内存数据量是4GB,磁盘的写入带宽是0.2GB/s,简单来说,至少需要20s (4/0.2=20)才能做完。如果在时刻t+5s时,一个还没有被写入磁盘的内存数据A,被修改成了A’,那么就会破坏快照的完整性,因为A’不是时刻t时的状态。因此,和拍照类似,我们在做快照时也不希望数据“动”,也就是不能被修改。

        但是,如果快照执行期间数据不能被修改,是会有潜在问题的。对于刚刚的例子来说,在做快照的20s时间里,如果这4GB的数据都不能被修改,Redis就不能处理对这些数据的写操作,那无疑就会给业务服务造成巨大的影响。

        RDB 文件生成期间能处理写操作不是一回事

        你可能会想到,可以用bgsave避免阻塞啊。这里我就要说到一个常见的误区了,避免阻塞和正常处理写操作并不是一回事。此时,主线程的确没有阻塞,可以正常接收请求,但是,为了保证快照完整性,它只能处理读操作,因为不能修改正在执行快照的数据。

        解决写问题

        Redis使用操作系统的多进程写时复制技术 (COW/ copy on write )来实现快照持久化。

  • 子进程刚刚产生时,子进程跟父进程共享内存里的所有代码段和数据段。(这是Linux内存机制,为了节省内存资源,更快的共享起来,在进程分离一瞬间,内存增长基本没有变化。)
  • 在进行快照的时候,同时进行写操作
  • 简单来说,bgsave子进程是由主线程fork生成的,可以共享主线程的所有内存数据。bgsave子进程运行后,开始读取主线程的内存数据,并把它们写入RDB文件。

        当主线程执行写指令修改数据的时候,这个数据就会复制一份副本, bgsave 子进程读取这个副本数据写到 RDB 文件,所以主线程就可以直接修改原来的数据。这样保证了快照的完整性,也允许主线程同时进行写操作,避免对正常业务的影响。

        到这里,我们就解决了对“哪些数据做快照”以及“做快照时数据能否修改”这两大问题:Redis会使用bgsave对、当前内存中的所有数据做快照,这个操作是子进程在后台完成的,这就允许主线程同时可以修改数据。

  • 13
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值