使用Java操作Redis事务
事务
Redis 事务可以一次执行多个命令,有两个特性:
-
隔离性:事务的所有命令都会序列化、按顺序的执行,事务执行完后才会执行其他客服端的命令。
-
原子性: 事务中的命令要么全部被执行,要么全部不执行。
使用你事务时会遇到两个错误:
-
入队时出错,一般时因为语法错误引起的,加入事务队列就会报错,遇到这类错误,一般会放弃事务
-
EXEC调用后出错,列如对一个 值为
a1
的key
执行incr
,这类错误,即使某个命令产生了错误,其他命令依旧会继续执行执行,不会回滚
Reids 中的 WATCH
命令
使用 WATCH
命令可以监控键,如果被监控的键,再 EXEC
之前被修改,那么事务会放弃执行(注意:事务中的命令在 exec
命令后才开始执行)
EXEC
执行以后,无论事务是否执行成功,都会放弃对所有键的监控。
使用Java操控Redis事务命令
1 2 3 4 5 6 7 8 9 10 | // 开启事务 Transaction transaction = jedis.multi(); // 提交事务 transaction.exec(); // 放弃事务 transaction.discard(); // 监控键 jedis.watch( "balance" , "debt" ); // 放弃所有被监控的键 jedis.unwatch(); |
完整代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | package com.project.test; import java.util.List; import org.junit.Before; import org.junit.Test; import redis.clients.jedis.Jedis; import redis.clients.jedis.Transaction; /** * Rdis 事务 * */ public class TestTX { static final Jedis jedis = new Jedis( "132.232.6.208" , 6381 ); /** * 清空数据库 */ @Before public void flushdb() { jedis.flushDB(); } @Test public void commitTest() { // 开启事务 Transaction transaction = jedis.multi(); transaction.set( "key-1" , "value-1" ); transaction.set( "key-2" , "value-2" ); transaction.set( "key-3" , "value-3" ); transaction.set( "key-4" , "value-4" ); // 提交事务 transaction.exec(); System.out.println(jedis.keys( "*" )); } @Test public void discardTest() { // 开启事务 Transaction transaction = jedis.multi(); transaction.set( "key-1" , "value-1" ); transaction.set( "key-2" , "value-2" ); transaction.set( "key-3" , "value-3" ); transaction.set( "key-4" , "value-4" ); // 放弃事务 transaction.discard(); System.out.println(jedis.keys( "*" )); } /** * watch 命令会标记一个或多个键 * 如果事务中被标记的键,在提交事务之前被修改了,那么事务就会失败。 * @return * @throws InterruptedException */ @Test public void watchTest() throws InterruptedException { boolean resultValue = transMethod( 10 ); System.out.println( "交易结果(事务执行结果):" + resultValue); int balance = Integer.parseInt(jedis.get( "balance" )); int debt = Integer.parseInt(jedis.get( "debt" )); System.out.printf( "balance: %d, debt: %d\n" , balance, debt); } // 支付操作 public static boolean transMethod( int amtToSubtract) throws InterruptedException { int balance; // 余额 int debt; // 负债 jedis.set( "balance" , "100" ); jedis.set( "debt" , "0" ); jedis.watch( "balance" , "debt" ); balance = Integer.parseInt(jedis.get( "balance" )); // 余额不足 if (balance < amtToSubtract) { jedis.unwatch(); // 放弃所有被监控的键 System.out.println( "Insufficient balance" ); return false ; } Transaction transaction = jedis.multi(); // 扣钱 transaction.decrBy( "balance" , amtToSubtract); Thread.sleep( 5000 ); // 在外部修改 balance 或者 debt transaction.incrBy( "debt" , amtToSubtract); // list为空说明事务执行失败 List<Object> list = transaction.exec(); return !list.isEmpty(); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具