简易描述秒杀系统的几个主要特点,分布式情况下使用锁,订单超时未支付使用mq的延时队列取消

maven依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.6.3</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.27</version>
</dependency>
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version>
</dependency>
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId><version>2.5.6</version>
</dependency>
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.17.0</version>
</dependency>

application.yml 配置文件

spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.34.7:3306/order?useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSourcedruid:# 下面为连接池的补充设置,应用到上面所有数据源中# 初始化大小,最小,最大initial-size: 15min-idle: 15max-active: 50# 配置获取连接等待超时的时间max-wait: 60000# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒time-between-eviction-runs-millis: 60000# 配置一个连接在池中最小生存的时间,单位是毫秒min-evictable-idle-time-millis: 300000redis:port: 6379database: 0host: 192.168.34.7rabbitmq:host: 192.168.34.7port: 5672virtualHost: /username: adminpassword: adminlistener:direct:#手动ask回复acknowledge-mode: manual
#mybatis plus 设置
mybatis-plus:mapper-locations: classpath*:com/**/mapper/xml/*.xmlglobal-config:# 关闭MP3.0自带的bannerbanner: falsedb-config:#主键类型  0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)";id-type: uuid# 默认数据库表下划线命名table-underline: trueconfiguration:#这个配置会将执行的sql打印出来,在开发或测试的时候可以用log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

RedisSon RabbitMQ的配置

@Configuration
public class RabbitMQConfig {@Bean//支付路由交换机public DirectExchange payOrderDirectExchange(){return new DirectExchange("payOrderDirectExchange",true,false);}@Bean//支付队列public Queue payOrderQueue(){return new Queue("payOrderQueue",true);}@Bean//支付绑定public Binding payOrderBinding(){return BindingBuilder.bind(payOrderQueue()).to(payOrderDirectExchange()).with("payOrder");}@Bean//取消订单路由交换机public DirectExchange cancelOrderDirectExchange(){return new DirectExchange("cancelOrderDirectExchange",true,false);}@Bean//取消订单队列,TTL DLX DLKpublic Queue cancelOrderQueue(){Map<String,Object> map = new HashMap<>();map.put("x-message-ttl",30*60*1000);//过期时间30分钟map.put("x-dead-letter-exchange","cancelOrderDeadDirectExchange");map.put("x-dead-letter-routing-key","cancelOrderDead");return new Queue("cancelOrderQueue",true,false,false,map);}@Bean//取消订单绑定public Binding cancelOrderBinding(){return BindingBuilder.bind(cancelOrderQueue()).to(cancelOrderDirectExchange()).with("cancelOrder");}@Bean//配合取消订单ttl结合的死信路由交换机public DirectExchange cancelOrderDeadDirectExchange(){return new DirectExchange("cancelOrderDeadDirectExchange",true,false);}@Bean//配合取消订单ttl结合的死信队列public Queue cancelOrderDeadQueue(){return new Queue("cancelOrderDeadQueue",true);}@Bean//配合取消订单ttl结合的死信绑定public Binding cancelOrderDeadBinding(){return BindingBuilder.bind(cancelOrderDeadQueue()).to(cancelOrderDeadDirectExchange()).with("cancelOrderDead");}}
@Configuration
public class RedisConfig {@Beanpublic LettuceConnectionFactory lettuceConnectionFactory(){return new LettuceConnectionFactory();}@Beanpublic Redisson redisson(){Config config = new Config();config.useSingleServer().setAddress("redis://192.168.34.7:6379").setDatabase(0);return (Redisson) Redisson.create(config);}@Beanpublic RedisTemplate<String, Object> redisTemplate() {// 配置redisTemplateRedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();redisTemplate.setConnectionFactory(lettuceConnectionFactory());// 设置 RedisConnection 工厂。 它就是实现多种 Java Redis 客户端接入的秘密工厂// 使用 String 序列化方式,序列化 KEY 。redisTemplate.setKeySerializer(RedisSerializer.string());// 使用 JSON 序列化方式(库是 Jackson ),序列化 VALUE 。redisTemplate.setValueSerializer(RedisSerializer.string());return redisTemplate;}
}

模拟分布式情况下秒杀订单生成

    @Autowiredprivate OrderService orderService;@Autowiredprivate RabbitTemplate rabbitTemplate;@Autowiredprivate Redisson redisson;@PostMapping("/saveOrder")@Transactionalpublic String saveOrder(@RequestBody Order order){String shopId = order.getShopId();//使用redisson加锁RLock lock = redisson.getLock(shopId);lock.lock();String id;try {//拿到了锁,库存减1,如果库存是0,就直接return,防止超卖//代码省略。。。。。。。。。id = UUID.randomUUID().toString();order.setOrderId(id);order.setCreateTime(new Date());orderService.save(order);//订单超时未支付自动取消,通过rabbitmq的TTL加死信队列实现rabbitTemplate.convertAndSend("cancelOrderDirectExchange","cancelOrder",id);} finally {lock.unlock();}return id;}/*** 取消订单的监听消费* @param message* @param channel* @throws Exception*/@RabbitListener(queues = "cancelOrderDeadQueue")@Transactionalpublic void cancelOrderListener(Message message, Channel channel) throws Exception {long deliveryTag = message.getMessageProperties().getDeliveryTag();String body = new String(message.getBody(), "UTF-8");try {//订单超时未支付取消//.....代码省略log.info("订单编号 {} 已取消 ",body);channel.basicAck(deliveryTag,false);}catch (Exception e){//手动ask回复,可以配合缓存增加重试次数channel.basicReject(deliveryTag,false);throw new RuntimeException("cancelOrderListener Exception",e);}}

模拟订单支付后操作

    @GetMapping("/pay")public String pay(String id){log.info("{} 订单支付了",id);//mq修改订单状态,并发送物流等信息rabbitTemplate.convertAndSend("payOrderDirectExchange","payOrder",id);return "success";}/*** 保存订单,通知物流* @param message* @param channel* @throws Exception*/@RabbitListener(queues = "payOrderQueue")@Transactionalpublic void payOrderListener(Message message, Channel channel) throws Exception {long deliveryTag = message.getMessageProperties().getDeliveryTag();String body = new String(message.getBody(), "UTF-8");try {//1.订单状态修改//2.发送物流信息//..............代码忽略channel.basicAck(deliveryTag,false);}catch (Exception e){//手动ask回复,可以配合缓存增加重试次数channel.basicReject(deliveryTag,false);throw new RuntimeException("payOrderListener Exception",e);}}

springboot 模拟秒杀 分布式锁 以及 延时取消未支付订单相关推荐

  1. Redis key过期事件监听实现 - 30分钟自动取消未支付订单

    目录 一.前言 二.实现方案分析 三.Redis key过期事件方案实现步骤 3.1 Redis 安装步骤详见 3.2 修改 Redis 配置 3.3 在获取支付链接视图中设置key过期事件 3.4 ...

  2. 视频教程- 19年录制Redis实战教程 高可用秒杀分布式锁布隆过滤器实战 SpringBoot教程整合-Java

    19年录制Redis实战教程 高可用秒杀分布式锁布隆过滤器实战 SpringBoot教程整合 7年的开发架构经验,曾就职于国内一线互联网公司,开发工程师,现在是某创业公司技术负责人, 擅长语言有nod ...

  3. SpringBoot实战实现分布式锁一之重现多线程高并发场景

    实战前言:上篇博文我总体介绍了我这套视频课程:"SpringBoot实战实现分布式锁" 总体涉及的内容,从本篇文章开始,我将开始介绍其中涉及到的相关知识要点,感兴趣的小伙伴可以关注 ...

  4. java实现订单未支付失效_未支付订单30分钟后,自动取消

    未支付订单30分钟后,自动取消 生成订单时发起延时30分钟的任务 /** * 取消订单的任务 * @Title: startCancelOrderTask * @Description: 取消订单的任 ...

  5. springboot 集成redission分布式锁

    Springboot整合Redisson 锁 一.依赖 <dependency><groupId>org.redisson</groupId><artifac ...

  6. springboot整合Redis分布式锁最佳实践

    什么是分布式锁 在单机环境中,一般在多并发多线程场景下,出现多个线程去抢占一个资源,这个时候会出现线程同步问题,造成执行的结果没有达到预期.我们会用线程间加锁的方式,比如synchronized,lo ...

  7. springboot(十二)-分布式锁(redis)

    什么是分布式锁? 要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁.进程锁. 线程锁:主要用来给方法.代码块加锁.当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段.线程锁只在同一 ...

  8. SpringBoot整合redisson分布式锁

    1.为什么要使用分布式锁 在分布式场景下为了保证数据最终一致性.在单进程的系统中,存在多个线程可以同时改变某个变量(可变共享变量)时,就需要对变量或代码块做同步(lock-synchronized), ...

  9. SpringBoot 使用 Redis 分布式锁解决并发问题

    问题背景 现在的应用程序架构中,很多服务都是多副本运行,从而保证服务的稳定性.一个服务实例挂了,其他服务依旧可以接收请求.但是服务的多副本运行随之也会引来一些分布式问题,比如某个接口的处理逻辑是这样的 ...

最新文章

  1. 你自己不优秀,认识谁都是个屁
  2. 通过index索引定位
  3. GDB动态库搜索路径
  4. 十四届恩智浦智能车竞赛双车组-星夜兼程队2019回顾
  5. Python 正则表达式详解(建议收藏!)
  6. 免费url长网址缩短压缩工具评测,短链接在线生成器推荐。
  7. 服务器防火墙开启导致无法远程连接解决方案
  8. vue 中 vue-print-nb 表格打印不全的问题
  9. U盘在手,忘记任何密码都可找回!!
  10. SRS源码阅读(一)
  11. 一本通 1335:【例2-4】连通块
  12. 雷锋网的那些段段(一)。
  13. java二进制计算_Java 二进制,八进制,十进制,十六进制转换运算
  14. 自己动手提高ubuntu性能
  15. Matlab 2018a与SolidWorks联合仿真——如何将SolidWorks模型以xml格式导出至Matlab中
  16. ojbk的sas proc 过程之transpose
  17. html最常用6个标签,1-1-6【HTML基础】HTML常用标签2
  18. WARN [Consumer clientId=consumer-console-consumer-22243-1, groupId=console-consumer-22243] Bootstrap
  19. dameware 客户端安装必备条件
  20. 资产定价核心等式及其应用

热门文章

  1. python爬虫之Scrapy框架--保存图片(详解)
  2. 抹去 CSDN 中图片水印的方法
  3. ABAP 数字转换中文大写数字的方法
  4. github上传文件遇到错误:kex_exchange_identification: read: Software caused connection abort banner exchange:
  5. Kaptcha 验证码 无噪点 无干扰线 配置
  6. 直觉就是小路神经系统
  7. Kali Linux Web扫描工具:Arachni安装使用教程(图文并茂哦)
  8. 2021海南二级造价师报名条件
  9. 上班族如何抓住风口增加额外收入
  10. 聚合数据入选2021年江苏省大数据产业发展试点示范项目名单