第一种使用lua脚本完成分布式锁
package com.atguigu.bootredis01.controller;
import com.atguigu.bootredis01.util.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@RestController
public class GoodConreoller {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Value("${server.port}")
private String serverPort;
private static final String REDIS_LOCK = "atguigu";
@GetMapping("/buy_goods")
public String buy_Goods() throws Exception {
long start = System.currentTimeMillis();
String value = UUID.randomUUID().toString() + Thread.currentThread().getName();
try {
Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK, value, 10L, TimeUnit.SECONDS);
if(!flag){
System.out.println("枪锁失败");
return "枪锁失败";
}
String result = stringRedisTemplate.opsForValue().get("goods:001");
int goodsNumber = result==null ? 0:Integer.parseInt(result);
if(goodsNumber > 0){
int realNUmber = goodsNumber - 1;
stringRedisTemplate.opsForValue().set("goods:001",String.valueOf(realNUmber));
System.out.println("成功买到商品,还剩下:"+realNUmber+"件库存"+"服务提供者是:"+serverPort);
return Thread.currentThread().getName()+"来光顾"+"成功买到商品,还剩下:"+realNUmber+"件库存"+"服务提供者是:"+serverPort;
}else {
System.out.println(Thread.currentThread().getName()+"来光顾 "+"卖完了啊,下次早点来啊"+"服务提供者是:"+serverPort);
}
return "卖完了啊,下次早点来啊"+"服务提供者是:"+serverPort;
} finally {
Jedis jedis = RedisUtils.getJedis();
String script ="if redis.call('get',KEYS[1]) == ARGV[1] " +
"then " +
"return redis.call('del',KEYS[1]) " +
"else " +
" return 0 " +
"end";
try {
Object eval = jedis.eval(script, Collections.singletonList(REDIS_LOCK), Collections.singletonList(value));
if("1".equalsIgnoreCase(eval.toString())){
System.out.println("-------del redis lock ok");
}
else {
System.out.println("-------del redis lock error");
}
}finally {
if(null != jedis){
jedis.close();
long finish = System.currentTimeMillis();
long timeElapsed = finish - start;
System.out.println("耗费时间 " + timeElapsed);
}
}
}
}
}
第二种:使用redis事务完成分布式事务锁
package com.atguigu.bootredis01.controller;
import com.atguigu.bootredis01.util.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@RestController
public class GoodConreoller {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Value("${server.port}")
private String serverPort;
private static final String REDIS_LOCK = "atguigu";
@GetMapping("/buy_goods")
public String buy_Goods() throws Exception {
String value = UUID.randomUUID().toString() + Thread.currentThread().getName();
Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK, value, 10L, TimeUnit.SECONDS);
if(!flag){
System.out.println("枪锁失败");
return "枪锁失败";
}
try {
String result = stringRedisTemplate.opsForValue().get("goods:001");
int goodsNumber = result==null ? 0:Integer.parseInt(result);
if(goodsNumber > 0){
int realNUmber = goodsNumber - 1;
stringRedisTemplate.opsForValue().set("goods:001",String.valueOf(realNUmber));
System.out.println("成功买到商品,还剩下:"+realNUmber+"件库存"+"服务提供者是:"+serverPort);
return Thread.currentThread().getName()+"来光顾"+"成功买到商品,还剩下:"+realNUmber+"件库存"+"服务提供者是:"+serverPort;
}else {
System.out.println(Thread.currentThread().getName()+"来光顾 "+"卖完了啊,下次早点来啊"+"服务提供者是:"+serverPort);
}
return "卖完了啊,下次早点来啊"+"服务提供者是:"+serverPort;
} finally {
Jedis jedis = RedisUtils.getJedis();
String script ="if redis.call('get',KEYS[1]) == ARGV[1] " +
"then " +
"return redis.call('del',KEYS[1]) " +
"else " +
" return 0 " +
"end";
try {
Object eval = jedis.eval(script, Collections.singletonList(REDIS_LOCK), Collections.singletonList(value));
if("1".equalsIgnoreCase(eval.toString())){
System.out.println("-------del redis lock ok");
}
else {
System.out.println("-------del redis lock error");
}
}finally {
if(null != jedis){
jedis.close();
}
}
}
}
}
第三种:使用redisson加锁
@Bean
public Redisson getRedissonInstance(){
Config config = new Config();
config.useSingleServer().setAddress("redis://localhost:6379").setDatabase(0);
return (Redisson) Redisson.create(config);
}
package com.atguigu.bootredis01.controller;
import com.atguigu.bootredis01.util.RedisUtils;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@RestController
public class GoodConreoller {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Value("${server.port}")
private String serverPort;
private static final String REDIS_LOCK = "atguigu";
@Autowired
private Redisson redisson;
@GetMapping("/buy_goods")
public String buy_Goods() throws Exception {
RLock redissonLock = redisson.getLock(REDIS_LOCK);
redissonLock.lock();
try {
String result = stringRedisTemplate.opsForValue().get("goods:001");
int goodsNumber = result==null ? 0:Integer.parseInt(result);
if(goodsNumber > 0){
int realNUmber = goodsNumber - 1;
stringRedisTemplate.opsForValue().set("goods:001",String.valueOf(realNUmber));
System.out.println("成功买到商品,还剩下:"+realNUmber+"件库存"+"服务提供者是:"+serverPort);
return Thread.currentThread().getName()+"来光顾"+"成功买到商品,还剩下:"+realNUmber+"件库存"+"服务提供者是:"+serverPort;
}else {
System.out.println(Thread.currentThread().getName()+"来光顾 "+"卖完了啊,下次早点来啊"+"服务提供者是:"+serverPort);
}
return "卖完了啊,下次早点来啊"+"服务提供者是:"+serverPort;
} finally {
if (redissonLock.isLocked() && redissonLock.isHeldByCurrentThread())
{
redissonLock.unlock();
}
}
}
}