首页 > 其他分享 >利用 zookeeper 的分布式锁实现秒杀

利用 zookeeper 的分布式锁实现秒杀

时间:2023-10-26 11:07:04浏览次数:36  
标签:10 lock zookeeper curator 秒杀 抢购 public 分布式


常见的业务场景:x年x月x日x点x分x秒,限时抢购10件商品。前提:分布式的环境,多用户高并发访问。

  1. 依赖的 jar 包
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.qjl</groupId>
	<artifactId>hdfs</artifactId>
	<version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

	<dependencies>
        <!-- zookeeper所需依赖 -->
        <dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-framework</artifactId>
			<version>4.0.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-recipes</artifactId>
			<version>4.0.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-client</artifactId>
			<version>4.0.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.zookeeper</groupId>
			<artifactId>zookeeper</artifactId>
			<version>3.4.6</version>
		</dependency>
		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>16.0.1</version>
		</dependency>
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</project>
  1. 待抢购的商品:
class Resource {
	
	/**
	 * 公共资源(可以看成10件商品)
	 */
	private static AtomicInteger count = new AtomicInteger(10);
	
	/**
	 * 公共的服务(可以看成购买一件商品)
	 */
	public static void commonService() {
		System.out.println("***********抢购开始 **********");
		int cur = count.decrementAndGet();
		System.out.println("当前剩余商品:" + cur);
		
		// 睡2秒,模拟线程切换
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("***********抢购结束 **********");
	}
}
  1. 抢购任务:
/**
 * 抢购任务
 * @author qujianlei
 */
class Task implements Runnable {
	
	private InterProcessMutex lock;
	
	public Task(InterProcessMutex lock) {
		this.lock = lock;
	}
	
