一.持久化
一.RBD持久化
1.rdb文件
在指定的时间间隔内,执行数据集的时间点快照 (snapshot
)。
快照会生成一个RDB
文件,RDB
保存到磁盘中的文件为dump.rdb
。
默认的snapshot
配置为:
-
save 900 1
:每隔900s(15min)
,如果有超过 1 个key
发生了变化,就写一份新的RDB
文件 -
save 300 10
:每隔300s(5min)
,如果有超过 10 个key
发生了变化,就写一份新的RDB
文件 -
save 60 10000
:每隔60s(1min)
,如果有超过 10000 个key
发生了变化,就写一份新的RDB
文件
2.操作
首先需要指定rdb
文件的存储路径,在redis@version.conf
中寻找dir
字段,(此处@version
需要根据自身redis
版本确定),并更改dir
的内容:
1
dir /myredis/dumpfiles
更改的内容是自定义的。
手动备份
通过Save
或BGSAVE
可以实现手动备份。
save
redis
无法同时处理save
与其他操作。因此在主程序中执行save
操作会阻塞当前redis
服务器。
也因此,线上禁止使用save
指令。
bgsave
bgsave
会产生一个子进程,并由子进程来复制持久化过程,不会影响主进程的操作。
lastsave
lastsave
可以快速获取上次备份的时间点。
修复命令
通过redis-check-rdb
加上rdb
文件的相对路径,可以实现使用rdb
文件修复当前redis
服务器。
二.AOF持久化
RDB
持久化的基本原理是存储内存中的数据,而AOF
持久化则是直接存储非读取操作语句。
默认情况下,redis
并没有开启AOF
持久化,需要在redis.conf
中启动appendonly yes
AOF
持久化保存的文件为appendonly.aof
,且保存路径与rdb
的保存路径一致。
1.写回策略
AOF
默认有三种写回策略:Always
、everysec
、no
。
策略 | 介绍 |
---|---|
always | 每次执行命令后立刻同步AOF 文件 |
everysec | 执行完命令后传入缓冲区,每秒向AOF 文件同步一次 |
no | 每次写入执行命令后都只读入缓冲区,由操作系统决定何时同步AOF 文件 |
默认的写回策略为everysec
。
2.数据恢复
正常的恢复操作,只需要重启redis
然后重新加载,便可以自动加载AOF
文件的内容。
如果aof
文件出现问题,可以通过fix
指令可以修复aof
文件
1
redis-check-aof --fix
上述指令加上aof
文件的路径即可,如:
1
redis-check-aof --fix appendonly.aof.1.incr.aof
3.重写
当AOF
文件的大小超过某个设定峰值后,Redis
就会自动启动文件内容压缩。
也可以手动使用bgrewriteaof
来重写。
4.混合持久化
Redis
会优先采用AOF
,其优先级高于RDB
持久化。
且RDB
的数据不是实时的。
混合持久化要求,RDB
镜像做全量持久化,而AOF
做增量持久化。即满足重写策略时,AOF
会将最新的数据存储为RDB
记录。
即混合持久化时,AOF文件 = 此前操作的RDB文件 + 新操作的AOF文件
。
二.事务
一.ACID
事务是数据库操作语句中满足ACID
特性的一组代码。
ACID
分别指代的是原子性、一致性、隔离性与持久性。
在mysql
中,事务需要使用begin
与end
包裹,且严格满足ACID
特性。
而Redis
只能满足一下特征:
- 单独的隔离操作,仅保证事务里的操作会被连续独占的执行。
- 没有隔离级别的概念,事务提交前任何指令都不会被实际执行,而是存在命令队列中。
- 不保证原子性,不能保证所有指令一定同时成功或同时失败。
- 不会被其他命令插入。
因此,Redis
中的事务不能称为真正意义上的事务。
二.操作
1.事务命令
命令 | 描述 |
---|---|
DISCARD | 取消事务,放弃执行事务块内的所有命令。 |
EXEC | 执行所有事务块内的命令。 |
MULTI | 标记—个事务块的开始。 |
UNWATCH | 取消WATCH 命令对所有key 的监视。 |
WATCH | 监视一个(或多个) key ,如果在事务执行之前这个(或这些)key 被其他命令所改动,那么事务将被打断。 |
通过MULTI
与EXEC
的包裹,我们可以实现事务操作
1
2
3
4
5
6
7
8
9
MULTI
SET K1 V1
SET K2 V2
SET K3 V3
MGET K1 K2 K3
EXEC
// value :
OK ; OK ; OK ; V1 ; V2 ; V3
通过将EXEC
改为DISCARD
,我们可以取消此前设定的事务块命令。
1
2
3
4
5
6
MULTI
SET K1 V1
SET K2 V2
SET K3 V3
MGET K1 K2 K3
DISCARD
如果事务块中一个语句的语法出错,则所有命令都不会执行。
1
2
3
4
5
6
7
8
9
10
MULTI
SET K1 V1
SET K2 V2
SET K3
EXEC
MGET K1 K2 K3
// value :
error ... ; QUEUED
但如果语法没错而是逻辑出错,则Redis
会执行没有逻辑错误的语句,而不执行有逻辑错误的语句。
这种行为违反了原子性特征,也印证了Redis
的事务不是真正意义上的事务。
三.管道
管道(pipeline
)可以一次性发送多条命令给服务端。
服务端依次处理完完毕后,通过一条响应一次性将结果返回,通过减少客户端与redis
的通信次数来实现降低往返延时时间。
pipeline
实现的原理是队列,先进先出特性就保证数据的顺序性。
其目的是减少网络交互,提高交互效率。
此处介绍一种实现管道的方法。
在linux
系统中使用如下命令行:
myredis> cat cmd.txt
set k1 v1
set k2 v2
set k3 v3
lpush list 1 2 3 4 5
myredis> cat cmd.txt | redis-cli -a "password" --pipe
// 返回值:
errors: 0, replies: 4
其中|
为linux
中的管道操作符。
原生批量命令与管道的区别是:
- 原生批量命令是原子性(例如:
mset
,mget
),pipeline
是非原子性 - 原生批量命令一次只能执行一种命令,
pipeline
支持批量执行不同命令 - 原生批量命令是服务端实现,而
pipeline
需要服务端与客户端共同完成
四.发布订阅
消息中间件内容,请关注kafka
、rabbitMQ
等。