1. 持久化
1.1 简介
- 什么是持久化?
- 利用永久性存储介质将数据进行保存,在特定的时间将保存的数据进行恢复的工作机制称为持久化。
- 为什么要持久化?
- 防止数据意外丢失,确保数据安全性。
- 持久化过程保存的是什么?
- 将当前数据状态进行保存,快照形式,存储数据结果,存储结构简单。(RDB)
- 将数据的操作过程进行保存,日志形式,存储结构复杂。(AOF)
1.2 RDB
1.2.1 save
- sava指令
- 命令:save
- 作用:手动执行一次保存操作
- 相关配置
- dbfilename dump.rdb
- 说明:设置本地数据库文件名,默认为dump.rdb
- 经验:通常设置为dump-端口号.rdb
- dir
- 说明:设置rdb文件存储路径
- 经验:通常设置成存储空间较大的目录中,目录名称为data
- rdbcompression yes
- 说明:设置存储至本地数据库时是否压缩数据,默认yes,采用LZF压缩
- 经验:通常默认开启,如果设置为no,可节省CPU运行时间,但会使存储文件变大
- rdbchecksum yes
- 说明:设置是否进行RDB文件格式校验,该校验在写文件和读文件过程均进行
- 经验:通常默认开启,如果设置为no,可以节约一定读写性能的消耗,但是会有存储文件损坏的风险
- dbfilename dump.rdb
- 工作原理
- 单线程执行任务队列(所有的命令相当于存入任务队列,依次执行)
- save指令会阻塞当前redis服务器,直到RDB过程完成为止,有可能会造成长时间阻塞,线上不建议使用。
- 问题:如果解决save指令导致的阻塞问题?bgsave
1.2.2 bgsave
-
命令
- bgsave
-
作用
- 手动启动后台保存数据,但不立即执行
-
工作原理(执行bgsave命令后)
-
发送bgsave指令给redis服务器。
-
返回Background saving started消息。
-
调用fork函数生成子进程
-
创建rdb文件
-
返回消息
bgsave命令是针对save阻塞问题的优化。redis中所有涉及到RDB的操作都采用bgsave的方式,save可以弃用。
-
-
相关配置
-
dbfilename dump.rdb
-
dir
-
rdbcompression yes
-
rdbchecksum yes
-
stop-writes-on-bgsave-error yes
- 说明:后台保存过程中出现错误,是否停止保存操作
- 经验:默认开启
-
save second changes
-
作用:满足限定时间范围内key的变化数量达到指定数量即进行持久化
-
参数:
- second:监控时间范围
- changes:监控key的变化量(对数据产生影响,而不是命令数)
-
位置:conf文件中进行配置
-
范例:
- save 900 1
- save 300 10
- save 60 10000
sava配置要根据具体实际业务进行设置,频度过高过低都会引起性能问题
sava配置的second和changes设置通常是互补关系,不要设置成包含关系
save配置启动后执行的是bgsave
-
-
-
RDB特殊启动形式
- 全量复制
- 服务器运行过程中重启 debug reload
- 关闭服务器时指定保存数据 shutdown save(如果没有开启AOF,默认情况下执行shutdown,自动执行bgsave)
1.2.3 特点
- 优点
- RDB存储结构紧凑的二进制文件,存储效率较高
- RDB存储的是redis某个时间节点的数据快照,非常适合数据备份,全量复制等场景
- RDB恢复数据的速度要比AOF快很多
- 应用:服务器中每X个小时执行bgsave备份,并将RDB文件拷贝到远程机器中,用于灾难恢复
- 缺点
- RDB无法做到实时持久化,有较大可能丢失数据
- bgsave指令每次运行都要执行fork操作创建子进程,要牺牲掉一些性能
- redis众多版本,RDB文件格式版本不统一,可能出现多版本兼容问题
1.3 AOF
- 概念
- AOF(append only file)持久化:以独立日志的方式记录每次写命令、重启时再重新执行AOF文件中的命令以达到恢复数据的目的。与RDB相比可以简单描述为改记录数据为记录数据产生的过程。
- AOF的主要作用是解决了数据持久化的实时性,目前已是redis持久化的主流方式。
- 原理
- 当执行命令时,aof将命令刷新到缓存区。
- 将缓冲区中的命令按照策略同步到AOF文件中。
- 策略
- always(每次):每次写入操作都同步到AOF文件中,数据零误差,性能较低。
- everysec(每秒):每秒将缓存中的指令同步到AOF中,数据准确性较高,性能较高。系统宕机会丢失1s数据。
- no(系统控制):由系统控制每次同步到AOF文件的周期,整体过程不可控。
- 配置
- appendonly yes|no 是否开启AOF持久功能,默认不开启
appendfsync always|everysec|no AOF写文件策略 - appendfilename filename AOF持久化文件名称,默认为appendonly.aof,建议为appendonly-端口号.aof
- dir path AOF持久化文件保存路径,与RDB持久化文件保持一致即可
- appendonly yes|no 是否开启AOF持久功能,默认不开启
- 问题:连续写入,aof同步的时候该如何处理?
- AOF重写
- 介绍
- 随着命令不断写入aof文件,文件会越来越大,为了解决这个问题,redis引入了AOF重写机制压缩文件体积。AOF文件重写是将redis进程内的数据转化为写命令同步到AOF文件的过程。简单的说就将一条数据的多条命令执行结果转换为最终数据对应的指令进行记录。
- 作用
- 降低磁盘占用率,提高磁盘使用率
- 提高持久化效率,降低持久化写时间,提高IO性能
- 降低数据恢复用时,提高数据恢复效率
- 规则
- 进程内已超时的数据不再写入文件
- 忽视无效指令,重写时使用进程内数据直接生成,这样AOF文件中只保留的最终数据写入指令
- 对同一数据的多条写命令合并为一条命令
- 方式
- 手动重写:bgrewriteaof
- 自动重写
- auto-aof-rewrite-min-size size
- auto-aof-rewrite-percentage percentage
- 介绍
- 系统调用write和fsync说明(AOF缓冲区同步文件策略,由参数appendfsync控制)
- write操作会触发延迟写(delayed write)机制,Linux在内核提供缓冲区页来提高硬盘IO性能。write操作在写入系统缓冲区后直接返回。同步硬盘操作依赖于系统调度机制,例如:缓冲区页空间写满或达到特定时间周期。同步文件之前,如果此时系统宕机,缓冲区内数据丢失。
- fsync针对单个文件操作(比如AOF文件),做强制硬盘同步,fsync将阻塞直到写入硬盘完成后返回,保证数据持久化。
1.4 区别
- 对数据非常敏感,建议使用AOF持久化方案
- aof持久化策略使用everysec,每秒fsync一次。该策略redis仍可以保持很好的处理性能,当出现问题最多丢失1s内数据。
- 注意:AOF文件存储体积较大,且恢复速度较慢。
- 数据呈现阶段有效性,建议使用RDB持久化方案
- 数据可以做到良好的阶段性不丢失,且恢复速度较快。
- 注意:利用RDB实现紧凑的数据持久化会使redis性能降低。
- 综合比对
- RDB和AOF的选择其实是在做一种平衡,各有利弊。
- 对数据敏感,不能承受分钟内数据丢失,使用AOF。
- 能承受分钟内数据丢失,并且追求大数据集快速恢复,使用RDB。
- 灾难恢复选用RDB。
- 双保险策略,同时开启RBD和AOF。
2. 事务
2.1 简介
- redis事务就是一个命令执行队列,将一系列预定义命令包装成一个整体(一个队列)。当执行时,一次性按照添加顺序依次执行,中间不会被打断或者干扰。
- 一个队列,一次性、顺序性、排他性的执行一系列命令。
2.2 基本操作
-
操作
-
开启事务:multi 设定事务开启位置,此命令执行后,后续的所有指令均加入到事务中。
-
关闭事务:exec 设定事务结束位置,同时执行事务。与multi成对出现,成对使用。
注意:加入事务的命令暂时进入队列中,并没有立即执行,只有执行exec命令之后才开始执行
-
取消事务:discard 终止当前事务的定义,发生在multi之后,exec之前。
-
-
注意事项
-
定义事务时,命令输入错误怎么办?
如果定义的事务所包含的命令出现语法错误,整体事务所有命令都不会执行,包括正确语法的命令也不会执行。
-
定义事务,命令执行出现错误怎么办?
指令语法正确,但无法正确执行。正确运行的指令会执行,运行错误的执行不会执行。已经执行的命令不会回滚,需要手动回滚。
-
-
手动进行事务回滚
- 记录操作过程中被影响数据之前的状态。
- 设置指令恢复所有的被修改的项。
2.3 锁
- redis锁(单个客户端)
- 业务分析
- 多个客户端可能操作一组数据,并且该数据一旦被修改,将不适用于继续操作
- 在操作之前锁定要操作的数据,一旦发生变化,终止当前操作
- 解决方案
- 对key添加监视器锁,在执行exec之前如果key发生变化,终止事务执行 (watch key1 key2)
- 取消对所有key的监视 (unwatch)
- 业务分析
- 分布式锁(多客户端)
- 使用setnx设置一个公共锁 (setnx lock-key value)
- 利用setnx命令的返回值特性,有值则返回设置失败,无值则返回设置成功
- 如果设置成功,则表示锁未被持有,可以进行业务操作
- 如果设置失败,则表示锁被持有,排队或等待
- 操作完毕听过del操作释放锁
- 分布式锁(改良)
- 使用expire为锁key添加过期时间,时间到后未释放锁,则放弃锁
- expire lock-key second
- pexpire lock-key milliseconds
- 使用expire为锁key添加过期时间,时间到后未释放锁,则放弃锁
2.4 redisson
https://github.com/redisson/redisson/wiki/Redisson%E9%A1%B9%E7%9B%AE%E4%BB%8B%E7%BB%8D
评论区