redis分布式锁(spring boot结合redis)
应用场景 : 例如一款手机只有10台的量秒杀,那么,在高并发的情况下,成千上万条数据更新数据库(例如10台的量被人抢一台就会在数据集某些记录下 减1),
那次这个时候的先后顺序是很乱的,很容易出现10台的量,抢到的人就不止10个这种严重的问题。
主要通过redis的 setnx 和getset来对方法加锁
测试方法 : 使用apache的ab命令压测 ab -n 500 -c 100 http://127.0.0.1/xxxx
-n 请求数量 -c 线程数量
1.引入相关jar包
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.配置application.yml
spring: redis: host: 192.168.12.39 #主机地址 port: 8001 #端口号 #password: 如果有密码就填写
3.代码实现
public class RedisLockService {
//过期时间 10s private static final int timeout = 10*1000; @Autowired private StringRedisTemplate stringRedisTemplate; /** * 加锁 * @param key * @param value 当前时间+ 过期时间 * @return */ public boolean lock(String key,String value){ //此方法就是调用setnx, 设置成功 if(stringRedisTemplate.opsForValue().setIfAbsent(key,value)){ return true; } //已存在,查看value是否过期 String currentValue = stringRedisTemplate.opsForValue().get(key); //过期时间 long time = timeout + System.currentTimeMillis() ; //获取时间小于(系统时间+过期时间),表示已过期 if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < time) { //返回旧值 ,设置新值 String oldValue = stringRedisTemplate.opsForValue().getAndSet(key,value); //这层判断防止两个进程同时进入,同时修改value值 if(!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue)){ return true; } } return false; } /** * 解锁 * @param key * @param value */ public void unLock(String key,String value){ try{ String currentValue = stringRedisTemplate.opsForValue().get(value); if(!StringUtils.isEmpty(currentValue)&& currentValue.equals(value)){ stringRedisTemplate.opsForValue().getOperations().delete(key); } }catch (Exception e){ log.error("redis分布锁解锁异常,"+e.getMessage()); } } }
4.使用方法
在需要上锁的地方调用加锁方法
@Autowired private RedisLockService redisLockService;
public void lockMethod(String key ,String value){ //1.拿锁 //没有拿到锁 if(!redisLockService.lock (key , value)){ throw new SellException(102,"人太多了,请换个姿势重试吧!"); } //2.执行加锁之后的逻辑 //3.解锁 redisLockService.unLock(key,value); }

浙公网安备 33010602011771号