Jedis 事务

Redis 事务是指将多条命令加入队列,一次批量执行多条命令,每条命令会按顺序执行,事务执行过程中不会受客户端传入的命令请求影响。本文将介绍通过 jedis 发起和执行 Redis 事务。

jedis 事务通过 multi() 开始,该方法将返回一个 Transaction 对象,我们可以利用 Transaction 对象进行事务操作,如:exec() 提交事务。

示例

开启 Redis 事务,然后保存用户基础信息、地址信息,最后保存用户和地址之间的关系信息。代码如下:

// 开启事务
Transaction transaction = this.jedis.multi();

/**
* 事务内容
*/
// 保存用户信息
Map<String,String> userHash = new HashMap<String,String>();
userHash.put("id", "1001");
userHash.put("name", "张三");
userHash.put("sex", "男");
userHash.put("age", "27");

String userId = "users:" + userHash.get("id");
transaction.hmset(userId, userHash); // 事务操作1

// 保存地址信息(多个地址)
Map<String,String> addressHash = new HashMap<String, String>();
addressHash.put("work", "工作地址");
addressHash.put("family", "家庭地址");
addressHash.put("school", "学习地址");

String addressId = "address:" + userHash.get("id");
transaction.hmset(addressId, addressHash); // 事务操作2

// 保存用户和地址间的关系
transaction.hset("userAddress", userId, addressId); // 事务操作3

// 提交事务
List<Object> result = transaction.exec();
System.out.println("结果:" + result);
System.out.println(userId + "=" + this.jedis.hgetAll(userId) );
System.out.println(addressId + "=" + this.jedis.hgetAll(addressId) );
System.out.println(userId + "=" + this.jedis.hget("userAddress", userId) );

运行代码,输出如下:

结果:[OK, OK, 1]
users:1001={sex=男, name=张三, id=1001, age=27}
address:1001={school=学习地址, work=工作地址, family=家庭地址}
users:1001=address:1001

从上面结果可知,transaction.exec() 返回了一个 List 列表,列表中表示了事务操作每个步骤的返回结果。

注意:使用事务修改 Redis 指定类型的数据时需要使用 Transaction 对象提供的方法,而不是 jedis 提供的方法。如使用 transaction.hset(),而不是 jedis.hset()。

事务原子性

还有一点我们需要特别注意,Redis 事务和关系型数据库的事务不太一样,它不保证原子性,也没有隔离级别的概念。下面就通过代码演示:

String key1 = "t1";
String key2 = "t2";

this.jedis.msetnx(key1, "Tomcat", key2, "male");
System.out.println( key1 + "=" + this.jedis.get(key1) );
System.out.println( key2 + "=" + this.jedis.get(key2) );

// 开启事务
Transaction transaction = this.jedis.multi();

transaction.set(key1, "Hibernate");
// 在字符串上面进行incrby操作将会抛出错误
transaction.incrByFloat(key2, 12.5D);

// 提交事务
transaction.exec();

// 从输出的结果可以看出,并没有进行回滚
System.out.println( key1 + "=" + this.jedis.get(key1) );
System.out.println( key2 + "=" + this.jedis.get(key2) );

运行代码,输出如下:

t1=Tomcat
t2=male
t1=Hibernate
t2=male

通过上面输出结果可知,t1 键的值已经被修改,当 jedis 抛错的时候并不会进行回滚。

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