(注:代码大部分来自黑马点评资料,稍加修改)
lua:
local voucherId=ARGV[1]
local userId=ARGV[2]
local stockKey='seckill:stock:'..voucherId
local orderKey='seckill:order:'..voucherId
if(tonumber(redis.call('get',stockKey))<=0) then
return 1
end
if(redis.call('sismember',orderKey,userId)==1) then
return 2
end
redis.call('incrby',stockKey,-1)
redis.call('sadd',orderKey,userId)
return 0
VoucherOrderServiceImpl:
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {
@Resource
private ISeckillVoucherService seckillVoucherService;
@Resource
private RedisIdWorker redisIdWorker;
@Resource
private StringRedisTemplate stringRedisTemplate;
IVoucherOrderService proxy_plus;
private static final DefaultRedisScript<Long> SECKILL_Script;
static{
SECKILL_Script=new DefaultRedisScript<>();
SECKILL_Script.setLocation(new ClassPathResource("seckill.lua"));
SECKILL_Script.setResultType(Long.class);
}
private BlockingQueue<VoucherOrder> orderTasks =new ArrayBlockingQueue<>(1024 * 1024);
private static final ExecutorService SECKILL_ORDER_EXECUTOR=Executors.newSingleThreadExecutor();
@PostConstruct
private void init(){
SECKILL_ORDER_EXECUTOR.submit(new VoucherHandler());
}
private class VoucherHandler implements Runnable{
@Override
public void run() {
while(true){
try {
//从阻塞队列获取预备订单
VoucherOrder voucherOrder = orderTasks.take();
//处理预备订单
proxy_plus.createVoucherOrder_plus(voucherOrder);
} catch (Exception e) {
log.error("处理订单异常...");
}
}
}
}
@Transactional
public void createVoucherOrder_plus(VoucherOrder voucherOrder){
seckillVoucherService.update()
.setSql("stock=stock-1")
.eq("voucher_id", voucherOrder.getVoucherId()).gt("stock",0)
.update();
save(voucherOrder);
}
@Override
public Result seckillVoucher(Long voucherId) {
//执行lua
Long userId = UserHolder.getUser().getId();
Long result = stringRedisTemplate.execute(
SECKILL_Script,
Collections.emptyList(),
voucherId.toString(), userId.toString()
);
int r=result.intValue();
//不能购买
if(r==1){
return Result.fail("库存不足!");
}
if(r==2){
return Result.fail("不能重复购买!");
}
//能购买
VoucherOrder voucherOrder=new VoucherOrder();
long orderId = redisIdWorker.nextId("order");
voucherOrder.setId(orderId);
voucherOrder.setUserId(UserHolder.getUser().getId());
voucherOrder.setVoucherId(voucherId);
orderTasks.add(voucherOrder);
proxy_plus=(IVoucherOrderService) AopContext.currentProxy();
return Result.ok(orderId);
}
}
IVoucherOrderService:
void createVoucherOrder_plus(VoucherOrder voucherOrder);