Redis 事务

在传统数据库中,事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态到另一种一致性状态。事务是逻辑上的一组操作,要么都执行,要么都不执行。事务具有四大特性(ACID):

(1)原子性(Atomicity): 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

(2)一致性(Consistency): 事务前后数据的完整性必须保持一致。

(3)持久性(Durability): 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

(4)隔离性(Isolation): 事务的隔离性是指多个用户并发操作数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。 简单来说: 事务之间互不干扰。

Redis 事务是指将多条命令加入队列,一次批量执行多条命令,每条命令会按顺序执行,事务执行过程中不会受客户端传入的命令请求影响。Redis 有以下三个重要的保证:

  • 批量操作在发送 EXEC 命令前被放入队列缓存。

  • 收到 EXEC 命令后进入事务执行,事务中任意命令执行失败,其余的命令依然被执行。

  • 在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中。

Redis 事务和关系型数据库的事务不太一样,它不保证原子性,也没有隔离级别的概念。如下:

(1)Redis 事务没有隔离级别的概念: 批量操作在发送 EXEC 命令前被放入队列缓存,并不会被实际执行,也就不存在事务内的查询要看到事务里的更新,事务外查询不能看到。

(2)Redis 不保证原子性: Redis 中,单条命令是原子性执行的,但事务不保证原子性,且没有回滚。事务中任意命令执行失败,其余的命令仍会被执行。

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

  • 第一阶段:开始事务

  • 第二阶段:命令入队列

  • 第三阶段:执行事务

实例

该实例使用 Redis 的事务批量执行多个命令,如下:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name "hello world"
QUEUED
127.0.0.1:6379> set age 20
QUEUED
127.0.0.1:6379> set email "demo@163.com"
QUEUED
127.0.0.1:6379> mget name age email
QUEUED
127.0.0.1:6379> exec
1) OK
2) OK
3) OK
4) 1) "hello world"
  2) "20"
  3) "demo@163.com"

上面实例中,使用 multi 命里开启事务,然后开始执行多个 set 和 mget 命令,最后执行 exec 命令提交事务。

Redis 发布订阅命令

下表列出了 Redis 事务的常用命令。

MULTI命令

标识一个事务的开启,即开启事务。语法如下:

MULTI

实例:

127.0.0.1:6379> multi
OK

EXEC命令

执行事务中的所有命令(即提交事务),并将连接状态恢复为正常。注意,使用 WATCH 时,EXEC 仅在未修改被监视的键时才执行命令,从而允许检查和设置机制。语法如下:

EXEC

实例:

127.0.0.1:6379> exec
1) OK
2) OK
3) OK
4) 1) "hello world"
  2) "20"
  3) "demo@163.com"

DISCARD命令

刷新事务中所有先前排队的命令,并将连接状态恢复到正常。即放弃事务,这和回滚不一样,Redis 事务不支持回滚。注意,如果使用了 WATCH 命令监听键,DISCARD 命令将取消对连接所监视的所有键的监视。语法如下:

DISCARD

实例:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name "hxstrive"
QUEUED
127.0.0.1:6379> discard
OK

WATCH命令

监视键的变化,用于实现乐观锁。如果监视的键的值改变了,事务最终会执行失败。语法如下:

WATCH key [key ...]

实例:

(1)使用 watch 命令监听 name 键,如下:

127.0.0.1:6379> watch name
OK

(2)使用 multi 和 exec 命令执行事务,如下:

127.0.0.1:6379> multi
OK
127.0.0.1:6379> set name "www.hxstrive.com"
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get name
"update name"

注意,上面实例执行事务失败了,这是因为在执行事务之前,其他 redis 客户端修改了 name 键的内容为 “update name”。

UNWATCH命令

放弃监视。注意,如果调用了 EXEC 或 DISCARD 命令,则无需手动调用 UNWATCH 命令放弃键的监视。语法如下:

UNWATCH

实例:

127.0.0.1:6379> watch name
OK
127.0.0.1:6379> unwatch
OK

更多命令请访问 https://redis.io/commands  进行参考。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号