Redis实战13-集群下线程并发安全问题

  • 作者: 凯哥Java(公众号:凯哥Java)
  • Redis
  • 时间:2023-04-02 19:09
  • 3140人已阅读
简介 通过前面两篇(Redis实战11-实现优惠券秒杀下单 Redis实战12-优惠券实现一人一单功能)的学习,我们已经解决了单机情况下优惠券秒杀及一人一单功能。其中,在优惠券秒杀时候,使用到了乐观锁处理的,在一人一单功能时候,使用了悲观锁,synchronized关键字及处理了spring事务失效情况。但是随着业务的增长,单机服务已经不能满足我们需求了,这个时候,需要多台机器来支撑。这就构成

🔔🔔好消息!好消息!🔔🔔

 如果您需要注册ChatGPT,想要升级ChatGPT4。凯哥可以代注册ChatGPT账号代升级ChatGPT4

有需要的朋友👉:微信号 kaigejava2022

通过前面两篇(Redis实战11-实现优惠券秒杀下单  Redis实战12-优惠券实现一人一单功能)的学习,我们已经解决了单机情况下优惠券秒杀及一人一单功能。其中,在优惠券秒杀时候,使用到了乐观锁处理的,在一人一单功能时候,使用了悲观锁,synchronized关键字及处理了spring事务失效情况。但是随着业务的增长,单机服务已经不能满足我们需求了,这个时候,需要多台机器来支撑。这就构成了集群,那么在集群模式下,我们再来测试我们的优惠券秒杀及一人一单情况。

从本篇文章开始,咱们就来学学Redis实现分布式锁。预计使用七个篇幅来讲解。在讲解完之后,我们使用5个篇幅讲讲Redisson实现分布锁的。如下图:

b60b4fa9ff94b023005371324ef894f9.png

1:我们将服务器启动两份,端口分别是8081和8082

在idea中,找到启动的项目,running,然后ctrl+D.如下图:

390633c5654342e8901d6ec406ac422f.png

如果在没有这个。按照如下方法:

1.点击菜单栏:Views -> Tool Windows -> Services;快捷键:Alt+8.如下图:

2.刚创建好的窗口是空白的,需要我们把服务加进去。

具体看在凯哥个人博客网站上搜索:《【经验:图文教程】IDEA开启并配置services窗口,观察启动模块的端口并方便操作.》和《【经验】在Idea中怎么一个spring boot服务怎么模拟多台实例部署》查看这两篇文章。

修改完端口之后,启动服务就能看到如下:启动了两个服务,端口分别是8081和8082

4413e3277b2cf5cae83473a43dbfdb02.png

2:修改nginx的conf目录下nginx.conf文件,配置反向代理和负载均衡:

我们先来看看,当前nginx.conf配置文件的内容:

80fff925b9e92def60985d3d68bdb9ee.png

从上图中,我们可以看到,访问api的时候,反向代理是8081.我们修改方向代理为8082和8081

tianj upstream backend如下图:

e979bcdbc9eacb38e2e04b6d8178de28.png

添加完之后,修改api的proxy_pass。如下图:

b652e1f1d6417ac1184c2134bff046ec.png

修改完成之后,我们重启Nginx。在Nginx的目录下,使用nginx.exe -s reload命令重启。如下图:

7273cea036355c6a3428e418a5a4297c.png

测试Nginx是否负载均衡生效。

请看idea中8081和8082的日志,然后访问我们的前端页面,我们会发现,8081和8082的日志轮询的打印。说明Nginx负载均衡生效了。

我们来测试集群模式下,线程并发安全问题

我们在8081服务中,同步代码块打上断点,8082的服务不变。我们来测试同一个用户,在集群下是否会出现一人多单的情况。我们用postman进行测试:

65eec6d00c5eb006220c27afe0ad158c.png

访问完成之后,查看数据库中库存情况:

021043d09b74d4e47525d1234a102b95.png

订单情况:

1c701240926ae41ef103e069834453d7.png

经过测试后的答案是肯定会出现一人多单的情况。为什么呢?我们来分析分析。

单机或者同一个JVM中,时序图如下:

c9499995550631ec9346686e2b252f14.png

当是集群的时候,是多个JVM进程了。这个时候,集群下时序图:

bdc73dbba6232b25aecd0fe050f0ddfb.png

因为,我们使用的synchronized关键字实现的锁,是JVM级别的。现在是集群环境下,已经跨JVM进程了,synchronized锁已经锁不住了。

那么怎么解决呢?在下一篇中,咱们就来讲讲分布式锁。

凯哥推荐Redis实现分布式锁系列文章:

《Redis实战11-实现优惠券秒杀下单》

《Redis实战12-优惠券实现一人一单功能》

《Redis实战13-集群下线程并发安全问题》

或者到凯哥个人博客(聪明的你,从结束语中应该能知道地址)查看Redis系列教程

结束语

大家好,我是凯哥Java(kaigejava),乐于分享技术文章,欢迎大家关注“凯哥Java”,及时了解更多。让我们一起学Java。也欢迎大家有事没事就来和凯哥聊聊~~~





TopTop