Redis之事务、发布订阅与持久化

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 Redis之事务、发布订阅与持久化,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、Redis事物

Redis事务可以一次执行多个命令

Redis事物的重要保证:

1.事务是一个单独的隔离操作:

事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

2.事务是一个原子操作:

事务中的命令要么全部被执行,要么全部都不执行。

Redis事物的执行阶段

一个事务从开始到执行会经历以下三个阶段:

开始事务
命令入队
执行事务

Redis事务实例

Redis事物是以MULTI命令开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC命令触发事务, 一并执行事务中的所有命令。

事务命令

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

事务命令使用示例

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set name1 redis1
QUEUED
127.0.0.1:6379> set name2 redis2
QUEUED
127.0.0.1:6379> set name3 redis3
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
3) OK
127.0.0.1:6379> keys *
1) "name1"
2) "name2"
3) "name3"
127.0.0.1:6379>

二、Redis发布订阅

Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis客户端可以订阅任意数量的频道。

发布订阅命令

命令 描述说明
PSUBSCRIBE pattern [pattern …] 订阅一个或多个符合给定模式的频道。
PUBSUB subcommand [argument [argument …]] 查看订阅与发布系统状态。
PUBLISH channel message 将信息发送到指定的频道。
PUNSUBSCRIBE [pattern [pattern …]] 退订所有给定模式的频道。
SUBSCRIBE channel [channel …] 订阅给定的一个或多个频道的信息。
UNSUBSCRIBE [channel [channel …]] 指退订给定的频道。

发布订阅使用示例

订阅

SUBSCRIBE  订阅频道名称
127.0.0.1:6379> SUBSCRIBE channel-1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel-1"
3) (integer) 1

发布

PUBLISH 订阅频道名称 消息
D:\Program Files (x86)\Redis>redis-cli.exe
127.0.0.1:6379> PUBLISH channel-1 "hello"
(integer) 1
127.0.0.1:6379>

接收到消息

127.0.0.1:6379> SUBSCRIBE channel-1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel-1"
3) (integer) 1
1) "message"
2) "channel-1"
3) "hello"

三、Redis的持久化方式

A、RDB持久化

在指定的时间间隔能对数据进行快照,类似MySQL的dump备份文件。

Redis快照

快照就是把整个内存数据映射到硬盘中,保存一份到硬盘,因此恢复数据起来比较快,把数据映射回去即可,不像AOF需要一条一条的执行操作命令。

快照是默认的持久化方式,该方式就是将内存中的数据以快照的方式写入到二进制文件中,默认文件名dump.rdb。可通过配置文件设置自动做快照持久化的方式。

RDB是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。

产生快照的情况:

手动bgsave执行,该命令是非阻塞的

手动save执行,该命令是阻塞的

根据配置文件自动执行

客户端发送shutdown,系统会自动执行save命令阻塞客户端,然后关闭服务器

若是主从架构模式,从服务器向主服务器发送sync命令来执行复制操作时,主服务器会执行bgsave操作。

开启RDB

配置Redis在N秒内如果超过M个Key被修改则自动做快照,如果注释配置,则代表RDB禁用。

Redis默认的快照保存配置:

# 900秒内如果超过1个key改动,则发起快照保存
save 900 1
# 300秒内如果超过10个key改动,则发起快照保存
save 300 10
# 60秒内如果超过1W个key改动,则发起快照保存
save 60 10000

redis.conf

# 放行访问IP限制
bind 0.0.0.0
# 后台启动
daemonize yes
# 日志存储目录及日志文件名
logfile "/usr/local/program/redis/log/redis.log"
# 持久化数据存储在本地的文件名
dbfilename dump.rdb
# 持久化数据存储在本地的路径 rdb数据文件和aof数据文件存储目录
dir /usr/local/program/redis/data
# 设置密码
requirepass 123456

# 5秒内如果超过2个key改动,则发起快照保存
save 5 2

