zookeeper实现商品秒杀抢购

package com.test;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CyclicBarrier;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

public class Main {

    public static void main(String[] args) throws IOException, KeeperException, InterruptedException {

        ZooKeeper zk = new ZooKeeper("127.0.0.1", 2000, null);
        Stat st = zk.exists("/goods", false);
        if (st == null) {
            zk.create("/goods", new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        }
        String[] goods = { "iPhone6s", "小米移动电源" };
        for (String g : goods) {
            zk.create("/goods/" + g, new byte[0], Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
        }

        int threadCount = 5;
        CyclicBarrier cb = new CyclicBarrier(threadCount); // 为了更好地表示并发,这里用了CyclicBarrier类
        for (int i = 0; i < threadCount; i++) {
            // 用多线程摸您多用户
            new Thread(new Thread1(cb)).start();
        }
        System.in.read();

    }

    static class Thread1 implements Runnable {
        ZooKeeper zk = null;
        CyclicBarrier cb;

        // 是否还没有抢过商品
        boolean isNotGet = true;

        public Thread1(CyclicBarrier cb) {
            this.cb = cb;
        }

        private void snatchGoods() throws Exception {

            // 获取商品库存
            List<String> goodsList = zk.getChildren("/goods", true);// 获取商品列表并监控变化,如果在和其它用户抢购同一个商品时没抢到的情况下可再次监控其它商品
            if (goodsList.isEmpty()) {
                // 商品库存为空,表示商品抢光了
                System.out.println(Thread.currentThread().getName() + "没抢到商品");
            } else {
                // 获取第一个商品
                String goods = goodsList.get(0);
                try {
                    // 从内存中删除商品节点,表示抢购,如果删除失败,就表示没抢到这个商品,并进入到下面的catch块中
                    zk.delete("/goods/" + goods, -1);
                    // 限制每个用户只能抢购一件商品,设置false表示已经抢购过了
                    isNotGet = false;
                    System.out.println(Thread.currentThread().getName() + "抢到了" + goods);
                } catch (Exception e) {

                }
            }
        }

        @Override
        public void run() {
            try {
                zk = new ZooKeeper("127.0.0.1:2181", 2000, new Watcher() {
                    @Override
                    public void process(WatchedEvent event) {
                        try {
                            EventType type = event.getType();
                            if (isNotGet) {
                                if (type == EventType.None) {
                                    // 用户第一次访问,则立即执行商品的抢购
                                    snatchGoods();
                                } else if (type == EventType.NodeChildrenChanged) {
                                    // 抢购一件商品失败后,再抢购另一件商品
                                    snatchGoods();
                                }
                            }
                        } catch (Exception e) {
                            System.out.println(e.getMessage());
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
  1. 使用多线程模拟多用户抢购
  2. 用户第一次访问,则立即执行商品的抢购
  3. 抢购一件商品失败后,再抢购另一件商品
  4. 商品库存为空,表示商品抢光了

zookeeper实现商品秒杀抢购:

秒杀活动是一些购物平台推出的集中人气的活动,一般商品数量很少,价格很便宜,限定开始购买的时间,会在以秒为单位的时间内被购买一空。比如原价千元甚至万元的商品以一元的价格出售,但数量只有一件,在某天的某个时间开始出售,这就造成很多人去抢这一件商品。

获取商品列表并监控变化,如果在和其它用户抢购同一个商品时没抢到的情况下可再次监控其它商品

抢购一件商品失败后,再抢购另一件商品

运行多次,打印出如下结果:

Thread-4-EventThread抢到了iPhone6s
Thread-1-EventThread抢到了小米移动电源
Thread-2-EventThread没抢到商品
Thread-3-EventThread没抢到商品
Thread-0-EventThread没抢到商品

Thread-3-EventThread抢到了iPhone6sThread-2-EventThread抢到了小米移动电源Thread-4-EventThread没抢到商品Thread-1-EventThread没抢到商品Thread-0-EventThread没抢到商品

Thread-0-EventThread抢到了iPhone6sThread-3-EventThread抢到了小米移动电源Thread-4-EventThread没抢到商品Thread-2-EventThread没抢到商品Thread-1-EventThread没抢到商品

Thread-2-EventThread抢到了iPhone6sThread-4-EventThread抢到了小米移动电源Thread-0-EventThread没抢到商品Thread-3-EventThread没抢到商品Thread-1-EventThread没抢到商品

可以看到,两件商品,多个线程并发抢购,总是只有两个线程分别抢到不同的商品。

时间: 2024-10-14 00:38:08

zookeeper实现商品秒杀抢购的相关文章

电商商品秒杀系统架构分析与实战

网址:http://my.oschina.net/xianggao/blog/524943 0 系列目录 1 秒杀业务分析 2 秒杀技术挑战 3 秒杀架构原则 4 秒杀架构设计 4.1 前端层设计 4.2 站点层设计 4.3 服务层设计 4.4 数据库设计 4.4.1 基本概念 4.4.2 设计思路 5 大并发带来的挑战 5.1 请求接口的合理设计 5.2 高并发的挑战:一定要“快” 5.3 重启与过载保护 6 作弊的手段:进攻与防守 6.1 同一个账号,一次性发出多个请求 6.2 多个账号,一

Java秒杀系统实战系列~商品秒杀代码实战

摘要: 本篇博文是"Java秒杀系统实战系列文章"的第六篇,本篇博文我们将进入整个秒杀系统核心功能模块的代码开发,即"商品秒杀"功能模块的代码实战. 内容: "商品秒杀"功能模块是建立在"商品详情"功能模块的基础之上,对于这一功能模块而言,其主要的核心流程在于:前端发起抢购请求,该请求将携带着一些请求数据:待秒杀Id跟当前用户Id等数据:后端接口在接收到请求之后,将执行一系列的判断与秒杀处理逻辑,最终将处理结果返回给到前端.

redis使用watch完成秒杀抢购功能(转)

redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内存数据库来抢购速度极快. 2. 速度快并发自然没不是问题. 3. 使用悲观锁,会迅速增加系统资源. 4. 比队列强的多,队列会使你的内存数据库资源瞬间爆棚. 5. 使用乐观锁,达到综合需求. 我觉得以下代码肯定是你想要的. [php] view plain copy print? <?php hea

redis使用watch完成秒杀抢购功能:

使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内存数据库来抢购速度极快. 2. 速度快并发自然没不是问题. 3. 使用悲观锁,会迅速增加系统资源. 4. 比队列强的多,队列会使你的内存数据库资源瞬间爆棚. 5. 使用乐观锁,达到综合需求. 我觉得以下代码肯定是你想要的. <?php header("content-type:text/html;charset=utf-8")

PHP商品秒杀计时实现(解决大流量方案)

PHP商品秒杀功能我们多半以整点或时间点为例子,这样对于php来说处理不复杂,但有一个问题就是如果流量大要如何来处理,下面我们一起来看看解决办法. 要求要有小时分钟秒的实时倒计时的显示,用户端修改日期时间不会影响到倒计时的正常显示(也就是以服务器时间为准). 其实这和很多的考试等系统的时间限制功能同样的要求. 总不能用ajax每秒都获取服务器时间吧,所以实时倒计时一定要用javascript实现.这很简单,网上一大把的例子. 现在问题是解决用户端修改日期时间对我们的显示的影响. 解决的办法是计算

一句JS帮你秒杀,抢购

刚刚看到一哥们儿写了一篇jquery插件之倒计时-团购秒杀  突然想到一个主意就是如题 想法:现在很多地方有类似秒杀,抢购等拼手速,网速的(其实就是服务器渣,如:某米),  很多人就想到可以写个客户端,开启一直刷, 我觉得应该可以直接通过js代码来执行. 下面进入正题 如果大家了解并会使用各浏览器的开发者工具就非常好办咯, 本人习惯用chrome,本例也就用chrome F12打开开发者工具 在控制台直接输入js带是可以执行的,所以大家应该有头绪了 测试: 写一个测试页面 <div> <

redis使用watch完成秒杀抢购功能

redis使用watch完成秒杀抢购功能: 使用redis中两个key完成秒杀抢购功能,mywatchkey用于存储抢购数量和mywatchlist用户存储抢购列表. 它的优点如下: 1. 首先选用内存数据库来抢购速度极快. 2. 速度快并发自然没不是问题. 3. 使用悲观锁,会迅速增加系统资源. 4. 比队列强的多,队列会使你的内存数据库资源瞬间爆棚. 5. 使用乐观锁,达到综合需求. 我觉得以下代码肯定是你想要的. [php] view plain copy print? <?php hea

SpringBoot+RabbitMQ+Redis实现商品秒杀

业务分析 一般而言,商品秒杀大概可以拆分成以下几步: 用户校验 校验是否多次抢单,保证每个商品每个用户只能秒杀一次 下单 订单信息进入消息队列,等待消费 减少库存 消费订单消息,减少商品库存,增加订单记录 付款 十五分钟内完成支付,修改支付状态 创建表 goods_info 商品库存表 列 说明 id 主键(uuid) goods_name 商品名称 goods_stock 商品库存 package com.jason.seckill.order.entity; /** * 商品库存 */ pu

php如何应对秒杀抢购高并发思路

我们常用QPS(Query Per Second,每秒处理请求数)来衡量一个web应用的吞吐率,解决每秒数万次的高并发场景,这个指标非常关键. 举个栗子:假设一个业务请求平均为100ms,同时系统内有20台apache web服务器,MaxClients(apache的最大连接数)设置为500,那么理论QPS峰值就是20*500/0.1=100000(理论与实际肯定有差异). 这系统貌似理论上来说很强大1秒钟处理100000个请求,实际当然没有这么理想.在高并发的实际场景下,机器都处于高负载的状