🌟 后端 | Redis 事务



Redis 事务提供了一种将多个命令请求打包的功能。然后,再按顺序执行打包的所有命令,并且不会被中途打断。

除了不满足原子性和持久性之外,事务中的每条命令都会与 Redis 服务器进行网络交互,这是比较浪费资源的行为。

因此,Redis 事务不建议在日常开发中使用。

使用 Redis 事务

Redis 可以通过 MULTI、EXEC、DISCARD 和 WATCH 等命令来实现事务(Transaction)功能。

1
2
3
4
5
6
7
8
9
MULTI
OK
SET PROJECT "JavaGuide"
QUEUED
GET PROJECT
QUEUED
EXEC
1) OK
2) "JavaGuide"

MULTI 命令后可以输入多个命令,Redis 不会立即执行这些命令,而是将它们放到队列,当调用了 EXEC 命令后,再执行所有的命令。

这个过程是这样的:

  • 开始事务(MULTI);
  • 命令入队(批量操作 Redis 的命令,先进先出(FIFO)的顺序执行);
  • 执行事务(EXEC)。

你也可以通过 DISCARD 命令取消一个事务,它会清空事务队列中保存的所有命令。

Redis 不支持原子性

Redis 事务在运行错误的情况下,除了执行过程中出现错误的命令外,其他命令都能正常执行。并且,Redis 事务是不支持回滚(roll back)操作的。因此,Redis 事务其实是不满足原子性的。Redis 官网也解释了自己为啥不支持回滚。简单来说就是 Redis 开发者们觉得没必要支持回滚,这样更简单便捷并且性能更好。

Redis 支持持久性

Redis 不同于 Memcached 的很重要一点就是,Redis 支持持久化,而且支持 3 种持久化方式:

  • 快照(snapshotting,RDB);
  • 只追加文件(append-only file,AOF);
  • RDB 和 AOF 的混合持久化(Redis 4.0 新增)。

与 RDB 持久化相比,AOF 持久化的实时性更好。

在 Redis 的配置文件中存在三种不同的 AOF 持久化方式(fsync 策略),它们分别是:

1
2
3
appendfsync always    #每次有数据修改发生时,都会调用fsync函数同步AOF文件,fsync完成后线程返回,这样会严重降低Redis的速度
appendfsync everysec #每秒钟调用fsync函数同步一次AOF文件
appendfsync no #让操作系统决定何时进行同步,一般为30秒一次

AOF 持久化的 fsync 策略为 no、everysec 时都会存在数据丢失的情况。always 下可以基本是可以满足持久性要求的,但性能太差,实际开发过程中不会使用。

因此,Redis 事务的持久性也是没办法保证的。