Redis 的落地策略

Stella981
• 阅读 617

因为之前使用redis一般都只做热数据处理,没有考虑过落地方案,因此,通过很多次不同的交流,发现落地也挺重要的,特来学习一般。

落地策略

我们知道,redis是纯内存数据库,一旦发生宕机,数据就会丢失,因此,Redis 的落地策略其实就是持久化(Persistence),主要有以下2种策略:

  1. RDB: 定时快照方式(snapshot)
  2. AOF: 基于语句追加文件的方式

RDB

RDB 文件非常紧凑,它保存了 Redis 某个时间点上的数据集。RDB 恢复大数据集时速度要比 AOF 快。但是 RDB 不适合那些对时效性要求很高的业务,因为它只保存了快照,在进行恢复时会导致一些时间内的数据丢失。实际在进行备份时,Redis 主要依靠 rdbSave() 函数,然后有两个命令会调用这个函数 SAVE 和 BGSAVE,前者会同步调用,阻塞主进程导致会有短暂的 Redis-server 停止工作,后者会 fork 出子进程异步处理。

在调用 SAVE 或者 BGSAVE 时,只有发布和订阅功能的命令可以正常执行,因为这个模块和服务器的其他模块是隔离的。 下面的命令表示: “60 秒内有至少有 1000 个键被改动”时进行RDB文件备份。

redis-server> SAVE 60 1000

Redis 的落地策略

开头的REDIS表示这是一个 RDB 文件,然后紧跟着 redis 的版本号,SELECT-DB 和 KEY-VALUES-PAIRS 构成了对一个数据库中的所有数据记录,其中 KEY-VALUES-PAIRS 具体结构如下,后面两个就不用说了。

Redis 的落地策略

AOF

AOF 可以通过设置的 fsync 策略配置,如果未设置 fsync ,AOF 的默认策略为每秒钟 fsync 一次,在这种配置下, fsync 会在后台线程执行,所以主线程不会受到打扰。但是像 AOF 这种策略会导致追加的文件非常大,而且在恢复大数据时非常缓慢,因为要把所有会导致写数据库的命令都重新执行一遍。AOF文件中实际存储的是 Redis 协议下的命令记录,因此非常易读。

当然 Redis 考虑到了 AOF 文件过大的问题,因此引入了 BGREWRITEAOF 命令进行重建 AOF 文件,保证可以减少大量无用的重复写操作。重建命令并不会去分析已有的 AOF 文件,而是将当前数据库的快照保存。

在 AOF 文件重写时,Redis 的具体逻辑如下:

  1. Redis 首先 fork 出一个子进程,子进程将新 AOF 文件的内容写入到临时文件。
  2. 对于所有新执行的写入命令,父进程一边将它们累积到一个缓存中,一边将这些改动追加到现有 AOF 文件的末尾: 这样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。
  3. 当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将缓存中的所有数据追加到新 AOF 文件的末尾。
  4. 现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。

Redis 会维持一个默认的AOF重写策略,当当前的AOF文件比上次重写之后的文件大小增大了一倍时,就会自动在后台重写AOF。

从策略方式来看,AOF文件模式类似于mysql的binlog,是做一个归档日志,属于逻辑日志。

AOF与RDB的优缺点和适用场景

RDB持久化是在指定的时间间隔内将内存中的数据集快照写入磁盘中,fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。具体操作:遍历hash table,利用copy on write,把整个db dump保存下来。save, shutdown, slave 命令会触发这个操作。

特点:粒度比较大,如果save, shutdown, slave 之前crash了,则中间的操作没办法恢复。

AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录。Redis 还可以在后台对 AOF 文件进行重写(rewrite),使得 AOF 文件的体积不会超出保存数据集状态所需的实际大小。Redis 还可以同时使用 AOF 持久化和 RDB 持久化。 在这种情况下, 当 Redis 重启时, 它会优先使用 AOF 文件来还原数据集, 因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。你甚至可以关闭持久化功能,让数据只在服务器运行时存在。

特点:粒度较小,crash之后,只有crash之前没有来得及做日志的操作没办法恢复。

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

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Stella981 Stella981
2年前
Nginx + lua +[memcached,redis]
精品案例1、Nginxluamemcached,redis实现网站灰度发布2、分库分表/基于Leaf组件实现的全球唯一ID(非UUID)3、Redis独立数据监控,实现订单超时操作/MQ死信操作SelectPollEpollReactor模型4、分布式任务调试Quartz应用
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
IM 消息服务架构
IM消息架构主要有1、消息redis缓存队列及用户信息memcache2、消息的数据落地(入库mysql)3、消息的发送4、离线消息服务5、过期消息服务消息redis缓存队列服务端落地队列1.客户端通过HTTPS
Stella981 Stella981
2年前
Redis——持久化数据
Redis被称为是内存数据库,那是因为它会将其所有数据存储在内存里,因此Redis具有强劲的速度性能,但是,也正因为数据存储在内存中,当Redis重启后,所有存储在内存的数据就会丢失。为了使得数据持久化,Redis提供了两种方式:RDB方式和AOF方式。一、RDB方式RDB方式的持久化是通过快照(snapshotting)完成的,
Stella981 Stella981
2年前
Redis—持久化
一、持久化简介Redis的数据全部存储在内存中,如果突然宕机,数据就会全部丢失,因此必须有一套机制来保证Redis的数据不会因为故障而丢失,这种机制就是Redis的持久化机制,它会将内存中的数据库状态保存到磁盘中。持久化发生了什么|从内存到磁盘
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这