java redis实现抢购_java redis 实现抢购秒杀

本文介绍了如何利用Redis的watch、multi事务来实现Java抢购秒杀功能,通过示例代码展示了如何控制秒杀数量以避免超卖。在并发环境下,存在抢购顺序的问题,作者提出了将请求存入Kafka以解决这一问题。

2018.10.24 今天研究了下抢购秒杀的功能实现

网上查了一大堆 用redis的最多。

主要是通过redis的 watch multi 事务来控制秒杀数量 不超卖。

这里说下自己的感受:

不超卖的话 那就要一个个的来减库存 这样的话 效率上会有点问题 这里上下代码 基本上是再网上抄的 。

我用的是 springboot jedis

我就直接上代码了

Controller层

package com.bicon.basedemo.controller;

import java.util.Arrays;

import java.util.List;

import java.util.Random;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import javax.annotation.Resource;

import org.omg.CORBA.PRIVATE_MEMBER;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import redis.clients.jedis.Jedis;

import redis.clients.jedis.JedisPool;

@RestController

@RequestMapping("/test")public classtest {//@Resource//RedisOperation redisOps;

@ResourceprivateJedisPool jedisPool;@RequestMapping("/redis")public voidredisTest() {

Jedis jedis=jedisPool.getResource();

final String watchkeys= "watchkeys";

ExecutorService executor= Executors.newFixedThreadPool(20); //20个线程池并发数

jedis.set(watchkeys, "10");//设置起始的抢购数//jedis.del("setsucc", "setfail");

jedis.close();for (int i = 0; i < 101; i++) {//设置101个人来发起抢购 模拟101个人抢购

executor.execute(newMyRunnable(jedisPool));

}

executor.shutdown();

}public static String getRandomString(int length) { //length是随机字符串长度

String base = "abcdefghijklmnopqrstuvwxyz0123456789";

Random random= newRandom();

StringBuffer sb= newStringBuffer();for (int i = 0; i < length; i++) {int number = random.nextInt(base.length());

sb.append(base.charAt(number));

}returnsb.toString();

}

}

MyRunnable 代码

package com.bicon.basedemo.controller;

import java.util.List;

import redis.clients.jedis.Jedis;

import redis.clients.jedis.JedisPool;

import redis.clients.jedis.Transaction;public classMyRunnable implements Runnable{privateJedisPool jedisPool;

String userinfo;

String watchkeys= "watchkeys";publicMyRunnable(JedisPool jedisPoo){

jedisPool=jedisPoo;

};public voidrun() {

Jedis jedis=jedisPool.getResource();try{

jedis.watch(watchkeys);//watchkeys

String val= jedis.get(watchkeys);int valint =Integer.valueOf(val);if (valint <= 100 && valint>=1) {

Transaction tx= jedis.multi();//开启事务//tx.incr("watchkeys");

tx.incrBy("watchkeys", -1);

List list = tx.exec();//提交事务,如果此时watchkeys被改动了,则返回null

if (list == null ||list.size()==0) {

System.out.println("重新抢购");this.run();return;

}else{for(Object succ : list){

String succuserifo="succ"+succ.toString() +userinfo ;

String succinfo="用户:" + succuserifo + "抢购成功,当前抢购成功人数:"

+ (1-(valint-10));

System.out.println(succinfo);/*抢购成功业务逻辑*/jedis.setnx(succuserifo, succinfo);

}

}

}else{

String failuserifo="kcfail" +userinfo;

String failinfo1="用户:" + failuserifo + "商品被抢购完毕,抢购失败";

System.out.println(failinfo1);

jedis.setnx(failuserifo, failinfo1);return;

}

}catch(Exception e) {

e.printStackTrace();

}finally{

jedis.close();

}

}

}

最后是效果

e0741a39200ca04fcff3349b63e5f369.png

这段代码问题其实还是有的:就是没有按照顺来来抢购

其实我觉得有种方法。就是将请求 存入 kafka中

然后取kafka中前面的数据 一直取到抢购的数量(用户不重复)

这样不就可以了吗,不需要考虑超卖问题啥的。纯属自己的感想。

原文:https://www.cnblogs.com/huobi/p/9844755.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值