Redis持久化锦囊在手,再也不会担心数据丢失了
大家好,我是小羽。
Redis 的读写都是在内存中进行的,所以它的性能高。而当我们的服务器断开或者重启的时候,数据就会消失,那么我们该怎么解决这个问题呢?
其实 Redis 已经为我们提供了一种持久化的机制,分别是 RDB
和 AOF
两种方式,接下来跟着我一起看看这两个锦囊都是怎么保证数据的持久化的。
持久化
由于 Redis 是基于内存的数据库,所以当服务器出现故障的时候,我们的数据就得不到安全保障。
这个时候就需要将内存中的数据存储到磁盘中,当我们服务器重启时,便可以通过磁盘来恢复数据,这个过程就叫做 Redis 持久化。
Redis持久化
RDB
简介
RDB全称Redis Database Backup file
(Redis数据备份文件),也可以称为Redis数据快照。
RDB 文件是一个经过压缩的二进制文件(默认:dump.rdb);
RDB 文件保存在硬盘里;
通过保存数据库中的键值对来记录数据库状态。
创建
当 Redis 持久化时,程序会将当前内存中的数据库状态保存到磁盘中。
创建
创建 RDB 文件主要有两个 Redis 命令:SAVE
和 BGSAVE
。
SAVE
同步操作,执行命令时,会阻塞 Redis 服务器进程,拒绝客户端发送的命令请求。
代码示例:
def SAVE():
# 创建 RDB 文件
rdbSave()
图示:
Save命令
BGSAVE
异步操作,执行命令时,子进程执行保存工作,服务器还可以继续让主线程处理客户端发送的命令请求。
代码示例:
def BGSAVE():
# 创建子进程
pid = fork()
if pid == 0:
# 子进程负责创建 RDB 文件
rdbSave()
# 完成之后向父进程发送信号
signal_parent()
elif pid > 0:
# 父进程继续处理命令请求,并通过轮训等待子进程的信号
handle_request_and_wait_signal()
else:
handle_fork_error()
图示:
bgSave命令
载入
载入工作在服务器启动时自动执行。
载入
服务器在载入 RDB 文件期间,会一直处于阻塞状态,直到载入工作完成为止。
主要设置
Redis 允许用户通过设置服务器配置的 save 选项,让服务器每隔一段时间自动执行一次 BGSAVE 命令。
设置保存条件
提供配置如下:
save 900 1
save 300 10
在这种情况下,只要满足以下条件中的一个,BGSAVE 命令就会被执行:
服务器在 900 秒之内,对数据库进行了至少 1 次修改了;
服务器在 300 秒之内,对数据库进行了至少 10 次修改。
saveparams
服务器程序会根据 save 选项所设置的保存条件,设置服务器状态 redisServer 结构的 saveparams
属性。
saveparams
属性是一个数组;数组中的每一个元素都是一个
saveparam
结构;每个
saveparam
结构都保存了一个save
选项设置的保存条件。
struct saveparam {
// 秒数
time_t seconds;
// 修改数
int changes;
}
dirty
dirty
计数器记录距离上一次成功执行 SAVE 命令或 BGSAVE 命令之后,服务器对数据库状态进行了多少次修改(包括写入、删除、更新等操作)。
lastsave
是一个 UNINX
时间戳,记录了服务器上一次成功执行 SAVE 命令或者 BGSAVE 命令的时间。
检查保存条件是否满足
服务器周期性操作函数 serverCron
(该函数对正在运行的服务器进行维护)默认每隔 100 毫秒就会执行一次,其中一项工作就是检查 save 选项所设置的保存条件是否已经满足,满足的话就执行 BGSAVE 命令。
代码示例:
def serverCron():
# ....
# 遍历所有保存条件
for saveparam in server.saveparams:
# 计算距离上次执行保存操作有多少秒
save_interval = unixtime_now() - server.lastsave
# 如果数据库状态的修改次数超过条件所设置的次数
# 如果距离上次保存的时间超过条件所设置的时间
if server.dirty >= saveparam.changes and save_interval > saveparam.seconds:
BGSAVE()
默认配置
RDB 文件默认的配置如下:
################################ SNAPSHOTTING ################################
#
# Save the DB on disk:
#在给定的秒数和给定的对数据库的写操作数下,自动持久化操作。
# save <seconds> <changes>
#
save 900 1
save 300 10
save 60 10000
#bgsave发生错误时是否停止写入,一般为yes
stop-writes-on-bgsave-error yes
#持久化时是否使用LZF压缩字符串对象?
rdbcompression yes
#是否对rdb文件进行校验和检验,通常为yes
rdbchecksum yes
# RDB持久化文件名
dbfilename dump.rdb
#持久化文件存储目录
dir ./
AOF
简介
AOF全称为 Append Only File
(追加日志文件)。日志是写后日志,Redis 是先执行命令,把数据写入内存,然后才记录日志。
写后日志
通过保存 Redis 服务器所执行的写命令来记录数据库状态;
写入 AOF 文件的所有命令都是以 Redis 的命令请求协议格式保存的。
实现
AOF 持久化流程实现主要是通过以下流程来实现的:
AOF流程
命令追加
若 AOF 持久化功能处于打开状态,服务器在执行完一个命令后,会以协议格式将被执行的写命令追加到服务器状态的 aof_buf
缓冲区的末尾。
文件同步
服务器每次结束一个事件循环之前,都会调用 flushAppendOnlyFile
函数,这个函数会考虑是否需要将 aof_buf
缓冲区中的内容写入和保存到 AOF 文件里。
flushAppendOnlyFile
函数执行以下流程:
WRITE:根据条件,将 aof_buf 中的缓存写入到 AOF 文件;
SAVE:根据条件,调用 fsync 或 fdatasync 函数,将 AOF 文件保存到磁盘中。
这个函数是由服务器配置的 appendfsync
的三个值:always、everysec、no
来影响的,也被称为三种策略。
Always
每条命令都会 fsync 到硬盘中,这样 redis 的写入数据就不会丢失。
Always
everysec
每秒都会刷新缓冲区到硬盘中(默认值)。
everysec
no
根据当前操作系统的规则决定什么时候刷新到硬盘中,不需要我们来考虑。
no
数据加载
创建一个不带网络连接的伪客户端;
从 AOF 文件中分析并读取出一条写命令;
使用伪客户端执行被读出的写命令;
一直执行步骤 2 和 3,直到 AOF 文件中的所有写命令都被处理完毕为止。
文件重写
为何需要文件重写:
为了解决 AOF 文件体积膨胀的问题;
通过重写创建一个新的 AOF 文件来替代现有的 AOF 文件,新的 AOF 文件不会包含任何浪费空间的冗余命令。
实现
文件重写的实现原理:
不需要对现有的 AOF 文件进行任何操作;
从数据库中直接读取键现在的值;
用一条命令记录键值对,从而代替之前记录这个键值对的多条命令。
后台重写
为不阻塞父进程,Redis 将 AOF 重写程序放到子进程里执行。
在子进程执行 AOF 重写期间,服务器进程需要执行三个流程:
执行客户端发来的命令;
将执行后的写命令追加到 AOF 缓冲区;
将执行后的写命令追加到 AOF 重写缓冲区。
服务器流程
默认配置
AOF 文件默认的配置如下:
############################## APPEND ONLY MODE ###############################
#开启AOF持久化方式
appendonly no
#AOF持久化文件名
appendfilename "appendonly.aof"
#每秒把缓冲区的数据fsync到磁盘
appendfsync everysec
# appendfsync no
#是否在执行重写时不同步数据到AOF文件
no-appendfsync-on-rewrite no
# 触发AOF文件执行重写的增长率
auto-aof-rewrite-percentage 100
#触发AOF文件执行重写的最小size
auto-aof-rewrite-min-size 64mb
#redis在恢复时,会忽略最后一条可能存在问题的指令
aof-load-truncated yes
#是否打开混合开关
aof-use-rdb-preamble yes
总结
通过以上的简介,想必大家都对 Redis 持久化有了大致的了解,那么这两种方式,我们该如何选择呢?
对于大中型的应用,我们既想保证数据完整性又想保证高效率,就应该结合使用 RDB 和 AOF 两种方式;
如果只是需要保证数据的完整性,保护数据不会丢失,那么优先使用 AOF 方式;
如果是处理大规模的数据恢复,追求更高更快的效率的话,优先使用 RDB 方式。
也可以参照下图进行选择:
主要对比
Redis持久化锦囊在手,再也不会担心数据丢失了的更多相关文章
- 一文吃透redis持久化,妈妈再也不担心我面试过不了!
持久化介绍 redis 提供了两种方式方式进行数据的持久化(将数据存储到硬盘中):第一种称为快照(snapshotting)RDB,它将某一时刻的所有数据都写入硬盘,所以快照是一次全量备份,并且存储的 ...
- redis持久化机制
redis持久化 redis的数据存在内存中,所以存取性能好.但是存在内存中的数据存在一个问题,一旦机器重启,内存数据消失.为了解决这个问题,redis支持持久化.持久化就是为了解决内存数据丢失时恢复 ...
- Redis持久化的方式
Redis小知识: redis是键值对的数据库,有5中主要数据类型: 字符串类型(string),散列类型(hash),列表类型(list),集合类型(set),有序集合类型(zset) Redis持 ...
- 转载redis持久化的几种方式
redis持久化的几种方式 1.前言 Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服 ...
- 二、redis持久化
一.redis持久化 1 RDB持久化(定redis的数据定时dump到磁盘上的RDB持久化)RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据 ...
- Redis持久化策略(RDB &AOF)
redis持久化的几种方式 1.前言 Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服 ...
- Redis持久化的方式有哪些?优缺点分别是什么?
Redis持久化方式 持久化的目的主要是做灾难恢复,数据恢复.由于Redis的数据全都放在内存里面,如果Redis挂了,没有配置持久化的话,重启的时候数据会全部丢失. 突 ...
- [动图演示]Redis 持久化 RDB/AOF 详解与实践
Redis 是一个开源( BSD 许可)的,内存中的数据结构存储系统,它可以用作数据库.缓存和消息中间件.它支持的数据类型很丰富,如字符串.链表.集 合.以及散列等,并且还支持多种排序功能. 什么叫持 ...
- Redis持久化(三)
Redis持久化 Redis提供了哪些持久化机制 1. RDB持久化: 该机制是指在指定的时间间隔内将内存中的数据集快照写入磁盘. 2. AOF持久化: 该机制 ...
随机推荐
- Day11_52_将Set集合转换为List集合
Set集合转换为List集合 ``` import java.util.*; public class SetReverseLsit { public static void main(String[ ...
- 794. Valid Tic-Tac-Toe State
A Tic-Tac-Toe board is given as a string array board. Return True if and only if it is possible to r ...
- css单位介绍em ex ch rem vw vh vm cm mm in pt pc px
长度单位主要有以下几种em ex ch rem vw vh vm cm mm in pt pc px %,大概可以分为几种"绝对单位"和"相对单位"和" ...
- 【网络协议】 RPC vs Http
- 【日志】MySQL中有多少种日志
redo 重做日志 作用:确保事务的持久性,防止在发生故障,脏页未写入磁盘.重启数据库会进行redo log执行重做,到达事务一致性 undo 回滚日志 作用:保证数据的原子性,记录事务发生之前的数据 ...
- 【日志追踪】(微服务应用和单体应用)-logback中的MDC机制
一.MDC介绍 MDC(Mapped Diagnostic Contexts)映射诊断上下文,该特征是logback提供的一种方便在多线程条件下的记录日志的功能, 某些应用程序采用多线程的方式来处理多 ...
- hdu4284 dfs+floyd
题意: 给你n个城市,m条边,要有h个必须旅游和打工的城市,问你能不能从1把所有必须的h个城市全部旅游并且打工完... 思路: 先一遍floyd跑出全局最短路,然后暴力枚举出打 ...
- 数据链路层协议(Ethernet、IEEE802.3、PPP、HDLC)
目录 数据链路层协议 Ethernet以太网协议 以太网数据帧的封装 IEEE802.3协议 PPP协议 HDLC协议 数据链路层协议 首先Ethernet.IEEE802.3.PPP和HDLC都是数 ...
- 【vue-02】基础语法
插值操作 插值运算符 语法:{{数据}} 插值运算符可以对数据进行显示{{msg}},也可以在插值运算符中进行表达式计算{{cnt*2}}. v-html 希望以html格式进行输出 htmlData ...
- 游戏中的2D OBB碰撞模型的碰撞算法介绍和实践
前言 上一篇博文说道,射线与场景中模型上的所有三角形求交时,会大幅度影响效率且花费比较多的时间,因此会采取使用包围盒的形式,进行一个加速求交.在此文中介绍OBB碰撞模型的碰撞算法 OBB的碰撞模型 有 ...