# 当snapshot时出现错误无法继续时,是否阻塞客户端“变更操作”,“错误”可能因为磁盘已满/磁盘故障/OS级别异常等  
stop-writes-on-bgsave-error yes  

# 是否启用rdb文件压缩,默认为yes,压缩往往意味着“额外的cpu消耗”,同时也意味这较小的文件尺寸以及较短的网络传输时间  
rdbcompression yes  

使用配置文件启动Redis

bin/redis-server conf/redis.conf 

连接客户端

root@DESKTOP-3M0E60F:/usr/local/program/redis# bin/redis-cli  -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> 

执行测试

在5秒内触发2次key的改动,发现快照执行成功,生成dump.rdb文件

root@DESKTOP-3M0E60F:/usr/local/program/redis# ll data
total 0
drwxr-xr-x 1 root root 4096 Jul 26 22:33 ./
drwxr-xr-x 1 root root 4096 Jul 26 21:48 ../
-rw-r--r-- 1 root root  102 Jul 26 22:33 dump.rdb
root@DESKTOP-3M0E60F:/usr/local/program/redis# 

RDB的优缺点

优点:

紧凑压缩的二进制文件,恢复速度快

fork子进程性能最大化,使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了redis的高性能

启动效率高,紧凑的压缩二进制文件

缺点:

生产快照的时机问题,RDB是间隔一段时间进行持久化,如果持久化之间 redis发生故障,会发生数据丢失。更适合数据要求不严谨的时候

fork子进程的开销问题,数据集很大的情况,频繁fork子进程进行快照

B、AOF持久化

记录每次对服务器写的操作,当服务器重启的时候重新执行这些命令来恢复原始的数据,类似MySQL的binlog日志

将“操作 + 数据”以格式化指令的方式追加到操作日志文件的尾部,在append操作返回后(已经写入到文件或者即将写入),才进行实际的数据变更,“日志文件”保存了历史所有的操作过程;当 server 需要数据恢复时,可以直接 replay此日志文件,即可还原所有的操作过程。AOF相对可靠,它和 mysql中bin.log、apache.log、zookeeper 中 txn-log 简直异曲同工。AOF文件内容是字符串,非常容易阅读和解析。

AOF只追加文件,也就是每次处理完请求命令后都会将此命令追加到aof文件的末尾,而RDB是压缩程二进制等时机开子进程去做这件事。

优点:

可以保持更高的数据完整性,如果设置追加file的时间是1s,如果redis发生故障,最多会丢失1s的数据;且如果日志写入不完整支持 redis-check-aof来进行日志修复;AOF文件没被rewrite 之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的flushall)。

缺点:

AOF文件比RDB 文件大,且恢复速度慢。

可以简单的认为AOF就是日志文件,只会记录“变更操作”(如:set/del 等),如果server中持续的大量变更操作,将会导致 AOF文件非常的庞大,意味着server失效后,数据恢复的过程将会很长;事实上,一条数据经过多次变更,将会产生多条 AOF记录,其实只要保存当前的状态,历史的操作记录是可以抛弃的;因为AOF持久化模式还伴生了“AOF rewrite”。

AOF的特性决定了它相对比较安全,如果期望数据更少的丢失,那么可以采用AOF模式。如果AOF文件正在被写入时突然 server失效,有可能导致文件的最后一次记录是不完整,可以通过手工或者程序的方式去检测并修正不完整的记录,以便通过aof文件恢复能够正常;同时需要提醒,如果redis持久化手段中有aof,那么在server故障失效后再次启动前,需要检测 aof文件的完整性。

AOF 默认关闭,开启方法,修改配置文件 reds.conf:appendonly yes

开启AOF

Redis默认使用RDB持久化方式,AOF默认是关闭的

