文章目录
题记
在线思维导图总结:redis大纲
利用Watch实现Redis乐观锁
乐观锁基于CAS(Compare And Swap)思想(比较并替换),是不具有互斥性,不会产生锁等待而消
耗资源,但是需要反复的重试,但也是因为重试的机制,能比较快的响应。因此我们可以利用redis来实
现乐观锁。具体思路如下:
- 利用redis的watch功能,监控这个redisKey的状态值
- 获取redisKey的值
- 创建redis事务
- 给这个key的值+1
- 然后去执行这个事务,如果key的值被修改过则回滚,key不加1
场景:开启20个线程,模拟100个用户秒杀商品,商品只有三个名额
package com.learn.cache;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author weijie
* @date 2020/7/30 13:05
*/
public class Demo {
public static void main(String[] args) {
String rediskey = "lock";
ExecutorService executorService = Executors.newFixedThreadPool(20);
Jedis jedis = new Jedis("127.0.0.1", 6379);
jedis.auth("123456");
jedis.set(rediskey, "0");
jedis.close();
for (int i = 0; i < 100; i++) {
executorService.execute(() -> {
Jedis jedis2 = new Jedis("127.0.0.1", 6379);
jedis2.auth("123456");
//监听key
jedis2.watch(rediskey);
String redisValue = jedis2.get(rediskey);
int v = Integer.parseInt(redisValue);
String userInfo = UUID.randomUUID().toString();
if (v < 3){
//开启redis事务
Transaction tx = jedis2.multi();
//自增长
tx.incr(rediskey);
//事务提交
List<Object> list = tx.exec();
if (list != null && list.size() > 0){
System.out.println("用户:" + userInfo + "秒杀成功!当前人数: " + (v + 1));
}
//版本变化
else{
System.out.println("用户:" + userInfo + "秒杀失败!");
}
}else {
System.out.println("商品已售空!");
}
});
jedis.close();
}
executorService.shutdown();
}
}