redis事务及持久化 / Redis Transaction

简单事务控制

  • redis是单线程处理所有client的请求
  • multi当前client连接进入一个事务上下文, 该连接后续的命令不会立即执行, 而是放到队列(Queue)中, 直到接收到exec指令后才会按顺序执行
1
2
3
4
5
6
7
8
9
10
11
12
redis 127.0.0.1:6379> multi
OK
redis 127.0.0.1:6379> set age 10
QUEUED
redis 127.0.0.1:6379> set age 20
QUEUED
redis 127.0.0.1:6379> exec
1) OK
2) OK
redis 127.0.0.1:6379> get age
"20"
redis 127.0.0.1:6379>
  • 使用discard命令取消事务, 使其回滚
  • watch命令可以监视键值对, 当exec提交时如果被监视的键值对发生变化, 事务将被取消

复杂事务控制 - 乐观锁

  • 基于version版本记录机制实现, 即为数据增加一个版本标识(version字段), 读取时将此版本号一同读出, 之后更新时对此版本号加1
  • 如果提交的数据版本号大于数据库当前版本号, 则予以更新, 否则失败
  • 即如果session 1和session 2同时对数据库进行操作, 在session 1提交更新之前, session 2已经完成提交, 那么数据库版本号已经+1, 则session 1提交失败
  • redis只能保证事务的每个命令连续执行, 如果事务中的一个命令失败了, 并不会回滚其他命令

持久化机制

redis是支持持久化的内存数据库, 需要经常将内存中的数据同步到磁盘来保证持久化; 有snapshotting快照(默认)和append-only file (aof) 两种方式

snapshooting

将内存中的数据以快照的方式写入到二进制文件, 默认文件名dump.rdb; 可以修改redis配置来实现

1
2
save 900 1  # 900秒内如果超过1个key被修改, 则发起快照保存
save 300 10 # 300秒内如果超过10个key被修改, 则发起快照保存

也可以使用savebgsave命令通知redis做一次快照持久化(不推荐), 这种方式会阻塞所有client请求;

另外需要注意, 每次快照持久化都是将内存数据完整写入磁盘一次, 如果数据量大时, 会造成大量的磁盘io操作, 严重影响性能

append-only file

由于每次snapshooting之间有间隔, 如果redis意外down掉, 会丢失最后一次快照前的所有修改. 避免这种情况可以使用aof方式持久化

aof方式下, redis会通过write函数追加到文件中(默认是appendonly.aof)

配置文件:

1
2
3
4
appendonly yes  # 启用aof持久化方式
# appendfsync always # 收到写命令立即写入磁盘, 最慢, 但是保证完全的持久化
appendfsync everysec # 每秒钟写入磁盘一次, 在性能和持久化方面做了折中
# appendfsync no # 完全依赖os, 性能最好, 但持久化没保证

使用aof方式的问题是, 其持久化文件会变得越来越大。 为了压缩, redis提供了bgrewriteaof命令; 收到此命令后, redis将使用与快照类似的方式将内存中的数据以命令的形式保存到临时文件中, 最后替换原来的文件.

本文标题:redis事务及持久化 / Redis Transaction

文章作者:Vincent Zheng

发布时间:2018年10月21日 - 14:10

最后更新:2018年10月21日 - 14:10

原始链接:https://zws910.github.io/2018/10/21/redis-transaction/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%