redis启动加载过程、数据持久化

https://www.cnblogs.com/cuijl/p/7992433.html

 

付出才有回报,敢于尝试才能成功。

 

随笔- 89  文章- 0  评论- 0 

redis启动加载过程、数据持久化

背景

  公司一年的部分业务数据放在redis服务器上,但数据量比较大,单纯的string类型数据一年就将近32G,而且是经过压缩后的。

  所以我在想能否通过获取string数据的时间改为保存list数据类型,或者将数据持久化到硬盘上,或者放在不同库上,解决未来数据过大导致down机的问题。

相关知识点

  • 数据持久化
  • 数据加载

 

数据持久化

  • filesnapshotting(快照) 
  • Append-only(aof)

filesnapshotting

  默认redis是会以快照的形式将数据持久化到磁盘的(一个二进 制文件,xx.rdb)

  在配置文件中的格式是:save N M表示在N秒之内,redis至少发生M次修改则redis抓快照到磁盘。

  当然我们也可以手动执行save或者bgsave(异步)做快照。

  工作原理简单介绍:当redis需要做持久化时,redis会fork一个子进程;子进程将数据写到磁盘上一个临时RDB文件中;当子进程完成写临时文件后,将原来的RDB替换掉,这样的好处就是可以copy-on-write

缺点:filesnapshotting方法在redis异常死掉时, 最近的数据会丢失(丢失数据的多少视你save策略的配置),所以这是它最大的缺点,当业务量很大时,丢失的数据是很多的

Appened-only

  可以做到全部数据不丢失,但redis的性能就要差些。AOF就可以做到全程持久化,只需要在配置文件中开启(默认是no),appendonly yes开启AOF之后,可以选择三种不同的策略,都会把它添加到aof文件中,当redis重启时,将会读取AOF文件进行“重放”以恢复到 redis关闭前的最后时刻。

AOF的三种策略

appendfsync :appendfsync always每提交一个修改命令都调用fsync刷新到AOF文件,非常非常慢,但也非常安全;

appendfsync everysec每秒钟都调用fsync刷新到AOF文件,很快,但可能会丢失一秒以内的数据;

appendfsync no依靠OS进行刷新,redis不主动刷新AOF,这样最快,但安全性就差。默认并推荐每秒刷新,这样在速度和安全上都做到了兼顾。

LOG Rewriting随着修改数据的执行AOF文件会越来越大,其中很多内容记录某一个key的变化情况。

因此redis有了一种比较有意思的特性:在后台重建AOF文件,而不会影响client端操作。在任何时候执行BGREWRITEAOF命令,都会把当前内存中最短序列的命令写到磁盘,这些命令可以完全构建当前的数据情况,而不会存在多余的变化情况(比如状态变化,计数器变化等),缩小的AOF文件的大小。

所以当使用AOF时,redis推荐同时使用BGREWRITEAOF

LOG Rewrite的工作原理:同样用到了copy-on-write:首先redis会fork一个子进程;子进程将最新的AOF写入一个临时文件;父进程 增量的把内存中的最新执行的修改写入(这时仍写入旧的AOF,rewrite如果失败也是安全的);当子进程完成rewrite临时文件后,父进程会收到 一个信号,并把之前内存中增量的修改写入临时文件末尾;这时redis将旧AOF文件重命名,临时文件重命名,开始向新的AOF中写入。

Redis启动加载过程

1. 初始化全局服务器配置

2. 加载配置文件(如果指定了配置文件,否则使用默认配置)

3. 初始化服务器

4. 加载数据库

5. 网络监听

下面对上面这些步骤进行介绍

初始化全局服务器配置

初始化全局服务器配置通过initServerConfig()函数完成,主要是初始化server变量

初始化的内容包括下面几个方面:

1. 网络监听相关,如绑定地址,TCP端口等 
2. 虚拟内存相关,如swap文件、page大小等 
3. 保存机制,多长时间内有多少次更新才进行保存 
4. 复制相关,如是否是slave,master地址、端口 
5. Hash相关设置 
6. 初始化命令表

如其中的保存机制中,服务器初始化策略为:

复制代码

// 1小时内1次更新
appendServerSaveParams(60*60,1);

// 5分钟内100次更新
appendServerSaveParams(300,100);

// 1分钟内10000次更新
appendServerSaveParams(60,10000);

复制代码

如果在启动服务器时,指定了配置文件,则会在下面的“加载配置文件”步骤中,根据配置文件内容,更改其中的某些服务器配置。

加载配置文件

如果指定了配置文件,Redis使用loadServerConfig()函数加载配置文件,使用标准I/O库打开配置文件,循环读取每一行然后覆盖上一步进行的默认配置。

