基于Zookeeper与Redis进行分布式锁的代码实现

  • 时间:
  • 来源:互联网
  • 文章标签:

一.分布式锁介绍

由于传统的锁是基于Tomcat服务器内部的,搭建了集群之后,导致锁失效,应该使用分布式锁来处理。

二.分布式锁解决方案

我们要想实现分布式锁,可以使用两种方案:

  • 1.基于Zookeeper;
  • 2.基于Redis。

下面我分别就两种方案进行代码实现讲解。

先展示一段未加锁时的秒杀需求

创建SpringBoot项目,编写抢购的业务。

@RestController
public class SecondKillController {

    //1. 准备商品的库存
    public static Map<String,Integer> itemStock = new HashMap<>();

    //2. 准备商品的订单
    public static Map<String,Integer> itemOrder = new HashMap<>();

    static{
        itemStock.put("牙刷",10000);
        itemOrder.put("牙刷",0);
    }

    @GetMapping("/kill")
    public String kill(String item) throws InterruptedException {
    
        //1. 减库存
        Integer stock = itemStock.get(item);
        if(stock <= 0){
            return "商品库存数不足!!!";
        }
        
        Thread.sleep(100);
        itemStock.put(item,stock - 1);
        
        //2. 创建订单
        Thread.sleep(100);
        itemOrder.put(item,itemOrder.get(item) + 1);

        //3. 返回信息
        return "抢购成功!!!" + item + ": 剩余库存数为 - " + itemStock.get(item) + ",订单数为 - " + itemOrder.get(item);
    }
}

下载ab进行压力测试

ab -n 请求数 -c 并发数 访问的路径

进行压力测试的结果展示:

会发现在进行并发操作时存在数量不一致的问题!出现了超卖的现象。

三.基于Zookeeper实现分布式锁

1. 创建项目,添加依赖

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.6.0</version>
    <exclusions>
        <exclusion>
            <artifactId>slf4j-api</artifactId>
            <groupId>org.slf4j</groupId>
        </exclusion>
        <exclusion>
            <artifactId>slf4j-log4j12</artifactId>
            <groupId>org.slf4j</groupId>
        </exclusion>
        <exclusion>
            <artifactId>log4j</artifactId>
            <groupId>log4j</groupId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-recipes</artifactId>
    <version>4.0.1</version>
    <exclusions>
        <exclusion>
            <artifactId>slf4j-api</artifactId>
            <groupId>org.slf4j</groupId>
        </exclusion>
    </exclusions>
</dependency>

2. 编写配置类

@Configuration
public class ZkConfig {

    @Bean
    public CuratorFramework cf(){

        RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000,2);

        CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
                .connectString("192.168.199.109:2181,192.168.199.109:2182,192.168.199.109:2183")
                .retryPolicy(retryPolicy)
                .build();

        curatorFramework.start();

        return curatorFramework;
    }

}

3. 在业务代码中添加分布式锁

InterProcessMutex lock = new InterProcessMutex(cf,"/lock");

//...加锁
lock.acquire();
lock.acquire(1,TimeUnit.SECONDS); // 指定排队多久就放弃获取锁资源

//----------------业务逻辑代码------------------------

// 释放锁
lock.release();

4. 进行ab压力测试

   可以发现并发抢购时不会出现超卖现象,卖出的商品与剩余商品的数量完全对应,保证了抢购时的数据一致性!

四.基于Redis实现分布式锁

1.创建springboot项目,添加依赖包

# redis依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.编写yml配置文件

# 配置文件
spring:
  redis:
    host: 192.168.199.109
    port: 6379

3.编写工具类

@Component
public class RedisLockUtil {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public boolean lock(String key,String value,int second){
        return redisTemplate.opsForValue().setIfAbsent(key,value,second,TimeUnit.SECONDS);
    }

    public void unlock(String key){
        redisTemplate.delete(key);
    }

}

4.修改业务逻辑代码

@GetMapping("/redis/kill")
public String redisKill(String item) throws Exception {
    //...加锁
    if(lock.lock(item,System.currentTimeMillis() + "",1)){
        // 业务代码。。。
        // 释放锁
        lock.unlock(item);
    }
}

5.进行ab压力测试

  会发现也可以解决抢购时的超卖问题。

一一哥Sun CSDN认证博客专家 Elasticsearch Java 架构
十年软件开发授课经验,专注大学生毕业设计及面试求职私塾式指导!对Android/JavaWeb/微服务/H5等技术领域有深入研究!曾任国内最大的智能物联网平台架构师,参与国内最大的智能物流系统平台天眼/冷链/订单/车次系统研发;曾主导国内首款国学教育App及后台架构;负责大庆油田采油管理系统,铝业云计算系统,湖南广电地面波机顶盒等项目的研发。目前担任某著名培训机构教学主管,培养了大批入职阿里,IBM,百度,国家电网等名企的高薪学生.本人坚持只有一心做教育,才能做一流教育的理念,被学生爱称为"一一哥"!QQ:2312119590,今日头条号:一一哥Sun;知乎ID:一一哥

本文链接http://www.taodudu.cc/news/show-1781852.html