springboot+支付宝完成秒杀项目的初体验
2020-12-13 06:05
标签:runnable 原理 键值 time() between 目的 热备 签名 接下来 当用户抢购时,进入并调用后端服务,这时候首先在redis中设置商品的键值对,然后读出redis中该商品的秒杀时间和数量,当满足条件时,更新redis中该商品的数量并在redis中生成订单。(这里用到了redis的锁,当这个商品的键没有时,则提交事物,当有时则不提交事物) 这时候通过线程来判断该商品是否在一分钟之内付款,付款失败则将商品?1,好让商品继续可以被秒杀。 同时,为了防止该商品在事物过程中发生错误,导致该商品一直锁住,所以使用了try catch finally代码块,在finally中释放该锁,即是删除该键值对。 利用任务系统查询当日秒杀商品业务: springboot+支付宝完成秒杀项目的初体验 标签:runnable 原理 键值 time() between 目的 热备 签名 接下来 原文地址:https://www.cnblogs.com/tanyiming/p/11165515.htmlspringboot+支付宝完成秒杀项目的初体验
思考的问题:
首先是秒杀的商品查询,考虑到是热点数据,所以写一个接口读取当日批次的秒杀商品到redis中(那么接下来对商品的操作都放入redis中)。
当用户抢购商品时,考虑到的是是否在秒杀时间段内以及商品是抢完的问题。首先需要判断该商品是否在秒杀时间内,然后要查询该商品数量是否足够。当然这些还不够,还要有为了防止高并发的解决方案:
###最主要的还是数据库的读写问题,强一致问题
核心代码如下:
public AppResult FindSkProduce() {
//找到今日打折的商品放入redis中
//条件 状态为1 数量大于0 在指定时间内
//用hash(Map)存储 大键为cs1901_sk 小键为商品id 值为商品对象
String s= DateUtils.getCurrentDate();
String s1 = s + " 00:00:00";
String s2 = s+ " 23:59:59";
Date date1 = DateUtils.stringToDate(s1,DateUtils.DATE_TIME_FORMAT);
Date date2 = DateUtils.stringToDate(s2,DateUtils.DATE_TIME_FORMAT);
TbSeckillGoodsExample example=new TbSeckillGoodsExample();
example.createCriteria().andEndTimeBetween(date1,date2).andStatusEqualTo("1").andNumGreaterThan(0);
List
秒杀业务:
public AppResult CreateSkOrder(Long pid) {
//创建订单
//用redis的锁 锁住 该商品(在redis中查出该商品)
//原理:redis 先设置唯一键 , 用redis 的事物和提交 ,再提交之前判断唯一键是否存在
//watch(key) 若有该唯一键 则不提交事物,无则提交事物
RedisLock redisLock=new RedisLock(redisTemplate,"lock"+pid);
try {
//事物
//生成订单之前的判断:1 判断秒杀是否过期 2 判断商品数量是否足够
//生成订单:1 生成唯一ID 将redis中的该商品数量减一 更新进redis
// 2 生成订单 redis设置键位 大键为cs1901_sk_order 小键为订单id 值为订单
//若抛出异常在finally中解锁 防止商品被锁死
//新建线程 若一分钟未付款删除订单
//用 thread
//1 判断秒杀是否过期
HashOperations hashOperations=redisTemplate.opsForHash();
TbSeckillGoods tbSeckillGoods= (TbSeckillGoods) hashOperations.get("cs1901_sk",pid+"");
if (redisTemplate.hasKey("cs1901_sk")==false){
throw new AppExeption(200,"秒杀时间已过");
}
//2 判断商品数量是否大于0
if (tbSeckillGoods.getNum()
支付宝创建订单:
@GetMapping("/pay/createsk/{orderid}")
public void createsk(@PathVariable("orderid") Long orderid , HttpServletResponse response) throws Exception {
//System.out.println(orderid+":"+total);
//获得初始化的AlipayClient(生成支付宝客户端)
AppResult result = payService.createSkPay(orderid,1L);
if(result.isSuccess()==true){
//把支付宝返回给我们的字符串 打印到客户端的浏览器
response.getWriter().println(result.getData());
}else{
response.getWriter().println(result.getMessage());
}
}
支付成功同步回调:
@PostMapping("/asynonotice")
@ResponseBody
public String asynonotice(HttpServletRequest request) throws Exception {
// 1: 获得支付宝返回的消息
System.out.println("异步回调");
String result = null;
Map
支付成功异步回调:
@PostMapping("/sk/syncnotice")
@ResponseBody
public String sksyncnotice(HttpServletRequest request) throws Exception {
String result = null;
// 1: 获得支付宝返回的消息
Map