分布式场景下的并发安全问题,收割快手,字节,百度,美团的Offer之旅
try {
lock.lock();
SimpleDateFormat simpt = new SimpleDateFormat(“yyyy-MM-dd-HH-mm-ss”);
String s = simpt.format(new Date()) + “-” + FileId.nextId();
return s;
}finally {
lock.unlock();
}
}
}
}
1.2. 启动2个tomcat
修改springboot配置文件application.properties
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bfQLzLOC-1638176020083)(/wps27.jpg)]
修改端口为8081
使用启动类分别启动8080,8081
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SoLpsa0h-1638176020098)(/wps28.jpg)]
1.3. 配置nginx访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SprhwIcW-1638176020099)(/wps29.jpg)]
1.4. **使用JMeter测试
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
**
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-haqspHt3-1638176020101)(/wps30.jpg)]
把测试结果排序后
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uhszGBBb-1638176020102)(/wps31.jpg)]
虽然单个节点解决了并发安全问题,但是在分布式场景下,依然出现了并发安全问题
2. 使用分布式锁解决
通过上面的案例使用JDK的锁解决不了分布式场景下的并发安全问题,接下来就考虑使用分布式锁来解决了。
2.1. 解决方案概述
分布式锁有很多种方案
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vw8oYcWs-1638176020103)(/wps32.jpg)]
这些方案可以使用一个设计模式来统一
2.2. 模板方法模式
2.2.1. 模板方法介绍
在父类中编排主流程,将步骤实现延迟到子类去实现。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U5kn9Fvg-1638176020105)(/wps33.jpg)]
上图网上购物的时候总体4个流程
-
清点商品
-
计算价格
-
支付(未知扩展)
-
送货上门
2.2.2. 代码实现
package cn.enjoy.template;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class AbstractTemplate {
public void shopping() {
Map<String,Float> cars = new HashMap();
cars.put(“电池”,10f);
cars.put(“娃娃”,20f);
cars.put(“打气筒”,30f);
//1.清点商品
checkGoods(cars);
//2计算价格
float mony = calculation(cars);
//3.支付
if(pay(mony)) {
//4.如果支付成功送货
delivery();
}
}
public void checkGoods(Map<String,Float> cars) {
if(cars!=null) {
System.out.print(“你购买的了:”);
for(String key:cars.keySet()) {
System.out.print(key+" ");
}
System.out.println();
}
}
public float calculation(Map<String,Float> cars) {
float result = 0;
if(cars!=null) {
for(String key:cars.keySet()) {
result += cars.get(key);
}
}
System.out.println(“你总共应该支付:”+result);
//钱
return result;
}
public abstract boolean pay(Float money) ;
public void delivery() {
System.out.println(“请稍等,小哥哥正在送货!”);
}
}
对于支付来说是【未知的扩展】因此它是个抽象的方法,如果想使用微信支付可以重现pay方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FAHpUV6i-1638176020106)(/wps34.jpg)]
2.3. 分布式锁的模板方法
2.3.1. 概览
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zL39UytC-1638176020107)(/wps35.jpg)]
1、定义锁的接口Lock
2、在AbstractLock模板锁里面实现getLock方法,实现通用的逻辑。
3、不能确实的步骤,作为虚拟方法,甩锅给子类实现。
4、子类只需要聚焦自己的小步骤逻辑,实现tryLock,waitLock,unLock方法
2.3.2. 代码实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PiRRtQaX-1638176020107)(/wps36.jpg)]
实现tryLock,waitLock,与Lock接口的unLock方法
2.4. MySql实现方式
2.4.1. 实现思路
利用数据库自身提供的锁机制实现,要求数据库支持行级锁;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cmU7VTGD-1638176020108)(/wps37.jpg)]
2.4.2. 实现流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ft5S7omI-1638176020108)(/wps38.jpg)]
转存中…(img-PiRRtQaX-1638176020107)]
实现tryLock,waitLock,与Lock接口的unLock方法
2.4. MySql实现方式
2.4.1. 实现思路
利用数据库自身提供的锁机制实现,要求数据库支持行级锁;
[外链图片转存中…(img-cmU7VTGD-1638176020108)]
2.4.2. 实现流程
[外链图片转存中…(img-ft5S7omI-1638176020108)]
分布式场景下的并发安全问题,收割快手,字节,百度,美团的Offer之旅
try {
lock.lock();
SimpleDateFormat simpt = new SimpleDateFormat(“yyyy-MM-dd-HH-mm-ss”);
String s = simpt.format(new Date()) + “-” + FileId.nextId();
return s;
}finally {
lock.unlock();
}
}
}
}
1.2. 启动2个tomcat
修改springboot配置文件application.properties
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bfQLzLOC-1638176020083)(/wps27.jpg)]
修改端口为8081
使用启动类分别启动8080,8081
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SoLpsa0h-1638176020098)(/wps28.jpg)]
1.3. 配置nginx访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SprhwIcW-1638176020099)(/wps29.jpg)]
1.4. **使用JMeter测试
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
**
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-haqspHt3-1638176020101)(/wps30.jpg)]
把测试结果排序后
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uhszGBBb-1638176020102)(/wps31.jpg)]
虽然单个节点解决了并发安全问题,但是在分布式场景下,依然出现了并发安全问题
2. 使用分布式锁解决
通过上面的案例使用JDK的锁解决不了分布式场景下的并发安全问题,接下来就考虑使用分布式锁来解决了。
2.1. 解决方案概述
分布式锁有很多种方案
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vw8oYcWs-1638176020103)(/wps32.jpg)]
这些方案可以使用一个设计模式来统一
2.2. 模板方法模式
2.2.1. 模板方法介绍
在父类中编排主流程,将步骤实现延迟到子类去实现。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U5kn9Fvg-1638176020105)(/wps33.jpg)]
上图网上购物的时候总体4个流程
-
清点商品
-
计算价格
-
支付(未知扩展)
-
送货上门
2.2.2. 代码实现
package cn.enjoy.template;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class AbstractTemplate {
public void shopping() {
Map<String,Float> cars = new HashMap();
cars.put(“电池”,10f);
cars.put(“娃娃”,20f);
cars.put(“打气筒”,30f);
//1.清点商品
checkGoods(cars);
//2计算价格
float mony = calculation(cars);
//3.支付
if(pay(mony)) {
//4.如果支付成功送货
delivery();
}
}
public void checkGoods(Map<String,Float> cars) {
if(cars!=null) {
System.out.print(“你购买的了:”);
for(String key:cars.keySet()) {
System.out.print(key+" ");
}
System.out.println();
}
}
public float calculation(Map<String,Float> cars) {
float result = 0;
if(cars!=null) {
for(String key:cars.keySet()) {
result += cars.get(key);
}
}
System.out.println(“你总共应该支付:”+result);
//钱
return result;
}
public abstract boolean pay(Float money) ;
public void delivery() {
System.out.println(“请稍等,小哥哥正在送货!”);
}
}
对于支付来说是【未知的扩展】因此它是个抽象的方法,如果想使用微信支付可以重现pay方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FAHpUV6i-1638176020106)(/wps34.jpg)]
2.3. 分布式锁的模板方法
2.3.1. 概览
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zL39UytC-1638176020107)(/wps35.jpg)]
1、定义锁的接口Lock
2、在AbstractLock模板锁里面实现getLock方法,实现通用的逻辑。
3、不能确实的步骤,作为虚拟方法,甩锅给子类实现。
4、子类只需要聚焦自己的小步骤逻辑,实现tryLock,waitLock,unLock方法
2.3.2. 代码实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PiRRtQaX-1638176020107)(/wps36.jpg)]
实现tryLock,waitLock,与Lock接口的unLock方法
2.4. MySql实现方式
2.4.1. 实现思路
利用数据库自身提供的锁机制实现,要求数据库支持行级锁;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cmU7VTGD-1638176020108)(/wps37.jpg)]
2.4.2. 实现流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ft5S7omI-1638176020108)(/wps38.jpg)]
转存中…(img-PiRRtQaX-1638176020107)]
实现tryLock,waitLock,与Lock接口的unLock方法
2.4. MySql实现方式
2.4.1. 实现思路
利用数据库自身提供的锁机制实现,要求数据库支持行级锁;
[外链图片转存中…(img-cmU7VTGD-1638176020108)]
2.4.2. 实现流程
[外链图片转存中…(img-ft5S7omI-1638176020108)]