本篇文章为大家展示了怎么在Java中使用redis或mysql实现一个秒杀功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
创新互联专注于成都做网站、网站建设、网页设计、网站制作、网站开发。公司秉持“客户至上,用心服务”的宗旨,从客户的利益和观点出发,让客户在网络营销中找到自己的驻足之地。尊重和关怀每一位客户,用严谨的态度对待客户,用专业的服务创造价值,成为客户值得信赖的朋友,为客户解除后顾之忧。所谓秒杀,就是网络卖家发布一些超低价格的商品,所有买家在同一时间网上抢购的一种销售方式。秒杀商品通常有两种限制:时间限制,库存限制,其中库存超卖问题是本教程的重点!
秒杀业务的运行流程主要可以分为以下几点:
商家提交秒杀商品申请,录入秒杀商品数据,主要有:商品标题,商品原价,秒杀价格,商品图片,介绍等信息
运营商审核秒杀申请
秒杀频道首页列出秒杀商品,点击秒杀商品图片可以跳转到秒杀商品详细页面
商品详细页面显示秒杀商品信息,点击立即抢购实现秒杀下单,下单时扣减库存,当库存为0或者不存在活动时间范围内时无法秒杀
秒杀下单成功,直接跳转到支付页面(扫码),支付成功,跳转到成功页面,填写收货、电话、收件人等信息,完成订单。
当用户秒杀下单5分钟内未支付,取消预订单,调用支付的关闭订单接口,恢复库存。
商品表:
订单表:
秒杀技术实现核心思想是运用缓存减少数据库瞬间的访问压力。读取商品详细信息时要运用缓存,当用户点击抢购时也要运用缓存,减少缓存中的库存数量,当库存数为0时或活动时间结束才同步到数据库中。产生的秒杀预订单也不会立刻写到数据库中,而是先写到缓存,当用户付款成功后再写入数据库,或者异步写入MQ,让数据库根据自身的能力去消费。
缓存商品信息,库存信息
@Override @Transactional(rollbackFor = Exception.class) public GoodsEntity initGoods(String name, Integer amount, BigDecimal price) { GoodsEntity goodsEntity = new GoodsEntity().setName(name).setAmount(amount).setPrice(price).setStartDate(new Date()).setEndDate(new Date()); Assert.isTrue(goodsService.save(goodsEntity), "抢购商品初始化发生异常~"); // 缓存库存 redisTemplate.opsForValue().increment("amount:" + goodsEntity.getId(), amount); // 缓存商品信息 redisTemplate.opsForValue().set("goods:" + goodsEntity.getId(), goodsEntity); return goodsEntity; }
基于redis incr 原子性防止超卖
@Override @Transactional(rollbackFor = Exception.class) public Boolean secKill(String key) { Long result = redisTemplate.opsForValue().decrement("amount:" + key, 1); if (result.compareTo(0L) >= 0) { // 下面的数据库操作建议走MQ让数据库按照他的处理能力,从消息队列中拿取消息进行处理。 Try.of(() -> { Assert.isTrue(goodsService.secKill(Long.valueOf(key)), "库存不足!"); OrderEntity orderEntity = new OrderEntity().setGoodsId(Long.valueOf(key)).setOrderNo(UUID.randomUUID().toString().replace("-", "")); Assert.isTrue(orderService.save(orderEntity), "订单创建发生异常~"); redisTemplate.opsForValue().set("secKill:" + orderEntity.getId(), orderEntity.getOrderNo(), 10, TimeUnit.SECONDS); return true; }).onFailure((e) -> { log.error("持久化异常:" + e.getMessage()); redisTemplate.opsForValue().increment("amount:" + key, 1); }); return false; } redisTemplate.opsForValue().increment("amount:" + key, 1); return false; }
最终效果:
上述内容就是怎么在Java中使用redis或mysql实现一个秒杀功能,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注创新互联行业资讯频道。