热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

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

一.秒杀业务分析

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

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

  • 商家提交秒杀商品申请,录入秒杀商品数据,主要有:商品标题,商品原价,秒杀价格,商品图片,介绍等信息
  • 运营商审核秒杀申请
  • 秒杀频道首页列出秒杀商品,点击秒杀商品图片可以跳转到秒杀商品详细页面
  • 商品详细页面显示秒杀商品信息,点击立即抢购实现秒杀下单,下单时扣减库存,当库存为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;
  }

 最终效果:

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

四.总结

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

五.完整代码示例

前往下载

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


推荐阅读
  • 一次上线事故,30岁+的程序员踩坑经验之谈
    本文主要介绍了一位30岁+的程序员在一次上线事故中踩坑的经验之谈。文章提到了在双十一活动期间,作为一个在线医疗项目,他们进行了优惠折扣活动的升级改造。然而,在上线前的最后一天,由于大量数据请求,导致部分接口出现问题。作者通过部署两台opentsdb来解决问题,但读数据的opentsdb仍然经常假死。作者只能查询最近24小时的数据。这次事故给他带来了很多教训和经验。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • yum安装_Redis —yum安装全过程
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Redis—yum安装全过程相关的知识,希望对你有一定的参考价值。访问https://redi ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • 2021最新总结网易/腾讯/CVTE/字节面经分享(附答案解析)
    本文分享作者在2021年面试网易、腾讯、CVTE和字节等大型互联网企业的经历和问题,包括稳定性设计、数据库优化、分布式锁的设计等内容。同时提供了大厂最新面试真题笔记,并附带答案解析。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
  • 面试经验分享:华为面试四轮电话面试、一轮笔试、一轮主管视频面试、一轮hr视频面试
    最近有朋友去华为面试,面试经历包括四轮电话面试、一轮笔试、一轮主管视频面试、一轮hr视频面试。80%的人都在第一轮电话面试中失败,因为缺乏基础知识。面试问题涉及 ... [详细]
  • 本文介绍了如何使用call_user_func_array函数向Redis中添加有序列表或集合。该函数可以接受一个数组作为参数,第一项是要操作的有序列表或集合的键,后续的项目是排序权重和值的交替。通过该函数,可以方便地向Redis中添加多个元素,并指定它们的排序权重。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • mysql-cluster集群sql节点高可用keepalived的故障处理过程
    本文描述了mysql-cluster集群sql节点高可用keepalived的故障处理过程,包括故障发生时间、故障描述、故障分析等内容。根据keepalived的日志分析,发现bogus VRRP packet received on eth0 !!!等错误信息,进而导致vip地址失效,使得mysql-cluster的api无法访问。针对这个问题,本文提供了相应的解决方案。 ... [详细]
  • 众筹商城与传统商城的区别及php众筹网站的程序源码
    本文介绍了众筹商城与传统商城的区别,包括所售产品和玩法不同以及运营方式不同。同时还提到了php众筹网站的程序源码和方维众筹的安装和环境问题。 ... [详细]
  • ubuntu用sqoop将数据从hive导入mysql时,命令: ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
author-avatar
wang静的天空
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有