仓库地址:https://gitee.com/J_look/ssm-zookeeper/blob/master/README.md
实现分布式锁的大致流程
整体思路
安装nginx运行所需的库
bash
//一键安装上面四个依赖
yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel
下载nginx
在那个目录下执行这个命令 就会下载到哪个目录下
bash
//下载tar包
wget http://nginx.org/download/nginx-1.13.7.tar.gz
解压
注意哦 解压出来的文件 我们还需要安装哦
下面所有的命令 都是在nginx-1.13.7文件夹里面进行哦
highlighter-
tar -zxvf nginx-1.13.7.tar.gz
安装
创建一个文件夹,也就是nginx需要安装到的位置
bash
mkdir /usr/local/nginx
执行命令 考虑到后续安装ssl证书 添加两个模块
bash
./configure --with-http_stub_status_module --with-http_ssl_module
执行make install命令
bash
make install
启动nginx服务
我这个是在/ 目录底下执行的 你们可以根据 自己所在的目录去执行
bash
/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
访问nginx
nginx的默认端口是80
我们所做的配置大概就是
当有人请求去访问我们服务器,然后负载到我们处理请求的服务器 我这里是为了方便 处理请求的这两台服务器 是在我Windows上
打开配置文件
bash
# 打开配置文件
vim /usr/local/nginx/conf/nginx.conf
xml
upstream look{
server 192.168.204.1:8001; //192.168.204.1是我本机的ip地址,8001是tomcat的端口号
server 192.168.204.1:8002; //8002是另外一个工程的tomcat端口号
}
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass http://look;
root html;
index index.html index.htm;
}
搭建ssm框架 有时间推出springboot的版本
sql
-- 商品表
create table product(
id int primary key auto_increment, -- 商品编号
product_name varchar(20) not null, -- 商品名称
stock int not null, -- 库存
version int not null -- 版本
)
insert into product (product_name,stock,version) values('锦鲤-清空购物车-大奖',5,0)
sql
-- 订单表
create table `order`(
id varchar(100) primary key, -- 订单编号
pid int not null, -- 商品编号
userid int not null -- 用户编号
)
简单解释一下build
我们引入的是tomcat7的插件configuration 配置的是端口 和根目录注意哦 记得刷新pom文件 build里面会有爆红 不要紧张 不用管他 后面的配置他会自己消失
xml
8
8
UTF-8
5.2.7.RELEASE
war
org.springframework
spring-context
${spring.version}
org.springframework
spring-beans
${spring.version}
org.springframework
spring-webmvc
${spring.version}
org.springframework
spring-jdbc
${spring.version}
org.mybatis
mybatis
3.5.10
org.mybatis
mybatis-spring
2.0.7
com.alibaba
druid
1.2.11
mysql
mysql-connector-java
8.0.29
junit
junit
4.13.2
test
org.projectlombok
lombok
1.18.24
org.apache.tomcat.maven
tomcat7-maven-plugin
8002
/
package
run
折叠
注意哦 :仔细查看上面的项目结构 创建相应的文件夹
xml
<?xml version="1.0" encoding="UTF-8" ?>
注意哦 :仔细查看上面的项目结构 创建相应的文件夹
xml
<?xml version="1.0" encoding="UTF-8"?>
折叠
注意哦 :仔细查看上面的项目结构 创建相应的文件夹
这里也会出现爆红,后面会自己消失
xml
<?xml version="1.0" encoding="UTF-8"?>
springMVC
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring/spring.xml
1
true
springMVC
/
Product
java
/**
* @author : look-word
* 2022-07-17 10:12
**/
@Data
public class Product implements Serializable {
private Integer id;
private String product_name;
private Integer stock;
private Integer version;
}
Order
highlighter- PHP
/**
* @author : look-word
* 2022-07-17 10:12
**/
@Data
public class Order implements Serializable {
private String id;
private Integer pid;
private Integer userid;
}
ProductMapper
java
@Mapper
@Component
public interface ProductMapper {
// 查询商品(目的查库存)
@Select("select * from product where id = #{id}")
Product getProduct(@Param("id") int id);
// 减库存
@Update("update product set stock = stock-1 where id = #{id}")
int reduceStock(@Param("id") int id);
}
OrderMapper
java
@Mapper
@Component
public interface OrderMapper {
// 生成订单
@Insert("insert into `order` (id,pid,userid) values (#{id},#{pid},#{userid})")
int insert(Order order);
}
ProductService
java
/**
* @author : look-word
* 2022-07-17 10:28
**/
public interface ProductService {
// 扣除库存
void reduceStock(Integer id) throws Exception;
}
ProductServiceImpl
java
/**
* @author : look-word
* 2022-07-17 10:29
**/
@Transactional
@Service
public class ProductServiceImpl implements ProductService {
@Resource
private ProductMapper productMapper;
@Resource
private OrderMapper orderMapper;
@Override
public void reduceStock(Integer id) throws Exception {
// 查询商品库存
Product product = productMapper.getProduct(id);
if (product.getStock() <= 0) {
throw new RuntimeException("库存不足");
}
// 减库存
int i = productMapper.reduceStock(id);
if (i == 1) {
Order order = new Order();
order.setId(UUID.randomUUID().toString());
order.setUserid(1);
order.setPid(id);
Thread.sleep(500);
orderMapper.insert(order);
} else {
throw new RuntimeException("扣除库存失败");
}
}
}
java
/**
* @author : look-word
* 2022-07-17 10:12
**/
@RestController
public class ProductAction {
@Resource
private ProductService productService;
@GetMapping("product/reduce/{id}")
private Object reduce(@PathVariable Integer id) throws Exception {
productService.reduceStock(id);
return "ok";
}
}
还记得我们在pom.xml配置的tomcat的插件吗,我们配置的意思是打包(package)之后会自动运行
在执行打包命令之前,先执行clean命令
执行package命令
测试
highlighter- Go
http://localhost:8001/product/reduce/1
访问流程
**注意**
在使用jmeter测试的时候 需要启动两个服务
简单阐述一下:我们会模拟高并发场景下对这个商品的库存进行扣减
这也就会导致一个问题,会出现商品超卖(出现负的库存)出现的原因: 在同一时间,访问的请求很多。
下载地址
解压双击jmeter.bat启动
创建线程组
这里的线程数量根据自己电脑去设置
创建请求
我们填写红框的内容即可就是访问的地址
配置好这些之后,点击菜单栏绿色启动标志
去数据库查看
需要用到 zookeeper集群,搭建的文章
zookeeper分布式锁不需要我们手写去实现,有封装好的依赖,引入即可
xml
org.apache.curator
curator-recipes
4.2.0
在控制层中加入分布式锁的逻辑代码
java
/**
* @author : look-word
* 2022-07-17 10:12
**/
@RestController
public class ProductAction {
@Resource
private ProductService productService;
// 集群ip
private String connectString = "192.168.77.132,192.168.77.131,192.168.77.130";
@GetMapping("product/reduce/{id}")
private Object reduce(@PathVariable Integer id) throws Exception {
// 重试策略 (1000毫秒试1次,最多试3次)
RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
//1.创建curator工具对象
CuratorFramework client = CuratorFrameworkFactory.newClient(connectString, retryPolicy);
client.start();
//2.根据工具对象创建“内部互斥锁”
InterProcessMutex lock = new InterProcessMutex(client, "/product_" + id);
try {
//3.加锁
lock.acquire();
productService.reduceStock(id);
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw e;
}
} finally {
//4.释放锁
lock.release();
}
return "ok";
}
}
启动jmeter去测试,会发现,请求就像排队一样,一个一个出现,数据库也没有超卖现象
springboot版本后续会退出
原文链接:https://www.cnblogs.com/look-word/p/16488623.html
留言与评论(共有 0 条评论) “” |