黑马点评实战篇知识点整理-秒杀进阶
异步秒杀思路问题串行执行性能不行查询库存查询订单扣减库存写入订单全是数据库还加了锁性能不行把判断秒杀资格和一人一单放到redis里保存用户id优惠券id订单id到阻塞队列里返回订单id给用户Redis优化秒杀库存string提前扣减订单set一人一单判断有无购买资格无返回1有判断是否满足一人一单不返回2有扣减库存把用户id加入订单set中返回0lua脚本保证原子性开始执行lua脚本判断返回值是否为0不为0返回异常信息为0将用户id优惠券id订单id到阻塞队列里返回订单id给用户package com.hmdp.service.impl; import com.hmdp.dto.Result; import com.hmdp.entity.VoucherOrder; import com.hmdp.mapper.VoucherOrderMapper; import com.hmdp.service.ISeckillVoucherService; import com.hmdp.service.IVoucherOrderService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.hmdp.utils.RedisIdWorker; import com.hmdp.utils.UserHolder; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.aop.framework.AopContext; import org.springframework.core.io.ClassPathResource; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.Collections; import java.util.concurrent.*; Slf4j Service public class VoucherOrderServiceImpl extends ServiceImplVoucherOrderMapper, VoucherOrder implements IVoucherOrderService { Resource private ISeckillVoucherService seckillVoucherService; Resource private RedisIdWorker redisIdWorker; Resource private StringRedisTemplate stringRedisTemplate; Resource private RedissonClient redissonClient; private static final DefaultRedisScriptLong SECKILL_SCRIPT; static { SECKILL_SCRIPT new DefaultRedisScript(); SECKILL_SCRIPT.setLocation(new ClassPathResource(seckill.lua)); SECKILL_SCRIPT.setResultType(Long.class); } private BlockingQueueVoucherOrder orderTasks new ArrayBlockingQueue(1024 * 1024); private static final ExecutorService SECKILL_ORDER_EXECUTOR Executors.newSingleThreadExecutor(); private IVoucherOrderService proxy; PostConstruct private void init() { SECKILL_ORDER_EXECUTOR.submit(new VoucherOrderHandler()); } private class VoucherOrderHandler implements Runnable { Override public void run() { while (true) { try { // 1. 获取队列中的订单信息 VoucherOrder voucherOrder orderTasks.take(); // 2. 创建订单 handleVoucherOrder(voucherOrder); } catch (Exception e) { log.error(创建订单失败, e); } } } } private void handleVoucherOrder(VoucherOrder voucherOrder) throws InterruptedException { // 1. 获取用户id Long userId voucherOrder.getUserId(); // 2. 创建锁对象 RLock lock redissonClient.getLock(lock:order: userId); // 获取锁 boolean isLock lock.tryLock(1L, TimeUnit.SECONDS); // 判断是否获取锁成功 if (!isLock) { // 获取锁失败返回错误或重试 log.error(不允许重复下单); } try { // 获取代理对象事务 // 集群锁不住不可靠 proxy.createVoucherOrder(voucherOrder); } finally { // 释放锁 lock.unlock(); } } Override public Result seckillvoucher(Long voucherId){ // 获取用户 Long userId UserHolder.getUser().getId(); // 1. 执行lua脚本 Long result stringRedisTemplate.execute(SECKILL_SCRIPT, Collections.emptyList(), voucherId.toString(),userId.toString() ); // 2. 判断结果是否为0 int r result.intValue(); if (r ! 0){ // 2.1 不为0没有秒杀资格 return Result.fail(r1?库存不足:不可重复下单); } // 2.2 为0扣减库存生成订单将用户id优惠券id订单id放入阻塞队列中 Long orderId redisIdWorker.nextId(order:); // 2.2.1 生成订单 VoucherOrder voucherOrder new VoucherOrder(); voucherOrder.setId(orderId); // 2.2.2 用户id voucherOrder.setUserId(userId); // 2.2.3 代金券id voucherOrder.setVoucherId(voucherId); // 3.放入阻塞队列 orderTasks.add(voucherOrder); // 4. 获取代理对象 proxy (IVoucherOrderService) AopContext.currentProxy(); // 5.返回订单id return Result.ok(orderId); } Transactional public void createVoucherOrder(VoucherOrder voucherOrder) { // 5. 一人一单 Long userId voucherOrder.getUserId(); // 5.1 查询订单 int count query().eq(voucher_id, voucherOrder.getVoucherId()) .eq(user_id, userId).count(); // 5.2 判断订单是否存在 if (count 0) { // 该用户已经购买过了 log.error(已购买); } // 5. 减少库存 boolean success seckillVoucherService .update() .setSql(stock stock - 1) .eq(voucher_id, voucherOrder.getVoucherId()) .gt(stock, 0) //防止超卖 .update(); if (!success) { log.error(库存不足); } save(voucherOrder); } }问题内存限制问题数据安全问题
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2496782.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!