需要注意的是,下载Redis后代码包中有一个默认配置文件,如果启动Redis服务器时,不指定配置文件,Redis不会使用这个默认文件的配置,而是使用上一步“初始化全局服务器配置”中的配置。在默认配置文件中提供的配置项与上一步默认初始化的配置有些事不一样的,所以如果没有指定配置文件,千万不能认为Redis的行为会按照默认配置文件进行,最典型的一个例子,在默认配置文件中的数据保存策略是:

复制代码

# 15分钟内1次更新
save 900 1

# 5分钟内100次更新
save 300 10

# 1分钟内10000次更新
save 60 10000

复制代码

而默认初始化的全局配置中数据保存策略:appendServerSaveParams的配置项

初始化服务器

初始化服务器的工作在initServer()函数中,主要是完成前面未完成的工作,继续对server变量初始化,如设置信号处理、创建clients、slaves列表,创建Pub/Sub通道列表,同时还会创建共享对象:

shared.crlf = createObject(REDIS_STRING,sdsnew("\r\n"));
shared.ok = createObject(REDIS_STRING,sdsnew("+OK\r\n"));
shared.err = createObject(REDIS_STRING,sdsnew("-ERR\r\n"));
shared.emptybulk = createObject(REDIS_STRING,sdsnew("$0\r\n\r\n"));

最后,如果启用了虚拟内存机制,还需要初始化虚拟内存相关,如Thread I/O等。

加载数据库

在完成了上面的所有的初始化工作之后,Redis开始加载数据到内存中,如果启用了appendonly了,则Redis从appendfile加载数据,否则就从dbfile加载数据

1. 从appendfile中加载数据:loadAppendOnlyFile()函数

在此之前,我们先来看一下appendfile里面保存了什么,如我执行了下面两条命令(记得在配置文件中开启appendonly):

redis> SET mykey001 myvalue001
OK
redis> GET mykey001
"myvalue001"

使用cat命令查看appendonly.aof的内容:

复制代码

$ cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$8
mykey001
$10
myvalue001

复制代码

在appendonly.aof文件中保存的正是从客户端发过来的请求命令,还可以看到对于GET命令,并没有保存。

既然appendonly.aof中保存了所有写入数据的请求命令,那么在加载数据的时候只要重新执行一遍这些命令即可。

事实上Redis也正是这么做的,在开始加载之前暂时关闭appendonly,然后Redis创建一个假的Redis客户端。

然后读取appendonly.aof文件中的命令,在假的Redis客户端上下文中执行,同时服务器也不对该客户端做任何应答。

如果加载过程中物理内存不够用,并且Redis开启了VM,则还需要处理swap操作,最后加载完成后重新设置appendonly标志。

2. 从dbfile中加载数据:rdbLoad()函数

如果Redis没有开启appendonly,就需要从数据库文件中加载数据到内存,基本步骤如下:

a. 处理SELECT命令,即选择数据库 
b. 读取key 
c. 读取value 
d. 检测key是否过期 
e. 添加新的对象到哈希表 
f. 设置过期时间(如果需要) 
g. 如果开启了VM,处理swap操作

网络监听

在完成了初始化配置和数据加载后,Redis启动监听。Redis的网络库没有使用libevent或者libev,而是作者自己实现的一个非常轻量级的库(主要实现在ae.c文件中)

 

然而回到我的问题上,如果数据库中数据已经放入了32G的数据,在启动redis时加载数据库这部分必定会相当相当慢,而且涉及到宕机的问题(物理内存到达峰值)

这时可能单台redis很难解决这个问题,而应该考虑集群。

作者:大胖儿在努力 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

分类: NoSQL

好文要顶 关注我 收藏该文  

大胖儿在努力
关注 - 18
粉丝 - 8

+加关注

0

0

« 上一篇:MongoDB学习笔记
» 下一篇:高位字节、低位字节

posted @ 2017-12-06 14:14 大胖儿在努力 阅读(1588) 评论(0) 编辑 收藏

刷新评论刷新页面返回顶部

注册用户登录后才能发表评论,请 登录 或 注册,访问网站首页。

【推荐】超50万VC++源码: 大型组态工控、电力仿真CAD与GIS源码库!

 

相关博文:
· Redis数据存储解决方案
· C# Redis
· redis 数据类型详解 以及 redis适用场景场合
· REDIS 数据类型详解 以及 REDIS适用场景场合
· Redis应用场景

 

最新新闻
· 清华毕业计算机教授遭持枪劫车!靠“贪心算法”追回秒杀美国警察
· 字节跳动涉诉讼365起 或难支撑750亿美元超高估值
· 2018<1790,这才是中华民族最大危机?
· 美国网瘾戒除中心:没有电击、隔绝WiFi,治一次18万元
· 苹果iTune和三星电视达成流媒体合作
» 更多新闻...

昵称:大胖儿在努力
园龄:6年11个月
粉丝:8
关注:18

+加关注

<2019年1月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

随笔分类

随笔档案

阅读排行榜

推荐排行榜

Copyright ©2019 大胖儿在努力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值