首页 > 技术文章 > Redis分布式锁

honour1207 2021-02-21 16:02 原文

  提起来锁,可能第一个念头就是在想是不是要使用 synchronized。但是synchronized一般都是使用在一个服务器当中。

  当多个服务器的时候该如何使用,能否保证锁住的东西起作用吗?

  锁,很显而易见,就是需要排队去解决,开锁解锁。

一. 思考

  按照这个思路,那么分布式锁是不是也是一样,锁定某个东西,在另一个地方使用完成以后解开。在重新回归使用?只不过和synchronized区分的是单服务器和多服务器罢了

 

二. 开始进行测验

  首先先进行库存小项目分析

  1. 正常不加锁情况

·  

 1     /**
 2      * 测试Redis分布式锁
 3      */
 4     public void simulation(){
 5         //入库存20件
 6         redisTemplate.opsForValue().set(GOODS,20);
 7         /**
 8          * 模拟不同人数购买
 9          */
10         for (int i=0;i<20;i++){
11             //单数的测试
12             int amount = i%3+1;
13             new Thread(()->unlock(amount)).start();
14         }
15     }
16 
17 
18    public void unlock(int goodsStorage){
19         //获取线程名
20         String name = Thread.currentThread().getName();
21         //获取库存数量
22         Integer num = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(GOODS)));
23         //库存大于需求
24         if (num>=goodsStorage){
25             //剩余量
26             Long decrement = redisTemplate.opsForValue().decrement(GOODS, goodsStorage);
27             System.out.println(name+"购买后剩余--->"+decrement);
28         }else {
29             System.out.println(name+"库存不足,请稍后联系补货!");
30         }
31     }

 

出现卖超了的情况。

 

  2.单服务器情况下,增加synchronized

 1  public synchronized void unlock(int goodsStorage){
 2         //获取线程名
 3         String name = Thread.currentThread().getName();
 4         //获取库存数量
 5         Integer num = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(GOODS)));
 6         //库存大于需求
 7         if (num>=goodsStorage){
 8             //剩余量
 9             Long decrement = redisTemplate.opsForValue().decrement(GOODS, goodsStorage);
10             System.out.println(name+"购买后剩余--->"+decrement);
11         }else {
12             System.out.println(name+"库存不足,请稍后联系补货!");
13         }
14     }

发现货物并不会出现卖超出的情况发现,但是多个服务器上发现还是会出现问题

 

  3. 增加Redis分布式锁(在分布式情况下)

 1    public void plusLock(int goodsStorage){
 2         //线程名
 3         String name = Thread.currentThread().getName();
 4         //判断是否存在锁
 5         //这一步的问题是解决在设置完锁以后,在还没有设置过期时间之前而出现问题
 6         final Boolean redisLock =   redisTemplate.opsForValue().setIfAbsent(LOCK,name,3,TimeUnit.SECONDS);
 7         if (redisLock){
 8             //查看剩余多少库存
 9             int num = Integer.parseInt(String.valueOf(redisTemplate.opsForValue().get(GOODS)));
10             //库存大于购买
11             if (num>=goodsStorage){
12                 Long decrement = redisTemplate.opsForValue().decrement(GOODS, goodsStorage);
13                 System.out.println(name+"购买后剩余:"+decrement);
14             }else {
15                 System.out.println("不好意思,库存不足");
16             }
17             //释放锁
18             redisTemplate.delete(LOCK);
19         }else {
20             System.out.println("不好意思,请重新抢锁");
21         }
22     }

 

 

宁愿会有人没有买到,也不要库存超出,因为一般没有买到会出现重复点击

 

 

分布式锁个人理解 :

   从房东租客传递钥匙变成了物业统一帮租客管理钥匙。

  

 

推荐阅读