java+mysql实现商品抢购功能
我们希望有人购买时检查商品数量是否足够,如果库存有剩余那么就让用户购买成功,之后变更库存,假如用户排队挨个购买这样当然没有问题。
可是实际情况下,可能是用户多个用户同时来购买,同时检查库存,这是可能库存仅够其中一人购买,但是由于库存还没减掉,就会出现几个人都购买成功,然后库存减为负数出现超卖的情况。这在大量用户在同一时间点同时购买时极可能出现。
于是我们调整一下顺序,有用户购买时我们先减掉库存,那你肯定要问,怎么减?库存不够一个人的时候也减?
我们假设每份商品有一个唯一的购买码(开始抢购前预先生成),用户抢到购买码的数量即他买到的份数,那么有用户购买时我们第一步就是给幸运码的状态由有效更改为无效,并为其标记上其购买者ID
"UPDATE`lottery_number`SET`status`=失效状态,`user_id`=购买者用户Id,`current_time`=时间戳 WHERE`goods_id`=抢购的商品IDAND`status`=有效状态LIMIT购买份数";
这样其实mysql会给我们一个返回结果,叫做影响行数,就是说这条语句更新影响了多少行的数据,这个影响行数就是他实际购买到的商品份数,如果影响行数为0,就说明一份也没购买成功,也就意味着商品已经抢购完成了。
java实现:
/** *生成商品的购买码<大量数据插入> * *@paramgoodsIssue *@authorNifury */ publicvoidinsertLotteryNumbers(GoodsIssuegoodsIssue){ Stringprefix="INSERTINTO`lottery_number`(`goods_id`,`periods`,`luck_number`,`create_time`,`status`,`issue_id`)VALUES\n"; Timestampnow=newTimestamp(System.currentTimeMillis()); Connectioncon=null; try{ con=jdbcTemplate.getDataSource().getConnection(); con.setAutoCommit(false); PreparedStatementpst=con.prepareStatement(""); Longtotal=goodsIssue.getTotalShare();//总人次 for(inti=0;inumbers=newArrayList (); for(intj=0;j<10000&&i+j 分配购买码(我们的业务需要给购买用户展示购买码,所以有返回)
/** *通过商品issue_id(每期每个商品有唯一issue_id)来随机获取购买码(使用的购买码会设为失效状态) *@paramissueId *@paramamount需要获取的购买码的数量 *@paramuserId *@returnLotteryNumber对象列表 *@authorNifury2016-7-22 */ publicListqueryByNewIssueId2(LongissueId,Longamount,LonguserId){ List numberList=newArrayList (); try{ longcurrentTime=System.currentTimeMillis(); StringupdateUserId="UPDATE`lottery_number`SET`status`=0,`user_id`=?,`current_time`=?WHERE`issue_id`=?AND`status`=1LIMIT?"; intrownum=jdbcTemplate.update(updateUserId,userId,currentTime,issueId,amount); if(rownum>0){//还有剩余有效购买码 Object[]buyargs={issueId,userId,currentTime}; numberList=jdbcTemplate.query(QUERY+"WHERE`issue_id`=?AND`status`=0AND`user_id`=?AND`current_time`=?", buyargs,LotteryNumberMapper); } }catch(DeadlockLoserDataAccessExceptione){ System.out.println("----分配购买码出现死锁,用户分得0个购买码-----"); } returnnumberList; } 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。