# 放行访问IP限制
bind 0.0.0.0
# 后台启动
daemonize yes
# 日志存储目录及日志文件名
logfile "/usr/local/program/redis/log/redis.log"
# 持久化数据存储在本地的文件名
dbfilename dump.rdb
# 持久化数据存储在本地的路径 rdb数据文件和aof数据文件存储目录
dir /usr/local/program/redis/data
# 设置密码
requirepass 123456

# aof功能开关,默认为no,关闭状态  
appendonly yes  

# 指定aof文件名称  
appendfilename appendonly.aof  

# 指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec  
appendfsync everysec  

# 在aof-rewrite期间,appendfsync是否暂缓文件同步,no:不暂缓,yes:暂缓,默认为no,
# 开启可以减轻文件重写时CPU和磁盘的负载,但可能会丢失AOF重写期间的数据,需在负载和安全中间平衡取舍
no-appendfsync-on-rewrite no  

# aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建议“512mb”  
# 当aof文件大于指定字节后才触发重写
auto-aof-rewrite-min-size 64mb  

# 相对于上一次重写,本次rewrite触发时aof文件应该增长的百分比。  
# 每一次rewrite之后,redis都会记录下此时“新aof”文件的大小(例如A),那么当aof文件增长到A*(1 + p)之后触发下一次rewrite,每一次aof记录的添加,都会检测当前aof文件的尺寸。  
# 当写入日志文件大小超过上一次写入后的文件大小的百分之100时触发Rewrite
auto-aof-rewrite-percentage 100  

# 如果AOF文件结尾损坏,Redis启动时是否仍然载入aof文件
aof-load-truncated yes

同步策略

Redis中提供了3种AOF同步策略

appendfsync everysec

每秒同步,默认方式,每秒同步一次,性能和安全都比较中庸的方式,也是redis 推荐的方式。如果遇到物理服务器故障,有可能导致最近一秒内aof记录丢失(可能为部分丢失)。everysec是最佳的选择

appendfsync always

每修改则同步,会极大削弱Redis的性能,每一条aof记录都立即同步到文件,这是最安全的方式,也带来更多的磁盘操作和阻塞延迟,IO开支较大。

appendfsync no

不主动同步,由操作系统自动调度,redis并不直接调用文件同步,而是交给操作系统来处理,操作系统可以根据buffer填充情况 / 通道空闲时间等择机触发同步;这是一种普通的文件操作方式。性能较好,在物理服务器故障时,数据丢失量会因OS配置有关。

写入与恢复

AOF文件是一个只进行append操作的日志文件,因此写入过程中如果出现宕机情况,也不会破坏日志中已存在内容。如果某一次操作只写入了一半数据就宕机了,可以再Redis下一次启动前,通过Redis-check-aof工具帮助修复问题。

AOF文是有序保存对数据库执行的所有写入操作,因此AOF文件内容易于被人读懂。

重写

Redis可以在AOF文件体积变得过大时,自动的在后台对AOF文件进行重写。也就是Redis以append方式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新文件用于记录此期间那些修改命令被执行。

因为Redis在创建新AOF文件过程中,会继续将命令追加到现有的AOF文件里,即使重写过程中发生宕机情况,现有AOF文件也不会丢失。

而一旦新AOF文件创建完毕,Redis就会从旧的AOF文件切换到新的AOF文件,并开始对新AOF文件进行追加操作。

AOF文件会不断增大,它的大小直接影响“故障恢复”的时间, 而且AOF文件中历史操作是可以丢弃的。
AOF重写操作就是“压缩”AOF 文件的过程,当然redis并没有采用“基于原aof 文件”来重写的方式,而是采取了类似snapshot的方式:基于 copy-on-write,全量遍历内存中数据,然后逐个序列到aof 文件中。因此 AOF重写能够正确反应当前内存数据的状态,这正是所需要的;

