java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java基于redis和mysql秒杀

Java基于redis和mysql实现简单的秒杀(附demo)

作者:JAVA拾贝

这篇文章主要介绍了Java基于redis和mysql实现简单的秒杀(附demo),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一.秒杀业务分析

       所谓秒杀,就是网络卖家发布一些超低价格的商品,所有买家在同一时间网上抢购的一种销售方式。秒杀商品通常有两种限制:时间限制,库存限制,其中库存超卖问题是本教程的重点!

秒杀业务的运行流程主要可以分为以下几点:

 二.数据库设计

商品表:

订单表:

  三.秒杀实现思路

       秒杀技术实现核心思想是运用缓存减少数据库瞬间的访问压力。读取商品详细信息时要运用缓存,当用户点击抢购时也要运用缓存,减少缓存中的库存数量,当库存数为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;
  }

 最终效果:

观察redis存储的数据和数据库的订单记录可发现,秒杀场景基本实现!

四.总结

     本文主要解决超卖,和长时间未支付库存重置的问题; 实际场景,还要考虑前后端的多种优化(静态页、cdn、防止重复下单、限流等等……)

五.完整代码示例

前往下载

到此这篇关于Java基于redis和mysql实现简单的秒杀(附demo)的文章就介绍到这了,更多相关Java基于redis和mysql秒杀内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文