zookeeper实现分布锁

        互联网电商项目扣减库存就是个典型的分布式问题,如果简单的使用synchronized,ReentrantLock,在单机的环境下是可行的,但是互联网项目一般是很多服务器集群的,再继续使用synchronized,ReentrantLock就无法锁住了,那么就需要使用分布锁,常用的分布锁有三种1.基于数据库的cas,2.基于redis分布锁  3.基于zookeeper分布锁。本文介绍zookeeper实现分布锁。

        1.安装zookeeper

         https://zookeeper.apache.org/releases.html#download官网下载zookeeper,具体安装可以网上另行找文章看看,比如这篇

https://www.cnblogs.com/expiator/p/9853378.html

        ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

        ZooKeeper就是个树形结构,可以设置key,value,节点类型包括:1、临时节点 2、持久节点  3、临时有序节点 4、持久有序节点,zookeeper分布锁其实创建的就是临时有序节点,每次创建一个临时有序节点时,比如0000001,就等于获取到了锁,创建0000002时需要监听0000001是否已经释放,如果没有释放就不能获取锁,释放了,才能获取锁。

        2.模拟高并发扣减库存

        有轮子尽量使用轮子了,使用开源的zookeeper客户端Curator来连接zookeeper,本文测试的时候使用的是springboot,添加相关依赖就可以了。

	<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-framework</artifactId>
			<version>5.0.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-recipes -->
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-recipes</artifactId>
			<version>5.0.0</version>
		</dependency>
package com.figo.demo.test;

import java.util.concurrent.CountDownLatch;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.apache.curator.retry.ExponentialBackoffRetry;
/**
 * zookeeper实现分布锁 .
 * @author figo .
 * 20200614 .
 */
public class ZookeeperTest {
	//假设库存是100
	static int stock = 100;
    
	public static void main(String[] args) {
		//连接zookeeper
		CuratorFramework cf = CuratorFrameworkFactory.newClient("127.0.0.1:2181", 5000, 4000,
				new ExponentialBackoffRetry(1000, 3));
		cf.start();
		//互斥锁创建(创建的是zookeeper的有序临时节点)
		InterProcessMutex lock = new InterProcessMutex(cf, "/testlocks");
		//测试高并发扣减库存
		testConcurrent(lock);
	}
    //100个线程同时扣减库存
	public static final int threadNum = 100;
    /*
     * 测试高并发扣减库存 .
     */
	public static void testConcurrent(InterProcessMutex lock) {
		//定义一个计数器
		CountDownLatch cdl = new CountDownLatch(1);
		for (int a = 0; a < threadNum; a++) {
			Thread thread = new Thread(new MyRunable(cdl,lock));
			thread.start();
		}
		//计数器减一,总共就1,减一等于0,这个时候所有的线程开始同时执行,模拟高并发
		cdl.countDown();
	}
    //定义runnable
	public static class MyRunable implements Runnable {
		private final CountDownLatch countDownLatch;
		InterProcessMutex lockNew;
		public MyRunable(CountDownLatch cdl,InterProcessMutex lock) {
			countDownLatch = cdl;
			lockNew=lock;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			try {
				//等待在这里,直到计数器数值为0开始执行
				countDownLatch.await();
				//获取锁
				lockNew.acquire();
				//扣减库存
				stock = stock - 1;
				//释放锁
				lockNew.release();
                //打印当前线程名称,库存剩余多少
				System.out.println("threadName="+Thread.currentThread().getName()+",current stock=" + stock);

			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}

	}

}

           加上锁以后,可以发现每个线程扣减后,库存是有序递减,不加锁,容易发现多个线程扣减完库存后,库存值是一样,这个就有问题了,就像100个人同时拍商品,总共100个库存,扣完后,还剩下几个。。。大家可以测试一下看看。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值