Redis的优惠券秒杀问题(七)在集群模式下的问题
Redis的优惠券秒杀问题(七)在集群模式下的问题
问题描述
我们在上一篇文章中提到过超卖问题、一人一单问题。
Redis的优惠券秒杀问题(六)超卖问题、一人一单问题_面向鸿蒙编程的博客-CSDN博客Redis的优惠券秒杀问题之超卖问题、一人一单问题!!!超卖问题是典型的多线程安全问题,针对这一问题的常见解决方案就是加锁!!!所以我们现在要研究是就是要加什么类型的锁?要怎么加锁?在哪里加锁?什么是一人一单问题?简单的来说就是模拟为了防止黄牛”屯“货而设计的,每一个用户ID,只能下一单!如下图,同一个用户下了很多单!!!这里使用”悲观锁"来实现!https://blog.csdn.net/weixin_43715214/article/details/127914721通过加锁可以解决在单机情况下的一人一单安全问题,但是在集群模式下就不行了!!!
伪集群模式搭建
(1)IDEA启动镜像
我们可以使用IDEA自带的镜像,启动多个实例,来模拟集群!
-Dserver.port=8082
然后将这两个实例都启动起来。
(2)修改nginx配置
再打开nginx的配置文件——nginx.conf
完整配置如下:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/json;
sendfile on;
keepalive_timeout 65;
server {
listen 8080;
server_name localhost;
# 指定前端项目所在的位置
location / {
root html/hmdp;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location /api {
default_type application/json;
#internal;
keepalive_timeout 30s;
keepalive_requests 1000;
#支持keep-alive
proxy_http_version 1.1;
rewrite /api(/.*) $1 break;
proxy_pass_request_headers on;
#more_clear_input_headers Accept-Encoding;
proxy_next_upstream error timeout;
# 打开集群模式
# proxy_pass http://127.0.0.1:8081;
proxy_pass http://backend;
}
}
# 打开集群模式 backend
upstream backend {
server 127.0.0.1:8081 max_fails=5 fail_timeout=10s weight=1;
server 127.0.0.1:8082 max_fails=5 fail_timeout=10s weight=1;
}
}
proxy_pass http://backend;
......
upstream backend {
server 127.0.0.1:8081 max_fails=5 fail_timeout=10s weight=1;
server 127.0.0.1:8082 max_fails=5 fail_timeout=10s weight=1;
}
重启nginx.exe
nginx.exe -s reload
(3)验证nginx是否启动成功
因为默认是采用轮询的模式,再刷新一下上面的网页,8081和8082都是看到日志信息
HmDianPingApplication1
HmDianPingApplication2
到这里,说明我们的模拟集群已经配置成功了!接下来就是复现这个BUG
BUG复现
(1)获取Token
先登入一下,从页面中拿到这个token(authorization)
我们在代码中打上一个断点,这段代码中是有加锁的!即如果是同一个用户ID是不能同时进来的!
(2)使用Postman 发请求
然后,将authorization配置到postman的请求头中,分别用两个postman实例去发送请求!
但是,在下面的两个实例中,显然同一个用户ID请求都进去了,就出现了锁“失效”的问题!
(3)锁“失效”发生
两个请求,分别进入到不同的IDEA实例中(8081、8082),但是这一块内容我们是上锁的!也就是说在集群模式下,JVM级别的synchronized锁是起不了作用的!
HmDianPingApplication1
HmDianPingApplication2
问题分析
JVM级别的synchronized锁失效
换而言之,就是系统部署在不同的服务器中,那它们的JVM是不一样的,而 synchronized 只能锁当前JVM中的线程,是不能操作其它JVM的!
解决思路
要解决这个问题,就必须要借助别的工具!——分布式锁就孕育而生!