12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀

目录

实战篇22

实战篇23

实战篇24

实战篇25

实战篇26

实战篇27

实战篇28

实战篇29

实战篇30


实战篇22

将任务分布给不同的线程去做,可以加快程序运行速度。

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第1张图片

放到lua脚本,保证原子性。同时,这样的优化,可以减轻数据库的压力。 

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第2张图片  

实战篇23

thinking:sismember?

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第3张图片

thinking:intValue?

intValue的用法_一般社员的博客-CSDN博客

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第4张图片

实战篇24

thinking:阻塞队列?

BlockingQueue:当一个线程尝试在队列里面获取元素时,如果没有元素,线程就会被阻塞,直到队列中有元素,他才会被唤醒并且获取元素

thinking:如何翻译文档或者单词?

IDEA翻译插件Translation配置翻译引擎解决翻译错误的问题_飞牛鱼鱼的博客-CSDN博客

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第5张图片

如果要翻译文档,出现这样的效果

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第6张图片

则鼠标移到文档里面,然后右键,translate documentation

实战篇25

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第7张图片

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第8张图片

实战篇26

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第9张图片

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第10张图片

实战篇27

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第11张图片

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第12张图片

实战篇28

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第13张图片

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第14张图片12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第15张图片

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第16张图片

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第17张图片

实战篇29 

不会漏消息

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第18张图片

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第19张图片 12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第20张图片

 12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第21张图片

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第22张图片

实战篇30

thinking:toString()、String.valueOf()、(String) 强转的区别?

toString()、String.valueOf()、(String) 强转的区别_string.valueof和tostring的区别-CSDN博客

String.valueof()与toString()方法的区别_stringvalueof和tostring_想起飞的张张的博客-CSDN博客

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第23张图片

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第24张图片 thinking:beanutil.fillbeanwithmap?

hutool工具包快速入门_beanutil.fillbeanwithmap-CSDN博客

12.1_黑马Redis实战篇Redis优化秒杀&Redis消息队列实现异步秒杀_第25张图片

package com.hmdp.service.impl;

import cn.hutool.core.bean.BeanUtil;
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 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.connection.stream.*;
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.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 

* 服务实现类 *