	@Override
	public void run() {
		try {
			// 执行任务之前先获得锁
			lock.acquire();
		} catch (Exception e) {
			e.printStackTrace();
		}
		Resource.commonService();
		// 闭锁数量减一
		SynLock.latch.countDown();
		try {
			// 任务完成之后释放锁
			lock.release();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
  1. 使用闭锁确保所有线程执行完任务以后再关闭 zookeeper 客户端:
/**
 * 通过闭锁来实现异步转同步的操作
 * @author qujianlei
 */
class SynLock {
	public static CountDownLatch latch = new CountDownLatch(10);
}
  1. 主程序:
/**
 * 利用zookeeper的分布式锁实现秒杀功能
 * @author qujianlei
 */
public class TestDistributedLock {

	public static void main(String[] args) {
		// 定义客户端重试策略
		RetryPolicy policy = new ExponentialBackoffRetry(1000, 10);
		
		// 定义ZK的一个客户端
		CuratorFramework client = CuratorFrameworkFactory.builder()
			.connectString("127.0.0.1:2181")
			.retryPolicy(policy)
			.build();
		
		// 在zk生成锁 --> 就是zk的目录
		client.start();
		InterProcessMutex lock = new InterProcessMutex(client, "/mylock");
		
		ExecutorService executorService = Executors.newFixedThreadPool(10);
		
		// 启动10个线程去调用公共的服务
		for (int i = 0; i < 10; i++) {
			executorService.execute(new Task(lock));
		}
		
		executorService.shutdown();
		
		try {
			// 在闭锁的数量减到0之前,当前线程一直处于阻塞状态,确保zookeeper客户端关闭前,所有的抢购任务可以执行完毕
			SynLock.latch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		client.close();
	}
}


标签:10,lock,zookeeper,curator,秒杀,抢购,public,分布式
From: https://blog.51cto.com/u_14655640/8030925

相关文章

  • 分布式系统分析
    什么是分布式系统分布式系统是支持分布式处理的软件系统,是由通信网络互联的多处理机体系结构上执行任务的系统。一个业务拆分为多个子业务,落地成不同的服务,将各个服务部署在不同的容器上。各个服务之间通过某种协议通信交互。好处是有更好的可靠性,可扩展性,但也带来了一致性问题......
  • Redisson分布式锁主从一致性问题解决
    Redis联锁联锁(RedissonMultiLock)对象可以将多个RLock对象关联为一个联锁,实现加锁和解锁功能。每个RLock对象实例可以来自于不同的Redisson实例。如果负责储存分布式锁的某些Redis节点宕机以后,而且这些锁正好处于锁住状态,就会出现死锁问题。为了避免这种情况的发生,Redisson内部提供......
  • XA分布式事务协议
          XA(eXtendedArchitecture)是指由X/Open组织提出的分布式交易处理的规范。XA是一个分布式事务协议,由Tuxedo提出,所以分布式事务也称为XA事务。XA协议主要定义了事务管理器TM(TransactionManager,协调者)和资源管理器RM(ResourceManager,参与者)之间的接口。其中,资源管......
  • 分布式锁优化(基于redisson实现)
    基于setnx实现的分布式锁存在下面的问题:1.不可重入同一个线程无法多次获取同一把锁2.不可重试获取锁只尝试一次就返回false,没有重试机制3.超时释放锁超时释放虽然可以避免死锁,但如果是业务执行耗时较长,也会导致锁释放,存在安全隐患4.主从一致性(主写从读)如果Redis提供了主从集群,主......
  • Redis 6 学习笔记 4 —— 通过秒杀案例,学习并发相关和apache bench的使用,记录遇到的问
    背景这是某硅谷的redis案例,主要问题是解决计数器和人员记录的事务操作按照某硅谷的视频敲完之后出现这样乱码加报错的问题 乱码的问题要去tomcat根目录的conf文件夹下修改logging.properties,把下面两个encoding参数都改成GBK就行。其实错误也很明显(ClassNotFoundExceptio......
  • Zookeeper 创建6种的节点实例(转)
    原文:https://blog.csdn.net/pengweismile/article/details/115444734作者:伟娃娃Zookeeper是ApacheHadoop的一个子项目,它主要用来解决分布式系统中经常遇到的一些数据管理问题,例如,统一命名,状态同步,集群管理,分布式应用配置管理。Zookeeper的定位,这个动物园的管理者,如下图ooke......
  • 分布式定时任务-利用分布式定时任务框架xxl-job实现任务动态发布
     1.场景:项目前期使用k8s部署的单节点,后期生产需要将单节点的服务扩展多个节点,每个节点的定时任务使用的quartz实现,如果不加限制且定时任务有对数据库的写操作,在不同节点上执行的定时任务容易造成数据库产生脏数据,所以需要分布式任务框架对任务进行控制,这里我们使用xxl-job实现。......
  • 分布式事务
    本地事务在分布式下会出现的问题只能各自回滚各自的簇点头那边抛出异常--->全部回滚(ok)簇点第一个远程调用返回code不正确,我们可在主方法这抛异常(ok)簇点非第一个远程调用code不正确,我们只有那个远程调用和主方法会rollback,在其之前的远程调用无法rollback没人通知(NO)......
  • 谷粒商城分布式基础(一)—— 项目简介 & 分布式基础
     目录一项目简介1、项目背景二、分布式基础概念 分布式基础篇回到顶部一项目简介1、项目背景1.1电商模式市面上有5种常见的电商模式B2B、B2C、C2B、C2C、O2O;(1)B2B模式B2B(BusinesstoBusiness),是指商家和商家建立的商业关系,如阿里巴巴(2)B2C模式......
  • zookeeper源码(02)源码编译启动及idea导入
    本文介绍一下zookeeper-3.9.0源码下载、编译及本地启动。下载源码gitclonehttps://gitee.com/apache/zookeeper.gitcdzookeepergitcheckoutrelease-3.9.0gitcheckout-brelease-3.9.0源码编译README_packaging.md文件该文件介绍了编译zookeeper需要的环境和命令......