redis事务的相关命令(如何实现 redis 事务)

本文目录
如何实现 redis 事务
Redis 通过 MULTI、EXEC、WATCH 等命令来实现事务(transaction)功能。事务提供了一种将多个命令请求打包,然后一次性、按顺序地执行多个命令的机制,并且在事务执行期间,服务器不会中断事务而改去执行其他客户端的命令请求,它会将事务中的所有命令都执行完毕,然后才去处理其他客户端的命令请求。
在传统的关系式数据库中,常常用 ACID 性质来检验事务功能的可靠性和安全性。在 Redis 中,事务总是具有原子性(Atomicity)、一致性(Consistency)和隔离性(Isolation),并且当 Redis 运行在某种特定的持久化模式下时,事务也具有持久性(Durability)。
如何在Redis中实现事务
举个例子:
我们到银行ATM机取一笔钱,我们的操作可能是如下:
插卡(输入密码)
输入要取的金额
ATM吐钞
后台在你的户头上扣掉相应金额
整个操作是一个顺序,不可分割的整体。上一步完成后才会执行下一步,如果ATM没吐钞却扣了用户的钱,银行可是要关门了。
Redis中的事务
先来看一下事务相关的命令
命令原型 命令描述
MULTI 用于标记事务的开始,其后执行的命令都将被存入命令队列,直到执行EXEC时,这些命令才会被原子的执行。
EXEC 执行在一个事务内命令队列中的所有命令,同时将当前连接的状态恢复为正常状态,即非事务状态。如果在事务中执行了WATCH命令,那么只有当WATCH所监控的Keys没有被修改的前提下,EXEC命令才能执行事务队列中的所有命令,否则EXEC将放弃当前事务中的所有命令。
DISCARD 回滚事务队列中的所有命令,同时再将当前连接的状态恢复为正常状态,即非事务状态。如果WATCH命令被使用,该命令将UNWATCH所有的Keys。
WATCH key 在MULTI命令执行之前,可以指定待监控的Keys,然而在执行EXEC之前,如果被监控的Keys发生修改,EXEC将放弃执行该事务队列中的所有命令。
UNWATCH 取消当前事务中指定监控的Keys,如果执行了EXEC或DISCARD命令,则无需再手工执行该命令了,因为在此之后,事务中所有被监控的Keys都将自动取消。
和关系型数据库中的事务相比,在Redis事务中如果有某一条命令执行失败,其后的命令仍然会被继续执行。
我们可以通过MULTI命令开启一个事务,有关系型数据库开发经验的人可以将其理解为 BEGIN TRANSACTION 语句。在该语句之后执行的命令都将被视为事务之内的操作,最后我们可以通过执行 EXEC/DISCARD 命令来提交/回滚该事务内的所有操作。这两个Redis命令可被视为等同于关系型数据库中的 COMMIT/ROLLBACK 语句。
在事务开启之前,如果客户端与服务器之间出现通讯故障并导致网络断开,其后所有待执行的语句都将不会被服务器执行。然而如果网络中断事件是发生在客户端执行 EXEC 命令之后,那么该事务中的所有命令都会被服务器执行。
当使用Append-Only模式时,Redis会通过调用系统函数write将该事务内的所有写操作在本次调用中全部写入磁盘。然而如果在写入的过程中出现系统崩溃,如电源故障导致的宕机,那么此时也许只有部分数据被写入到磁盘,而另外一部分数据却已经丢失。Redis服务器会在重新启动时执行一系列必要的一致性检测,一旦发现类似问题,就会立即退出并给出相应的错误提示。此时,我们就要充分利用Redis工具包中提供的redis-check-aof工具,该工具可以帮助我们定位到数据不一致的错误,并将已经写入的部分数据进行回滚。修复之后我们就可以再次重新启动Redis服务器了。
样例
@Test
public void test2Trans() {
Jedis jedis = new Jedis("localhost");
long start = System.currentTimeMillis();
Transaction tx = jedis.multi();
for (int i = 0; i 《 100000; i++) {
tx.set("t" + i, "t" + i);
}
List《Object》 results = tx.exec();
long end = System.currentTimeMillis();
System.out.println("Transaction SET: " + ((end - start)/1000.0) + " seconds");
jedis.disconnect();
}
得到事务结果result之后,可以检查当中是否有非OK的返回值,如果存在则说明中间执行错误,可以使用 DISCARD 来回滚执行结果。
WATCH命令
WATCH 为 MULTI 执行之前的某个Key提供监控(乐观锁)的功能,如果Key的值变化了,就会放弃事务的执行。
当事务 EXEC 执行完成之后,就会自动 UNWATCH 。
你应该知道的Redis事务
如果你了解过关系型数据库事务的话,相信这篇文章对你来说是很容易理解的了。具体什么是事务我就不说不多了,直接讲 Redis 事务相关的部分。
首先,我们先来看下,Redis 是怎么执行事务的。
show code:
一个事务的开始到结束会经过以下 3 个过程
结合上面的例子,用人话介绍这 3 个过程就是:
Redis 执行 multi 命令标志事务开始。
当客户端切换至事务状态后,服务端会将除了 exec、discard(取消事务,放弃执行事务块内的所有命令)、watch 和 multi 以外的命令放进一个先进先出的事务队列中。即上面例子的 2 个 set 命令会被放进队列,并返回 QUEUED 给客户端。
当客户端发送 exec 命令时,服务端会立即执行该命令。遍历这个客户端的事务队列,执行队列保存的所有命令。最后将执行命令所得结果返回给客户端。
两者最大区别就是 Redis 事务不支持回滚 。即使事务队列中某个命令在执行期间发生了错误,事务也会继续执行,直到事务队列中所有命令执行完成。
文字貌似不够直观,没事,看下面的例子你就马上明白了。
PS:如果客户端向事务入列一个错误的命令(比如输入一个不存在的命令,像:sett 命令),那么该事务将不被服务端执行。该情况是入队错误,上面例子是执行错误的情况。
提到 redis 事务,就不得不提 watch 命令了。
该命令是一个乐观锁,只能在客户端进入事务状态之前执行。
作用是 exec 命令执行之前,监视任何数量个键,并在 exec 命令执行时,检查被监视的键是否至少有一个已经被修改过。若是则拒绝执行事务,否则执行。
当 exec 执行完成后,这次事务也就结束了。
我们依旧来看一个简单的栗子:

更多文章:
数据库管理系统和数据库系统分别侧重(数据库,数据库管理系统,数据库系统,这三个分别是什么意思并举个实例)
2026年9月7日 17:00
springmvc的依赖(springMVC的注入方式有哪几种,这与springMVC依赖)
2026年9月7日 14:00
display flex 自动换行(overflow-y:hidden;overflow-x:auto;无效解决方法)
2026年9月7日 11:00
timestamp without time zone(Postgresql中to_date()函数使用问题)
2026年9月7日 09:40






