持久化的两种方式
由于redis是基于内存的存储方式,所以redis内数据的特点是掉电易失,所以redis也提供了持久化的方案。
常用持久化的两种方案:
- 快照/副本 - 复制出一份数据的镜像
- 日志 - 逐条记录操作
关于Linux进程通信的相关概念
管道:
1.衔接作用,前一个命令的输出 作为后一个命令的输入
2.管道会触发创建子进程
#当前解释程序的进程ID
echo $$ - 19251
#当前解释程序的进程ID $$ = $BASHPID
echo $BASHPID - 19251
#$$ 高于管道,先开辟进程再执行管道
echo $$ | more - 19251
#$BASHPID 优先级低于管道,先开启管道,管道会触发创建子进程,再开启了两个子进程
echo $BASHPID | more - 19524
Linux父子进程通信
1.父子进程概念的引出
num=0
echo $num - 0
((num++))
echo $num - 1
((num++)) | echo ok - ok
echo $num - 1
echo $$ - 13646
echo $$ | more - 13646
echo $BASHPID - 13646
#抛出了子进程
echo $BASHPID | more - 13672
echo $BASHPID | more - 13674
echo $BASHPID | more - 13676
2.常规思想中,进程数据是隔离的
echo $$ - 13646
echo $num - 1 当前bash的num == 1
#启动一个新的进程
/bin/bash
echo $$ - 13679
#查看进程
pstree -
systemd─┬─AliSecGuard───6*[{AliSecGuard}]
├─AliYunDun───22*[{AliYunDun}]
├─AliYunDunUpdate───3*[{AliYunDunUpdate}]
├─2*[agetty]
├─aliyun-service───2*[{aliyun-service}]
├─atd
├─auditd───{auditd}
├─crond
├─dbus-daemon
├─dhclient
├─ntpd
├─polkitd───5*[{polkitd}]
├─redis-server───3*[{redis-server}]
├─rsyslogd───2*[{rsyslogd}]
├─sshd───sshd───bash───bash───pstree
├─systemd-journal
├─systemd-logind
├─systemd-udevd
└─tuned───4*[{tuned}]
#sshd───sshd───bash───bash───pstree可以看出启动的进程是当前bash的子进程
echo $num - 没有值,之前bash中的num == 1
由此可得在常规思想中,进程数据是隔离的
3.进阶思想,父进程其实可以让子进程看到数据
echo $num - 1
export num
echo $num - 1
/bin/bash
echo $num -1
进阶思想,父进程可以让子进程看到数据
4.在linux中,export的环境连变量,子进程的修改不会破坏父进程(子进程修改数据,父进程的数据不会修改)
1.echo num=1
2.#编辑脚本
vim test.sh
#切换到子进程
#!/bin/bash
#打印子进程的num并且修改为999
echo $$
echo #num
num=999
echo num:$num
#子进程睡眠20秒,再打印num
sleep 20
- 休眠之后切换到父进程 观察num的数值
echo #num
#编辑完文件后,把该文件修改为可执行文件
3.chmod +x test.sh
4../test.sh &在后台运行脚本查看结果
5.echo $num - 1 子进程睡眠后观察父进程的num=1
6.999 - 子进程num依然等于999
在linux中,export的环境连变量,子进程的修改不会破坏父进程
4.在linux中,export的环境连变量,父进程的修改不会破坏子进程
echo $num - 1
./test.sh &
#子进程休眠,给num赋值888
num=888
#子进程依然是999
999
Redis如何创建副本
首先要思考的是:如果redis是父进程,有10G数据,那么
1.Redis创建子进程的速度如何
2.创建子进程后内存空间是10G还是20G?
在我们操作程序时,操作系统会帮我们维护内存,把应用程序的虚拟内存映射为物理内存
此时当我们使用系统调用System Call:fork(),会为我们创建子进程,在创建子进程的过程中,根据之前的知识,子进程可以看到父进程的数据,只需把指针指向具体物理地址,不需要复制数据,速度相对快,占用空间小
man 2 fork
当我们修改数据时,父进程指向新的物理地址,bash依旧指向原来的物理地址,此时bash依旧可以把执行持久化操作时间点的数据做对应操作。
Redis的持久化配置
1.RDB
save 900 1
save 300 10
save 60 10000
默认开启,如果什么都不写就是空
dbfilename dump.rdb - RDB文件名
dir var/lib/redis/6379 -RDB文件路径
RDB的优点:
- 类似java的序列化,恢复速度相对快
RDB的缺点:
- 不支持拉链,只有一个dump.rdb,需要每天或者定时把dump.rdb文件考出并添加时间
-
丢失数据相对多,时间点和时间点之间的窗口的数据容易丢失
2.AOF
把redis的写操作记录到文件中
appendonly yes
no-appendfsync-on-rewrite no #RDB时是否AOF
aof-use-rdb-preamble no #是否开启RDB、AOF混用
AOF的优点:
- 丢失数据少
AOF的缺点:
- 数据体量无限变大,恢复慢
Redis中,RDB和AOF可以同时开启,如果开启了AOF只会用AOF恢复数据。
为了减少日志体量
- 4.0之前:Redis会删除抵消的命令,合并重复的命令。最终得到一个纯指令文件。
- 4.0之后:将老的数据RDB到AOF文件中,将增量数据以指令的方式append到AOF文件中,得到一个混合体
AOF级别:
appendfsync no
appendfsync always
appendfsync everysec
详解appendfsync
刷写AOF的过程是Redis先把数据写入内核buffer(4K左右),再刷写给磁盘(类似flush方法),appendfsync配置是控制刷写的频率
- appendfsync no:当buffer满了刷写给磁盘,最多丢失一个buffer大小的数据
- appendfsync always:每一条数据刷写一次,最多丢失一条数据
- appendfsync everysec:每一秒数据刷写一次,最多丢失一秒内数据,最大不到一个buffer大小(推荐)
总结:
验证
- 关闭redis
- vi /etc/redis/6379.conf
- daemonize no 为了看前台的日志
- logfile /var/log/redis_6379.log注释掉 日志打印到屏幕
- appendonly yes
cd /var/lib/redis/6379
rm -rf appendonly.aof
rm -rf dump.rdb
#启动redis
redis-server /etc/redis/6379.conf
set k1 hello
- 打开AOF文件
*代表 下一条指令由几个元素组成,比如这里2 - select ,0
$代表这个元素又几个字符组成
*2
$6
SELECT
$1
0
*3
$3
set
$2
k1
$5
hello
- bgsave
Background saving started by pid 17043
17043:C 29 Jun 2020 12:29:29.454 * DB saved on disk
17043:C 29 Jun 2020 12:29:29.454 * RDB: 4 MB of memory used by copy-on-write
17036:M 29 Jun 2020 12:29:29.461 * Background saving terminated with success
- 检查持久化是否成功
redis-check-rdb dump.rdb
- 删除抵消指令
set k1 a
set k1 b
set k1 c
#观察AOF文件再执行以下操作
BGREWRITEAOF
- 修改配置 开启RDB、AOF混合
aof-use-rdb-preamble yes