redis采用的是乐观锁的方式进行的事务控制,使用watch命令监视给定的key,当exec提交事务的时候,监视的key从调用watch后发生变化 ,则事务失败 当然exec , discard ,unwatch都会清除连接中的所有监视.
为什么使用事务?
为了保证数据的正确性
特性 ACID
原子性
一致性
持久性
隔离性
基本指令
multi 手动开启事务
exec 手动提交事务
discard 手动取消事务
watch 开启监控,如果监控发生变化,则提交事务时会失败
unwatch 去掉监控
discard取消事务
redis事务太简单,没有回滚 只是取消.
售票代码实例
package com.jt.redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
/**
* 基于redis实现一个简单的多线程秒杀的抢票操作
* 演示乐观锁
*/
public class SecondKillDemo02 {
public static void main(String[] args){
//初始化票数
Jedis jedis = new Jedis("192.168.126.129",6379);
jedis.set("ticket", "100");
jedis.set("money", "0");
//模拟多个线程抢票操作
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 10; i++) {
byTicket();
}
}
});
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
byTicket();
}
});
//启动线程
thread.start();
thread1.start();
}
private static void byTicket(){
Jedis jedis = new Jedis("192.168.126.129",6379);
//监控redis中的key
jedis.watch("ticket","money");
//业务
String ticket = jedis.get("ticket");
if (ticket == null && Integer.valueOf(ticket) == 0 && "".equals(ticket) )
throw new RuntimeException("余票不足");
//开启事务
Transaction multi = jedis.multi();
try {
multi.decr("ticket");
multi.incrBy("money", 100);
//提交事务
multi.exec();
System.out.println("事务执行成功");
}catch (Exception e){
multi.discard();
System.out.println("事务执行失败");
}finally {
//取消监控
jedis.unwatch();
//释放资源
jedis.close();
}
}
}