redis模拟秒杀业务javademo简单实现

redis实现秒杀javademo实现

 

WATCH命令介绍

监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

MULTI命令介绍

标记一个事务块的开始。

事务块内的多条命令会按照先后顺序被放进一个队列当中,最后由 EXEC 命令原子性(atomic)地执行。

EXEC命令介绍

执行所有事物块内的命令

假如某个(或某些) key 正处于 WATCH 命令的监视之下,且事务块中有和这个(或这些) key 相关的命令,那么 EXEC 命令只在这个(或这些) key 没有被其他命令所改动的情况下执行并生效,否则该事务被打断(abort)。

思路

先通过WATCH命令监控goods,此后又将set命令包围在事务中,这样就可以有效的保证每个连接在执行EXEC之前,如果当前连接获取的goods的值被其它连接的客户端修改,那么当前连接的EXEC命令将执行失败。这样调用者在判断返回值后就可以获悉val是否被重新设置成功。

我们看下伪代码

WATCH goods

val = val + 1

MULTI

SET goods $val

EXEC

废话不多说,上代码

 

/**
 * 初始化商品
 */
 private void initGoogs() {
    Jedis jedis = RedisUtil.getJedis();
    String watchKey = "goods";
    int goodsCount = 20;
    jedis.set(watchKey, String.valueOf(goodsCount));
 }

 

/**
 * 模拟多个用户抢购
 */
private void secKill() {
    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    int clientNum = 1000;// 模拟客户数目
    for (int i = 0; i < clientNum; i++) {
        cachedThreadPool.execute(new customerThread(i));
    }
    cachedThreadPool.shutdown();
    while(true){
        if(cachedThreadPool.isTerminated()){
            System.out.println("所有的线程都结束了!");
            break;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
/**
 * 打印秒杀结果
 */
public void print() {
    Jedis jedis = RedisUtil.getJedis();
    Set<String> set = jedis.smembers("client");
    int i = 1;
    for (String value : set) {
        System.out.println("第" + i++ + "个抢到商品," + value + " ");
    }
}
 
class customerThread implements Runnable{
    // 监视的商品
    String watchKey = "goods";
    String clientKey = "client";
    String customerName;

    customerThread(int num) {
        this.customerName = "编号:" + num;
    }

    public void run() {
        try {
            //随机暂停
            Thread.sleep((int)(Math.random()*5000));
        } catch (InterruptedException e) {
        }
        while (true) {
            System.out.println(customerName + "开始抢商品!");
            Jedis jedis = RedisUtil.getJedis();
            try{
                jedis.watch(watchKey);
                int goodsCount = Integer.parseInt(jedis.get(watchKey));
                if(goodsCount > 0) {
                    //开启事物
                    Transaction transaction = jedis.multi();
                    transaction.set(watchKey, String.valueOf(goodsCount - 1));
                    //提交事物
                    List<Object> result =  transaction.exec();
                    if(!result.isEmpty()) {
                        jedis.sadd(clientKey, customerName);//
                        System.out.println("顾客" + customerName + "抢到了¥¥¥¥");
                        break;
                    } else{
                        System.out.println("顾客" + customerName + "没抢到!!!!");
                    }
                } else {
                    System.out.println("顾客" + customerName + "没货了!!!!");
                    break;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                jedis.unwatch();
                RedisUtil.returnResource(jedis);
            }
        }
    }
 }
@Test
public void test() {
    initGoogs();
    secKill();
    print();
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值