一、前言
在分布式环境下,传统的一些技术会失败,比如传统的synchronized或者lock锁,以及创建数据库的事务,无法保证ACID,还有定时任务也可能会出现重复执行的问题。
二、分布式锁介绍
由于传统的锁是基于Tomcat服务器内部的,搭建了集群之后,导致锁失效,使用分布式锁来处理。
三、分布式锁解决方案【重点】
3.1 搭建环境
创建SpringBoot
编写抢购的业务
@RestControllerpublic class SecondKillController//1. 准备商品的库存public static Map‹String, Integer> itemStock = new HashMap<>0):1/2.准备商品的订单public static Map«String, Integer> itemOrder = new HashMape>();static{itemStock.put("FRI",10000):itemOrder.put("#B)",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);return "抢购成功!!!" + item + ": 剩余库存数为 - " + itemStock.get (item) + ", 订单数为 - " + itemOrder.get(item);}}
下载ab压力测试
ab -n请求数 一。并发数 访问的路径
测试结果
3.2 zookeeper实现分布式锁原理
3.3 Zookeeper实现分布式锁
导入依赖
<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></exclusions><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>orq.slf4j</groupId></exclusion></exclusions></dependency>
编写配置类
@Configurationpublic class ZkConfig{@Beanpublic 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).buildO;curatorFramework.start();return curatorFramework;}}
在业务代码中添加分布式锁
@Autowiredprivate CuratorFramework cf;InterProcessMutex lock = new InterProcessMutex(cf,"/lock") ;//...加锁lock.acquire();lock .acquire(1,TimeUnit.SECONDS);//指定排队多久就放奔获取锁资源//-----------业务逻辊代码-----------//释放锁lock.release();
3.4 Redis实现分布式锁原理
3.5Redis实现分布式锁
导入依赖,添加配置文件
# redis依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency># 配置文件spring:redis:host: 192.168.199.109port: 6379
编号工具类
@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);
}
}
修改业务逻辑代码
@GetMapping("/redis/kill")
public String redisKill(String item) throws Exception (
//...加锁
if(lock.lock (item, System.currentTimeMillis0) +"",1)){
//业务代码 .....
//释放锁
lock.unlock(itme);
}
}
再测试
