redis的使用场景、持久化

转自
https://blog.csdn.net/tr1912/article/details/70197085?foxhandler=RssReadRenderProcessHandler
https://www.cnblogs.com/chenliangcl/p/7240350.html

说道redis,我们可能都会知道了他是一个类似缓存的一个内存数据库,这篇我们来讲讲redis这种非关系型数据库用在什么地方,以及他的特色——持久化是怎么实现的。

1 redis的适用环境

首先作为一个nosql的key—value组成的数据库,它们能存储的数据结构必须是简单的,因为有关系的数据即使存储进去之后查询也是很困难的,并且对于海量的数据存储还是关系型数据库比较合适

举一个把一般数据库数据存储到key-value中的例子:
在这里插入图片描述遵从规则为
key:表名:主键值:列名
value:列值

如果加上表关系的话还要复杂好几倍的。

那么什么样的数据适合存储在非关系型数据库中的呢?

  1. 关系不是很密切的的数据,比如用户信息,班级信息,评论数量等等。
  2. 量比较大的数据,如访问记录等
  3. 访问比较频繁的数据,如用户信息,访问数量,最新微博等

2 持久化

那么这么多,这么重要的数据都存储在内存中,如果突然断电,岂不是很糟糕,于是就有了数据的持久化机制,这个其实就是把内存中的数据存储到硬盘中,方便数据的持续存在,也可以减少断电造成的损失。

那么我们怎么持久化数据呢?多长时间进行一次持久化呢?

redis 支持两种持久化方式,一种是 Snapshotting(快照,RDB)也是默认方式,另一种是 Append-only file(缩写 aof)的方式。下面分别介绍:

2.1 Snapshotting

快照是默认的持久化方式。这种方式是就是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。我们可以配置 redis在 n 秒内如果超过 m 个 key 被修改就自动做快照,下面是默认的快照保存配置:

save 900 1 #900 秒内如果超过 1 个 key 被修改,则发起快照保存
save 300 10 #300 秒内容如超过 10 个 key 被修改,则发起快照保存
save 60 10000

下面介绍详细的快照保存过程

  1. redis 调用 fork创建子进程,现在有了子进程和父进程。
  2. 父进程继续处理 client 请求,子进程负责将内存内容写入到临时文件。由于 os 的实时复制机制( copy on write)父子进程会共享相同的物理页面,当父进程处理写请求时,os 会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程地址空间内的数据是 fork时刻整个数据库的一个快照。所以他是一个全量的方式来进行持久化的。
  3. 当子进程将快照写入临时文件完毕后用临时文件替换原来的快照文件,然后子进程退出。client 也可以使用 save 或者 bgsave 命令通知 redis 做一次快照持久化。 save 操作是在主线程中保存快照的,由于 redis 是用一个主线程来处理所有 client 的请求,这种方式会阻塞所有client 请求。所以不推荐使用。另一点需要注意的是,每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步变更数据。

优点:

  1. 一旦采用该方式,那么你的整个Redis数据库只包含一个文件,这样非常方便进行备份。比如你可能打算每1天归档一些数据。
  2. 方便备份,我们可以很容易的将一个一个RDB文件移动到其他的存储介质上
  3. RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快
  4. RDB 可以最大化 Redis 的性能:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作父进程无须执行任何磁盘 I/O 操作

缺点:

  1. 服务器宕机时,会丢失从上一次快照后修改的数据
  2. 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果数据量大的话而且写操作比较多,必然会引起大量的磁盘 io 操作可能会严重影响性能

2.2 AOF方式

由于快照方式是在一定间隔时间做一次的,所以如果 redis 意外 down 掉的话,就会丢失最后一次快照后的所有修改。如果应用要求不能丢失任何修改的话,可以采用 aof 持久化方式。下面介绍 Append-only file:aof 比快照方式有更好的持久化性,是由于在使用 aof 持久化方式时,redis 会将每一个收到的写命令通过 write 函数追加到文件中(默认是 appendonly.aof)。当 redis 重启时会通过重新执行文件中保存的写命令在内存中重建整个数据库的内容。当然由于 os 会在内核中缓存 write 做的修改,所以可能不是立即写到磁盘上。这样 aof 方式的持久化也还是有可能会丢失部分修改。不过我们可以通过配置文件告诉 redis 我们想要通过 fsync 函数强制 os 写入到磁盘的时机。有三种方式如下(默认是:每秒 fsync 一次)

 # appendfsync always //收到写命令就立即写入磁盘,最慢,但是保证完全的持久化
 #appendfsync everysec //每秒钟写入磁盘一次,在性能和持久化方面做了很好的折中
 # appendfsync no //完全依赖 os,性能最好,持久化没保证

如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性

aof 的方式也同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用 incr test命令 100 次,文件中必须保存全部的 100 条命令,其实有 99 条都是多余的。因为要恢复数据库的状态其实文件中保存一条 set test 100 就够了。为了压缩 aof 的持久化文件。 redis 提供了 bgrewriteaof 命令。收到此命令 redis 将使用与快照类似的方式将内存中的数据以命令的方式保存到临时文件中,最后替换原来的文件。

AOF的缺点:

  1. 对于相同数量的数据集而言,AOF文件通常要大于RDB文件RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快
  2. 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。

二者选择的标准

二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。RDB这个就更有些 eventually consistent(最终一致)的意思了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值