首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

ZooKeeper系列(二)之商品秒杀

ZooKeeper系列(二)

商品秒杀

今天跟大家分享一个使用ZooKeeper锁服务(Lock Service)机制实现商品秒杀的一个生活案例。

一、ZooKeeper环境准备

准备三台服务器作为ZooKeeper(简称ZK)集群搭建环境,搭建方法参见我们之前分享的《ZooKeeper系列(一)之集群环境搭建》一文,各服务器信息如下:

在每台服务器上执行zkServer.sh start,启动ZK集群,执行zkServer.sh status命令,查看各节点运行状态,如图:

bigdata112:

bigdata113:

bigdata114:

我们看到113服务器作为ZK集群的leader,事实上,“领导者”是通过ZK的选举机制产生的。

二、商品秒杀代码实现

1、商品类Product

代码如下:

public classProduct {

//商品数量

private static intnum=100;

//秒杀商品

public static voidseckill(){

System.out.println("***************秒杀开始***************");

System.out.println("秒杀前商品余量:"+num);

//商品数减1

num--;

System.out.println("秒杀后商品余量:"+num);

try{

//模拟秒杀过程花费的时间

Thread.sleep(2000);

}catch(Exception e){

e.printStackTrace();

}

System.out.println("***************秒杀结束***************");

System.out.println();

}

}

Product类描述了我们要秒杀的商品,类中只有一个整型变量num和秒杀方法seckill,num表示库存中商品数量;seckill方法模拟了整个秒杀过程,秒杀成功,商品总量减1,这里我们使用线程沉睡来模拟秒杀过程花费的时间。

2、用户类Client

代码实现:

public classClient {

//开始秒杀

public voidstart() {

//重试策略

RetryPolicy rp =newExponentialBackoffRetry(1000,10);

//客户端

CuratorFramework client = CuratorFrameworkFactory.builder()

.connectString("192.168.189.112:2181,192.168.189.113:2181,192.168.189.114:2181").retryPolicy(rp).build();

client.start();

//分布式锁

finalInterProcessMutex lock =newInterProcessMutex(client,"/mylock");

//开始秒杀

try{

//获取分布式锁

lock.acquire();

//秒杀商品

Product.seckill();

}catch(Exception e) {

e.printStackTrace();

}finally{

try{

//释放分布式锁

lock.release();

}catch(Exception e) {

e.printStackTrace();

}

}

}

}

Client类模拟了用户秒杀行为,包括定义秒杀策略,创建客户端,实现分布式锁等,ExponentialBackoffRetry类描述了用户秒杀的策略:当用户秒杀失败时,每隔1秒重新秒杀,最多秒杀10次。

CuratorFrameworkFactory工厂类创建连接ZK服务器的客户端,并以秒杀策略连接ZK集群,连接字符串中配置了三台服务器的ZK地址和端口,主要是为了实现ZK集群的恢复性:当某个服务器因为某种原因出现单点故障,整个集群照样能够正常使用。

InterProcessMutex实现了分布式锁的定义,mylock是存储在ZK中的一个znode(z-节点),事先不用在ZK中创建,当ZK中没有该znode时会自动创建,事实上,ZK是一个树形结构的文件系统,每个znode节点即是文件又是目录,说是文件是指znode本身可以存储不超过1M的数据,目录是指znode下可以再创建新的znode作为子节点。

3、主类Main

代码如下:

public classTestDistributedLock {

public static voidmain(String[] args) {

//创建100个线程,模拟100个秒杀用户

for(inti=;i

newThread(newRunnable() {

public voidrun() {

newClient().start();

}

}).start();

}

}

}

主类非常简单,通过for循环创建了100个线程,而每个线程创建了一个用户。也就是说主类模拟了100用户秒杀商品。

我们执行程序,部分结果如下:

ZK的mylock节点下生成了100个节点,用于存储每个客户的数据,部分结果如图:

从运行结果看,每次只能有一个用户成功秒杀商品,我们可以停止任意一台服务器,因为当某台服务器被停止后,例如停止bigdata113(leader),ZK集群会从剩余的两台服务器中选举新的leader,继续接受客户端的write请求(这里就是秒杀)。事实上,在2n+1台ZK集群中,有n+1台服务器正常工作,ZK集群就能正常工作(我们这里是3台ZK集群,有2台服务器正常工作即可)。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180614G1E2JN00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券