MySQL redis如何实现_Java基于redis和mysql实现简单的秒杀(附demo)

本文详细介绍了如何使用Java、Redis和MySQL来构建一个秒杀系统,重点在于防止超卖和处理未支付订单的库存恢复。通过缓存商品信息和库存,并利用Redis的原子性操作减小数据库压力,确保了秒杀过程的稳定性。
摘要由CSDN通过智能技术生成

一.秒杀业务分析

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

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

商家提交秒杀商品申请,录入秒杀商品数据,主要有:商品标题,商品原价,秒杀价格,商品图片,介绍等信息

运营商审核秒杀申请

秒杀频道首页列出秒杀商品,点击秒杀商品图片可以跳转到秒杀商品详细页面

商品详细页面显示秒杀商品信息,点击立即抢购实现秒杀下单,下单时扣减库存,当库存为0或者不存在活动时间范围内时无法秒杀

秒杀下单成功,直接跳转到支付页面(扫码),支付成功,跳转到成功页面,填写收货、电话、收件人等信息,完成订单。

当用户秒杀下单5分钟内未支付,取消预订单,调用支付的关闭订单接口,恢复库存。

二.数据库设计

商品表:

0cf3cd5025678c00c57c6eb46fbb0ad6.png

订单表:

b390a700e075b6ec967cb0299f611333.png

三.秒杀实现思路

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

}

最终效果:

8123c74c95f90804c877f44744723451.png

91c53b1642e4debccb1c3432518678f5.png

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

四.总结

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

五.完整代码示例

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值