前言
redis中的事务其实就是 :一段指令
redis单条命令的原子性的,而事务不保证原子性
redis事务中所有的命令都会被序列化,执行顺序:谁先进谁先执行
redis事务的三个特性:一次性、顺序性、排他性
redis事务中没有隔离级别概念:所有的命令在事务中,并没有直接执行,只有发起执行的时候才会执行
乐观锁:只会在更新的时候去判断,期间是否有人修改过version
1.导入依赖
<dependencies>
<!--jedis-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.2.0</version>
</dependency>
<!--fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
</dependencies>
maven仓库: https://mvnrepository.com
2.创建一个User实体类
package dao;
public class userDao {
/**
* 用户id
*/
private long userId;
/**
* 用户姓名
*/
private String userName;
/**
* 用户年龄
*/
private Integer age;
/**
* 0中性 1男 2女
* */
private Integer sex;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public userDao() {
}
public userDao(long userId, String userName, Integer age, Integer sex) {
this.userId = userId;
this.userName = userName;
this.age = age;
this.sex = sex;
}
@Override
public String toString() {
return "userDao{" +
"userId=" + userId +
", userName='" + userName + '\'' +
", age=" + age +
", sex=" + sex +
'}';
}
}
3.提交事务并获取数据
public static void main(String[] args) {
//user对象1
userDao user1 = new userDao();
user1.setUserId(Long.valueOf("1"));
user1.setUserName("一只小狐狸OvO");
user1.setAge(18);
user1.setSex(1);
//user对象2
userDao user2 = new userDao();
user2.setUserId(Long.valueOf("2"));
user2.setUserName("凉拌小狐狸OvO");
user2.setAge(16);
user2.setSex(2);
// 1. new jsedis 对象
// jedis里面存放了全部的指令,具体的指令用途可以去redis的官方文档里面看
// Redis中文帮助手册:https://www.redis.net.cn/order/
// 地址是云Redis地址,到期日期是:2025-09-20 大家都可以使用
Jedis jedis = new Jedis("114.115.208.175",6379);
// 清除数据 为了下面模拟
jedis.flushDB();
//开启事务
Transaction multi = jedis.multi();
try{
multi.set("user_data_key:userId:"+user1.getUserId(),toJsonString(user1));
multi.set("user_data_key:userId:"+user2.getUserId(),toJsonString(user2));
//提交事务
multi.exec();
}catch (Exception e){
//放弃事务 事务中的所有命令都不会执行
multi.discard();
//抛出异常
e.printStackTrace();
}finally {
// mget:批量获取
List<String> redisGetList = jedis.mget("user_data_key:userId:"+user1.getUserId(),"user_data_key:userId:"+user2.getUserId());
//输出从redis中拿到的数据
System.out.println(redisGetList);
//关闭事务
jedis.close();
}
}
/**
* 将对象转成json字符串
* */
public static String toJsonString(Object object){
return JSONObject.toJSONString(object);
}
/**
* 将jsonString转换成Obj
* */
public static Object toStringObj(String jsonString,Class Objclass){
return JSONObject.parseObject(jsonString,Objclass);
}
5.Redis乐观锁:watch监控
当watch检测到数据变动的时候,此时watch失效,可以使用unwatch取消监视,再重新监视值,开启事务。(需要在多线程的情况下)
public static void main(String[] args) {
// new jsedis 对象
Jedis jedis = new Jedis("114.115.208.175",6379);
// 清除数据 为了下面模拟
jedis.flushDB();
// set 一个监控的数据
jedis.set("user_data_key:userAge","18");
// 乐观锁·监控 userAge
jedis.watch("user_data_key:userAge");
//开启事务
Transaction multi = jedis.multi();
try{
//步长 将userAge+1
multi.incrBy("user_data_key:userAge",1);
//提交事务
multi.exec();
}catch (Exception e){
// 提交事务可能会遇到运行时异常
multi.discard();
//抛出异常
e.printStackTrace();
}finally {
//关闭事务
jedis.close();
}
}