zookeeper案例-分布式锁-商品秒杀原理解析

锁:我们在多线程中接触过,作用就是让当前的资源不会被其他线程访问! 我的日记本,不可以被别人看到。所以要锁在保险柜中

当我打开锁,将日记本拿走了,别人才能使用这个保险柜

zookeeper中使用传统的锁引发的 羊群效应1000个人创建节点,只有一个人能成功,999 人需要等待!

羊群是一种很散乱的组织,平时在一起也是盲目地左冲右撞,但一旦有一只头羊动起来,其他的羊  也会不假思索地一哄而上,全然不顾旁边可能有的狼和不远处更好的草。羊群效应就是比喻人都有  一种从众心理,从众心理很容易导致盲从,而盲从往往会陷入骗局或遭到失败。

 避免羊群效应zookeeper采用分布式锁

 

  1. 所有请求进来,在/lock下创建 临时顺序节点 ,放心,zookeeper会帮你编号排序
  2. 判断自己是不是/lock最小的节点
    1. 是,获得锁(创建节点)
    2. 否,对前面小我一级的节点进行监听
    3. 获得锁请求,处理完业务逻辑,释放锁(删除节点),后一个节点得到通知(比你年轻的死了,你  成为最嫩的了)
    4. 重复步骤2

1. 实现步骤

1.1 初始化数据库

创建数据库zkproduct,使用默认的字符集utf8

-- 商品表
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)
-- 订单表
create table `order`(
id varchar(100) primary key, -- 订单编号
pid int not null,	-- 商品编号
userid int not null	-- 用户编号
)

1.2 搭建工程

搭建ssm框架,对库存表-1,对订单表+1

具体代码见github

1.3 启动测试

  1. 启动两次工程,端口号分别80018002
  2. 使用nginx做负载均衡

 1.3 使用 JMeter 模拟1秒内发出10http请求

 下载地址:http://jmeter.apache.org/download_jmeter.cgi

 

 

  1. 查看测试结果,10次请求全部成功
  2. 查看数据库,stock库存变成 -5 (并发导致的数据结果错误)

1.4 apahce提供的zookeeper客户端

基于zookeeper原生态的客户端类实现分布式是非常麻烦的,我们使用apahce提供了一个zookeeper客  户端来实现

Curatorh   ttp://curator.apache.org/

<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version> <!-- 网友投票最牛逼版本 -->
</dependency>

recipescurator族谱大全,里面包含zookeeperframework

1.5 在控制层中加入分布式锁的逻辑代码

@Controller
public class ProductAction {

@Autowired
private ProductService productService;

private static String connectString = "192.168.204.141:2181,192.168.204.142:2181,192.168.204.143:2181";

@GetMapping("/product/reduce") @ResponseBody
public Object reduce( int 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";
}
}

再次测试,并发问题解决!

节选自拉钩教育JAVA系列课程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值