redis实现分布式锁
只是做个简单的demo测试使用(核心代码)
/** * 单体架构,没有添加锁(可以使用Synchronization实现单体架构同步代码块) * */ @RequestMapping("/getVlaue") public String getVlaue(){ // redisTemplate.opsForValue().set("num","100"); int num = Integer.parseInt(redisTemplate.opsForValue().get("num")); if(num>0){ num = num -1; redisTemplate.opsForValue().set("num",zs+""); }else{ System.out.println("库存不足"); } System.out.println(redisTemplate.opsForValue().get("num")); return redisTemplate.opsForValue().get("num"); }
使用redis
//redis实现(存在两个问题 // 1.高并发的情况下,如果两个线程同时进入循环,可能导致加锁失败。 // 2.SETNX 是一个耗时操作,因为它需要判断 Key 是否存在,因为会存在性能问题。) @RequestMapping("/getRedis") public String getRedis(){ String lock ="lock"; //为了避免本线程删除其他线程的锁,为每个线程的锁设置唯一的指 String clientId = UUID.randomUUID().toString(); try { // //1.获取锁 // redisTemplate.opsForValue().set(lock,clientId); // //2.设置过期时间 // redisTemplate.expire(lock,10,TimeUnit.SECONDS); //为保证程序的原子性,把1 2两步合并 Boolean result = redisTemplate.opsForValue().setIfAbsent(lock,clientId,10,TimeUnit.SECONDS); if(!result){ System.out.println("error"); return "error"; } int num = Integer.parseInt(redisTemplate.opsForValue().get("num")); if(num > 0){ num = num -1;// redisTemplate.opsForValue().set("num",num+""); System.out.println("剩余"+num); }else{ System.out.println("库存不足"); } }finally { //只有值为本线程的值时才释放锁 if(clientId.equals(redisTemplate.opsForValue().get("lock"))){ redisTemplate.delete(lock); } } return redisTemplate.opsForValue().get("num"); }
使用redisson,简单实用
//合适解决方案 @RequestMapping("/getRedisson") public String getRedisson(){ String lockKey = "lock"; String clientId = UUID.randomUUID().toString(); //获取锁 RLock lock =redisson.getLock(lockKey); try { //加锁 lock.lock(30,TimeUnit.SECONDS); int num = Integer.parseInt(redisTemplate.opsForValue().get("num")); if(num>0){ num = num -1; redisTemplate.opsForValue().set("num",num+""); System.out.println("剩余"+num); }else{ System.out.println("库存不足"); } }finally { //释放锁 lock.unlock(); } return redisTemplate.opsForValue().get("num"); }
使用jMeter测试