使用Redisson和Zookeeper实现分布式锁模拟模拟抢红包业务

使用Redisson和Zookeeper实现分布式锁模拟模拟抢红包业务

业务场景

模拟1000人在10秒内抢10000(或1000)元红包,金额在1-100不等;

使用的框架或软件:

  • Springboot(基础框架)
  • Redisson(实现分布式锁)
  • Zookeeper(实现分布式锁方案)
  • Ngnix(负载均衡)
  • Redis(红包数据存取数据库)

系统或软件:

  • Linux服务器
  • Jmeter(模拟并发请求)

Jmeter 下载和运行

官方网站:http://jmeter.apache.org/

解压后, 运行 “bin/jmeter.bat”

Jmeter 是支持中文的, 启动Jmeter 后, 点击 Options -> Choose Language 来选择语言

测试需求

以获取城市的天气数据为例

第一步: 获取城市的城市代号

发送request到http://toy1.weather.com.cn/search?cityname=上海

从这个请求的 response 中获取到上海的城市代码. 比如:

上海的地区代码是101020100

上海动物园的地区代码是: 10102010016A

第二步: 得到该城市的天气数据

发送request 到: http://www.weather.com.cn/weather2d/101020100.shtml

测试步骤

步骤一: 新建一个Thread Group

必须新建一个Thread Group, jmeter的所有任务都必须由线程处理,所有任务都必须在线程组下面创建。

img

第二步:新建一个 HTTP Request

img

比如我要发送一个Get 方法的http 请求: http://toy1.weather.com.cn/search?cityname=上海

可以按照下图这么填

img

第三步 添加HTTP Head Manager

选中上一步新建的HTTP request. 右键,新建一个Http Header manager. 添加一个header

img

img

第四步: 添加View Results Tree

View Results Tree 是用来看运行的结果的

img

第五步:运行测试,查看结果

img

img

模拟抢红包业务开发

情况1 – 单机服务——没有任何线程安全考虑

输出数据有异常:

情况2 – 单机服务, 使用Lock锁

Lock在单服务器是线程安全的, 此时输出数据正常:

情况3.1 – 两台服务器, 使用Lock锁

数据异常(代码情况2一样);

Lock在镀钛服务器下是非线程安全的

负载均衡配置

使用Nginx配置负载均衡,部署两个服务分别是8001和8002端口,Nginx暴露8080端口,转发请求到8001和8002;

img

nginx配置

情况3.2 – 两台服务器 使用Redisson分布式锁

情况3.3 – 两台服务器——使用Zookeeper分布式锁——数据正常

附录

1- 其他配置和类

application.properties文件

ReturnModel 类

SeckillController类

流程解析

Zookeeper分布锁

1- 在ZkConfiguration类中加载CuratorFramework时,设置参数,实例化一个CuratorFramework类; 实例化过程中,执行CuratorFrameworkImpl类中的的start(),其中CuratorFrameworkImpl类是CuratorFramework的实现类;根据具体的细节可以参考博客

2- 在ZkConfiguration类中加载DistributedLockByZookeeper时;执行其中的init()方法;init()方法中主要是创建父节点和添加监听

3- 在具体业务中调用distributedLockByZookeeper.acquireDistributedLock(PATH);获取分布式锁

4- 业务结束时调用distributedLockByZookeeper.releaseDistributedLock(PATH);释放锁

原理图如下

img

期间碰到的问题

问题: 项目启动时:java.lang.ClassNotFoundException: com.google.common.base.Function

原因:缺少google-collections jar包;如下

问题:项目启动时:org.apache.curator.CuratorConnectionLossException: KeeperErrorCode = ConnectionLoss

原因:简单说,就是连接失败(可能原因的有很多);依次排查了zookeeper服务器防火墙、application.properties配置文件;最后发现IP的写错了,更正后就好了

问题:Jemter启用多线程并发测试时:java.net.BindException: Address already in use: connect.

Views: 509

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注