* * @author 虎哥 * @since 2021-12-22 */ @Service public class VoucherOrderServiceImpl extends ServiceImpl implements IVoucherOrderService { @Resource private ISeckillVoucherService seckillVoucherService; @Resource private RedisIdWorker redisIdWorker; @Resource private StringRedisTemplate stringRedisTemplate; @Resource private RedissonClient redissonClient; //提前读好这个文件,避免多次读取 private static final DefaultRedisScript SECKILL_SCRIPT; //因为是静态的,因此在静态代码块里面搞 static { SECKILL_SCRIPT = new DefaultRedisScript<>(); SECKILL_SCRIPT.setLocation(new ClassPathResource("seckill.lua")); SECKILL_SCRIPT.setResultType(Long.class); } //private BlockingQueue orderTasks = new ArrayBlockingQueue<>(1024 *1024); //创建线程池 private static final ExecutorService SECKILL_ORDER_EXECUTOR = Executors.newSingleThreadExecutor(); //线程任务 这个要在初始化的时候就要完成了。 @PostConstruct private void init() { SECKILL_ORDER_EXECUTOR.submit(new VoucherOrderHandler()); } private class VoucherOrderHandler implements Runnable { String queueName = "stream.orders"; @Override public void run() { while (true) { try { //1. 获取消息中的订单信息 List> list = stringRedisTemplate.opsForStream().read( Consumer.from("g1", "c1"), StreamReadOptions.empty().count(1).block(Duration.ofSeconds(2)), StreamOffset.create(queueName, ReadOffset.lastConsumed()) ); //2. 判断消息获取是否成功 if (list == null || list.isEmpty()) { //2.1 如果获取失败,说明pending-list没有异常消息,结束循环 break; } //3.解析消息中的订单消息 MapRecord record = list.get(0); Map values = record.getValue(); VoucherOrder voucherOrder = BeanUtil.fillBeanWithMap(values, new VoucherOrder(), true); //4.如果获取成功,可以下单 handleVoucherOrder(voucherOrder); //5.ACK确认 stringRedisTemplate.opsForStream().acknowledge(queueName, "g1", record.getId()); } catch (Exception e) { log.error("处理pending-list订单异常", e); handlePendingList(); try { Thread.sleep(200); } catch (InterruptedException ex) { ex.printStackTrace(); } } } } private void handlePendingList() { while (true) { try { //1. 获取pending-list中的订单信息 List> list = stringRedisTemplate.opsForStream().read( Consumer.from("g1", "c1"), StreamReadOptions.empty().count(1), StreamOffset.create(queueName, ReadOffset.from("0")) ); //2. 判断消息获取是否成功 if (list == null || list.isEmpty()) { //2.1 如果获取失败,说明没有消息,继续下一次循环 continue; } //3.解析消息中的订单消息 MapRecord record = list.get(0); Map values = record.getValue(); VoucherOrder voucherOrder = BeanUtil.fillBeanWithMap(values, new VoucherOrder(), true); //4.如果获取成功,可以下单 handleVoucherOrder(voucherOrder); //5.ACK确认 stringRedisTemplate.opsForStream().acknowledge(queueName, "g1", record.getId()); } catch (Exception e) { log.error("处理订单异常", e); } } } } private void handleVoucherOrder(VoucherOrder voucherOrder) { //获取用户 Long userId = voucherOrder.getUserId(); //创建锁对象 RLock lock = redissonClient.getLock("lock:order:" + userId); //获取锁 //不传参数,代表我失败了立即返回 boolean isLock = lock.tryLock(); //判断是否获取锁成功 if (!isLock) { //获取锁失败,返回错误或重试 log.error("不允许重复下单"); return; } try { proxy.createVoucherOrder(voucherOrder); } finally { //释放锁 lock.unlock(); } } private IVoucherOrderService proxy; @Override public Result seckillVoucher(Long voucherId) { //获取用户 Long userId = UserHolder.getUser().getId(); //获取订单id long orderId = redisIdWorker.nextId("order"); //1.执行lua脚本 Long result = stringRedisTemplate.execute( SECKILL_SCRIPT, Collections.emptyList(), voucherId.toString(), userId.toString(), String.valueOf(orderId) ); //2.判断结果是为0 int r = result.intValue(); if (r != 0) { //2.1 不为0.代表没有购买资格 return Result.fail(r == 1 ? "库存不足" : "不能重复下单"); } //3 获取代理对象 proxy = (IVoucherOrderService) AopContext.currentProxy(); //4. 返回订单id return Result.ok(orderId); } //@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(r ==1 ? "库存不足" : "不能重复下单"); // } // //2.2 为0,有购买资格,把下单信息保存到阻塞队列 // VoucherOrder voucherOrder =new VoucherOrder(); // //2.3 订单id // long orderId = redisIdWorker.nextId("order"); // voucherOrder.setId(orderId); // //2.4 用户id // voucherOrder.setUserId(userId); // //2.5 代金券id // voucherOrder.setVoucherId(voucherId); // //2.6 放入阻塞队列 // orderTasks.add(voucherOrder); // //3 获取代理对象 // proxy = (IVoucherOrderService) AopContext.currentProxy(); // //4. 返回订单id // return Result.ok(orderId); // } @Transactional public void createVoucherOrder(VoucherOrder voucherOrder) { //5,一人一单 Long userId = voucherOrder.getUserId(); //5.1 查询订单 int count = query().eq("user_id", userId).eq("voucher_id", voucherOrder.getVoucherId()).count(); //5.2 判断是否存在 if (count > 0) { // 用户已经购买过了 log.error("用户已经购买过一次"); return; } //6,扣减库存 boolean success = seckillVoucherService .update().setSql("stock = stock - 1") .eq("voucher_id", voucherOrder.getVoucherId()) .gt("stock", 0) .update(); if (!success) { //扣除失败 log.error("库存不足!"); return; } //7,创建订单 save(voucherOrder); } }

你可能感兴趣的:(redis,缓存,java)