我们希望有人购买时检查商品数量是否足够,如果库存有剩余那么就让用户购买成功,之后变更库存,假如用户排队挨个购买这样当然没有问题。
可是实际情况下,可能是用户多个用户同时来购买,同时检查库存,这是可能库存仅够其中一人购买,但是由于库存还没减掉,就会出现几个人都购买成功,然后库存减为负数出现超卖的情况。这在大量用户在同一时间点同时购买时极可能出现。
于是我们调整一下顺序,有用户购买时我们先减掉库存,那你肯定要问,怎么减?库存不够一个人的时候也减?
我们假设每份商品有一个唯一的购买码(开始抢购前预先生成),用户抢到购买码的数量即他买到的份数,那么有用户购买时我们第一步就是给幸运码的状态由有效更改为无效,并为其标记上其购买者ID
"UPDATE `lottery_number` SET `status` = 失效状态,`user_id` = 购买者用户Id,`current_time`= 时间戳 WHERE `goods_id` = 抢购的商品ID AND `status`=有效状态 LIMIT 购买份数 ";
java实现:
/** * 生成商品的购买码<大量数据插入> * * @param goodsIssue * @author Nifury */ public void insertLotteryNumbers(GoodsIssue goodsIssue) { String prefix = "INSERT INTO `lottery_number` (`goods_id`, `periods`,`luck_number`, `create_time`, `status`, `issue_id` ) VALUES \n"; Timestamp now = new Timestamp(System.currentTimeMillis()); Connection con = null; try { con = jdbcTemplate.getDataSource().getConnection(); con.setAutoCommit(false); PreparedStatement pst = con.prepareStatement(""); Long total = goodsIssue.getTotalShare();// 总人次 for (int i = 0; i < total; i += 10000) {// 1万条提交一次 StringBuffer suffix = new StringBuffer(); List<Integer> numbers = new ArrayList<Integer>(); for (int j = 0; j < 10000 && i+j < total; j++) { numbers.add(10000001 + i + j); } Collections.shuffle(numbers);//打乱幸运码 for (int n = 0,length = numbers.size(); n < length; n++) { suffix.append("(" + goodsIssue.getGoodsId() + "," + goodsIssue.getPeriods() + "," + numbers.get(n) + ",'" + now.toString() + "'," + 1 + "," + goodsIssue.getIssueId() + ")\n,"); } // 构建完整sql String sql = prefix + suffix.substring(0, suffix.length() - 2); pst.addBatch(sql); pst.executeBatch(); con.commit(); } con.setAutoCommit(true);// 还原 pst.close(); con.close(); } catch (Exception e) { e.printStackTrace(); try {// 事务回滚 con.rollback(); con.setAutoCommit(true); con.close(); } catch (SQLException e1) { e1.printStackTrace(); }// 还原 } }
分配购买码(我们的业务需要给购买用户展示购买码,所以有返回)
/** * 通过商品issue_id(每期每个商品有唯一issue_id)来随机获取购买码(使用的购买码会设为失效状态) * @param issueId * @param amount 需要获取的购买码的数量 * @param userId * @return LotteryNumber对象列表 * @author Nifury 2016-7-22 */ public List<LotteryNumber> queryByNewIssueId2(Long issueId, Long amount,Long userId) { List<LotteryNumber> numberList = new ArrayList<LotteryNumber>(); try { long currentTime=System.currentTimeMillis(); String updateUserId = "UPDATE `lottery_number` SET `status` = 0,`user_id` = ?,`current_time`= ? WHERE `issue_id` = ? AND `status`=1 LIMIT ? "; int rownum=jdbcTemplate.update(updateUserId, userId, currentTime, issueId, amount ); if(rownum>0){//还有剩余有效购买码 Object[] buyargs={issueId, userId ,currentTime}; numberList = jdbcTemplate.query(QUERY + " WHERE `issue_id` = ? AND `status` = 0 AND `user_id` = ? AND `current_time`= ?", buyargs, LotteryNumberMapper); } } catch (DeadlockLoserDataAccessException e) { System.out.println("----分配购买码出现死锁,用户分得0个购买码-----"); } return numberList; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:notice#nhooo.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。