一、Redis持久化
由于Redis的数据都存放在内存中,如果没有配置持久化,Redis重启后数据就全丢失了,于是需要开启
Redis的持久化功能,将数据保存到磁盘上,当Redis重启后,可以从磁盘中恢复数据。
Redis提供了两个不同形式的持久化方式:
- RDB(Redis DataBase)
- AOF(Append Only File)
1 持久化操作-RDB
1.1 RDB是什么?
在指定的时间间隔内将内存的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里。
1.2 备份过程
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
1.3 dump.rdb文件
1. RDB保存的文件,在redis.conf中配置文件名称,默认为dump.rdb。
2. rdb文件的保存位置,也可以修改。默认在Redis启动时命令行所在的目录下。
redis.conf中配置文件路径
1.4 如何触发快照?
1.4.1 配置文件中默认的快照配置
1. 快照默认配置
save 3600 1:表示3600秒内(一小时)如果至少有1个key的值变化,则保存
save 300 100:表示300秒内(五分钟)如果至少有100个 key 的值变化,则保存
save 60 10000:表示60秒内如果至少有 10000个key的值变化,则保存
可以自己配置新的保存规则。
2. 例:给redis.conf添加新的快照策略,30秒内如果有5次key的变化,则触发快照。配置修改后,需要重启Redis服务。
dump.rdb默认大小是92字节,里面会有一些基本信息。
30秒内设置5个以上的值。
set k1 v1
set k2 v2
set k3 v3
set k4 v4
set k5 v5
set k6 v6
set k7 v7
dump.rdb大小已经改变。
1.4.2 flushall
执行flushall命令,也会触发rdb规则。
1.4.3 save与bgsave
手动触发Redis进行RDB持久化的命令有两种:
1. save
该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止,不建议使用。
2. bgsave
执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。
这两个命令是在Redis客户端中执行,并不是redis.conf中修改。
1.4.4 stop-writes-on-bgsave-error
默认值是yes。当Redis无法写入磁盘的话,直接关闭Redis的写操作。
1.4.5 rdbcompression
默认值是yes。对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能,但是存储在磁盘上的快照会比较大。
1.4.6 rdbchecksum
默认值是yes。在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
1.5 恢复数据
只需要将rdb文件放在Redis的启动目录,Redis启动时会自动加载dump.rdb并恢复数据。
2 持久化操作-AOF
2.1 AOF是什么?
以日志的形式来记录每个写操作,将Redis执行过的所有写指令记录下来(读操作不记录),只允许加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,Redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。
2.2 AOF持久化流程
1. 客户端的请求写命令会被append追加到AOF缓冲区内。
2. AOF缓冲区根据AOF持久化策略[always,everysec,no]将操作同步到磁盘的AOF文件中。
3. AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容量。
4. Redis服务重启时,会重新load加载AOF文件中的写操作达到数据恢复的目的。
2.3 AOF默认不开启
可以在redis.conf中配置文件名称,默认为appendonly.aof。
AOF文件的保存路径,同RDB的路径一致。
如果AOF和RDB同时启动,Redis默认读取AOF的数据。
2.4 AOF启动/修复/恢复
正常恢复
1. 启动:设置Yes:修改默认的appendonly no,改为yes。
2. 恢复:重启Redis然后重新加载。
例:设置appendonly为yes,配置修改后,需要重启Redis服务。
服务器启动后,生成appendonly.aof文件,且大小为0。
设置数据。
set k11 v11
set k12 v12
set k13 v13
set k14 v14
set k15 v15
appendonly.aof大小已经改变。
异常恢复
1. 启动:设置Yes:修改默认的appendonly no,改为yes。
2. 修复:如遇到AOF文件损坏,通过/user/local/bin/redis-check-aof --fix appendonly.aof进行恢复。
3. 恢复:重启Redis然后重新加载。
例:服务启动和数据设置同上,模拟损坏appendonly.aof文件
vi appendonly.aof
重启Redis服务,并连接。由于aof文件被破坏,导致服务器启动失败。
通过/user/local/bin/redis-check-aof --fix工具对appendonly.aof进行恢复。
./redis-check-aof --fix appendonly.aof
修复成功。再次查看aof文件,破坏的地方已经修复。再次启动服务器成功。
2.5 AOF同步频率设置
1. appendfsync always
始终同步,每次Redis的写入都会立刻记入日志,性能较差但数据完整性比较好。
2. appendfsync everysec
每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失。
3. appendfsync no
redis不主动进行同步,把同步时机交给操作系统。
2.6 Rewrite
1. AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。
例:设置k1为0,然后incr 进行了4次,k1对应的值会是4,其实就相当于set k1 4
2. 重写虽然可以节约大量磁盘空间,减少恢复时间。但是每次重写还是有一定的负担的,因此设定
Redis要满足一定条件才会进行重写。
四、Redis事务
1 Redis事务简介
1. Redis事务是一组命令的集合,一个事务中的所有命令都将被序列化,按照一次性、顺序性、排他性的执行一系列的命令。
2. Redis单条命令保证原子性,但是事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。
3. Redis事务没有隔离级别的概念。批量操作在执行前被放入缓存队列,并不会被实际执行,也就不存在事务内的查询要看到事务里的更新,事务外查询不能看到。
4. Redis事务的三个阶段:
- 开始事务
- 命令入队
- 执行事务
2 Redis事务基本操作
2.1 Multi、Exec、discard
事务从输入Multi命令开始,输入的命令都会依次压入命令缓冲队列中,并不会执行,直到输入Exec后,Redis会将之前的命令缓冲队列中的命令依次执行。组队过程中,可以通过discard来放弃组队。
例1:
multi 开始事务
set k1 v1 进行组队,并不执行
set k2 v2 进行组队,并不执行
exec 执行队列命令,依次设置k1 k2
例2:
multi 开始事务
set k3 v3 进行组队,并不执行
set k4 v4 进行组队,并不执行
discard 取消组队,都不执行
2.2 事务的错误处理
1. 组队阶段某个命令出现了错误,整个队列中的命令都不执行。
例:整个命令缓存队列都不会执行。
2. 执行阶段某个命令出现了错误,只有报错的命令不会执行,其他正常执行。
例:只有报错的命令没有执行。
3 悲观锁与乐观锁
3.1 事务应用场景
- 一个请求想给余额减8000
- 一个请求想给余额减5000
- 一个请求想给余额减1000
3.2 悲观锁(Pessimistic Lock)
每次去拿数据的时候都认为别人会修改,所以在每次拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞,直到它拿到锁。传统关系型数据库就用到很多悲观锁,比如行锁、表锁等。
3.3 乐观锁(Optimistic Lock)
每次去拿数据的时候都认为别人不会修改,所以不会上锁,但在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制。乐观锁适用于多读的应用类型,可以提高吞吐量。Redis就是乐观锁机制实现事务的。
4 Redis中的乐观锁
4.1 watch key [key……]
在执行multi之前,先执行watch监视一个或多个key,如果在事务执行之前这个(或这些)key被其它命令所改动,那么事务将被打断。
例:开启两个客户端
1号客户端
set money 10000 设置一个money的key
watch money 监视money
multi 开启事务
set money 100 修改money,暂时不执行事务
2号客户端
watch money 监视money
multi 开启事务
set money 110 修改money,暂时不执行事务
1号客户端
exec 执行事务,返回成功
2号客户端
exec 执行事务,更新失败
1号客户端
2号客户端
4.2 unwatch
取消watch命令对所有key的监视
如果在执行watch命令之后,exec命令或discard命令先执行的话,那么就不需要再执行unwatch。