重写过程中,对于新的变更操作将仍然被写入到原 AOF 文件中,同时这些新的变更操作也会被 redis 收集起来(buffer,copy-on-write 方式下,最极端的可能是所有的 key 都在此期间被修改,将会耗费 2 倍内存),当内存数据被全部写入到新的 aof 文件之后,收集的新的变更操作也将会一并追加到新的aof文件中,此后将会重命名新的aof文件为 appendonly.aof, 此后所有的操作都将被写入新的 aof 文件。

如果在 rewrite 过程中,出现故障,将不会影响原AOF文件的正常工作,只有当 rewrite完成之后才会切换文件,因为rewrite过程是比较可靠的。

触发rewrite的时机可以通过配置文件来声明,同时 redis中可以通过 bgrewriteaof 指令人工干预。因为rewrite操作aof记录同步snapshot都消耗磁盘 IO,redis 采取了“schedule”策略:无论是“人工干预”还是系统触发,snapshot 和rewrite需要逐个被执行。AOF rewrite 过程并不阻塞客户端请求。系统会开启一个子进程来完成。

AOF优缺点

优点:

数据不易丢失,每秒记录命令与数据

自动重写机制,保证AOF文件不会无限的膨胀,在恢复数据时不至于太慢

易懂易恢复,日志记录是有序写入,便于读懂

缺点:

AOF文件恢复数据慢,相对于RDB而言,RDB是二进制存储

AOF持久化效率低,每秒都会记录操作命令

C、RDB与AOF混合使用

RDB与AOF混合使用是Redis4.0开始的新特性,默认开启状态。

解决问题:Redis在重启时通常是加载AOF文件,但是加载速度慢,因为RDB数据不完整,所以加载AOF。
 
开启后,在混合使用中AOF直接读取RDB数据重建原始数据集,集合二者优势为一体。

数据恢复

当开启混合持久化时,启动Redis依然优先加载aof文件,aof文件加载可能有两种情况:

aof文件开头是rdb格式,先加载rdb内容在加载剩余的aof文件

aof文件开头不是rdb格式,直接以aof格式加载整个文件

优缺点

优:

既能快速备份又能避免大量数据丢失

缺:

rdb是压缩格式,AOF在读取时可读性较差。

动态切换

Redis在2.2后版本,可以在不重启的情况下,从RDB切换到AOF。

1.将最新dump.rdb文件创建备份

cp dump.rdb dump.rdb.backup

2.开启AOF

执行该命令后,Redis会阻塞直到初始化AOF文件创建完成为止,然后继续处理命令请求并开始将写入命令追加到AOF文件末尾。

redis-cli config set appendonly yes

3.关闭rdb

redos-cli config set save ""

四、Redis容灾备份

开启RDB持久化

save 900 1
save 300 10

开启AOF配置

# 开启aof
appendonly yes
appendfilename "appendony.aof"

# 开启重写
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 选择使用同步策略
appendfsync everysec

RDB日志备份

RDB日志备份,编写定时备份脚本:backup_del.sh

#!bin/bash
# 获取当前时间
cur_date=$(date "+%Y%m%d%H%M%S")
# 先删除在创建
rm -rf /usr/local/program/redis/backup/$cur_date
mkdir -p /usr/local/program/redis/backup/$cur_date
# 备份数据
cp /usr/local/program/redis/data/dump.rdb /usr/local/program/redis/backup/$cur_date
# 删除48小时前的数据
del_date=$(date -d -48hour "+%Y%m%d%H%M")
rm -rf /usr/local/program/redis/backup/$del_date

使用定时任务执行备份脚本

# 打开crontab
crontab -e

写入定时任务

* */1 * * * sh /usr/local/program/redis/backup_del.sh

四、Redis优化

1.独立部署:fork子进程频繁创建与销毁

2.硬盘优化:Redis大量的写入

3.缓存功能禁用持久化:缓存数据存在关系型数据库中,Redis可禁用持久化

4.主从模式,主关闭持久化,让从节点进行持久化

5.优化fork子进程:降低Aof重写频率,增大aof文件大小配置,关闭重写期间追加操作的配置

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/137044.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!