数据库基础之Redis学习 part two

Posted by OuterCyrex on September 3, 2024

一.持久化

一.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

更改的内容是自定义的。

手动备份

通过SaveBGSAVE可以实现手动备份。

  • 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默认有三种写回策略:Alwayseverysecno

策略 介绍
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中,事务需要使用beginend包裹,且严格满足ACID特性。

Redis只能满足一下特征:

  • 单独的隔离操作,仅保证事务里的操作会被连续独占的执行。
  • 没有隔离级别的概念,事务提交前任何指令都不会被实际执行,而是存在命令队列中。
  • 不保证原子性,不能保证所有指令一定同时成功或同时失败。
  • 不会被其他命令插入

因此,Redis中的事务不能称为真正意义上的事务

二.操作

1.事务命令

命令 描述
DISCARD 取消事务,放弃执行事务块内的所有命令。
EXEC 执行所有事务块内的命令。
MULTI 标记—个事务块的开始。
UNWATCH 取消WATCH命令对所有key的监视。
WATCH 监视一个(或多个) key ,如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断。

通过MULTIEXEC的包裹,我们可以实现事务操作

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中的管道操作符

原生批量命令管道的区别是:

  • 原生批量命令原子性(例如:msetmget),pipeline非原子性
  • 原生批量命令一次只能执行一种命令,pipeline支持批量执行不同命令
  • 原生批量命令是服务端实现,而pipeline需要服务端与客户端共同完成

四.发布订阅

消息中间件内容,请关注kafkarabbitMQ等。