首页 > 数据库 >基于Zookeeper与Redis进行分布式锁的代码实现

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

时间:2022-12-23 14:34:16浏览次数:45  
标签:String lock Zookeeper Redis item org public 分布式


一.分布式锁介绍

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

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

二.分布式锁解决方案

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

  • 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与Redis进行分布式锁的代码实现_分布式锁_02

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

三.基于Zookeeper实现分布式锁

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

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实现分布式锁

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

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压力测试

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

标签:String,lock,Zookeeper,Redis,item,org,public,分布式
From: https://blog.51cto.com/u_7044146/5965623

相关文章

  • 分布式调度zookeeper、单机版、伪分布式、完全分布式
    分布式调度——zookeeper一、 为什么需要zookeeperl 大部分分布式应用需要一个主控、协调器或控制器来管理物理分布的子进程(如资源、任务分配等)l 大部分应用需要开发私......
  • laas、paas、saas、单体应用、微服务、分布式、soa架构、微服务实战、rpc、CAP 定理、
    一IaaS基础设施服务IaaS:Infrastructure-as-a-Service(基础设施即服务)第一层叫做IaaS,有时候也叫做Hardware-as-a-Service,几年前如果你想在办公室或者公司的网站上运行一些......
  • redis hset 哈希表操作添加json串为单引号且客户端窗口需要最大化,字符串不能断行
    redishset哈希表操作添加json串为单引号且客户端窗口需要最大化,字符串不能断行语法:1.HGETkeyfield获取存储在哈希表中指定字段的值。DEMO:单个查询hget"微服务名称:......
  • redis-参数配置之内存大小设置规则
    redis的配置文件一般是redis.conf,位于/etc目录下。关于配置里面的一些大小设置规则,比如最大内存,记录如下。设置最大内存注意:大小写不敏感,1GB1Gb1gB都一样#1k=>100......
  • 使用Redission实现抢红包
    业务描述:发起红包,规定好总金额100,红包个数10。发完红包后,1秒钟内100个人同时抢。需要注意的点:1.数据库瞬时压力过大,需采用缓存;2.线程并发进行,避免超卖;处理:使用redis配......
  • redis持久化
    1)RDB默认方式: AOF方式:  3)对比rdb的优点:高性能的持久化实现----创建一个子进程来执行持久化,先将数据写入临时文件,持久化过程结束后,再用这个临时文件替换......
  • redis 初探
    redis(端口6379)单线程基于内存操作很快cpu不是瓶颈是内存和带宽C语言写的使用redis-server--service-installredis.windows.conf--loglevelverboseselect3......
  • redis c++接口
    redis接口redis是c语言写的,有c接口,无c++接口。在一个负载均衡服务器项目中,用过一个redis的c++接口类。简单粗暴上代码吧,需要的自行移植一下。/**redis_interface.cpp*Aut......
  • Redis集群的三种方式详解(附优缺点及原理区别)
    Redis提供了三种集群方式,下面我重点详解Redis三种集群方式的原理及优缺点等区别@mikechen目录Redis主从复制模式Redis哨兵模式Redis集群模式Redis主从复制模式......
  • 刨根问底 Redis, 面试过程真好使(缓存穿透,缓存击穿,缓存雪崩等)
      在Web应用发展的初期阶段,一个网站的访问量本身就不是很高,直接使用关系型数据库就可以应付绝大部分场景。但是随着互联网时代的崛起,人们对于网站访问速度有着越来......