当前位置: 首页 > news >正文

预约优化方案全链路优化实践

预约是高频需求,但很多团队初期会用 “MySQL 直连 + 同步流程” 快速落地,后续却难免踩坑:早高峰抢预约时库存超卖、接口响应卡到几秒、节假日调休要改代码重启

我在项目中基于 SpringBoot+RabbitMQ+Redis,做了套轻量优化方案:既搞定了库存准确性、接口速度、节假日维护这些核心痛点,又不用额外学习重技术。

在这里插入图片描述

一、传统单个系统设计的核心不足

在未优化的单个 SpringBoot 系统中,印章预约功能会因 “同步阻塞、数据竞争、规则僵化” 导致一系列问题,具体如下:

  1. 库存超卖:全靠 MySQL 直接扣减库存,高并发下多线程同时修改同一库存,易出现 “库存为负”(比如库存 1,两人同时预约都成功),业务规则失效。
  2. 节假日维护繁琐:节假日、调休规则硬编码在代码中(如if (date == “2024-10-01”)),每次调休需改代码、重启系统,重启期间功能不可用。
  3. 定时任务阻塞业务:每日初始化库存的定时任务(如 20:00 更新未来库存)若 “全量一次性执行”,会占用系统主线程,导致用户预约时接口卡顿甚至超时。
  4. 接口响应慢:预约流程中同步执行 “查库存 + 生成订单 + 发通知 + 写日志”,单接口耗时常超 1 秒,用户体验差。
  5. 数据库压力大:查可预约日期、库存等高频操作直接访问 MySQL,高峰期(如早 8 点抢预约)数据库 QPS 被打满,系统整体卡顿。

二、优化后的方案设计(核心:RabbitMQ 异步解耦 + 分层控制)

1. 整体逻辑

单个系统内通过 “定时任务预加载 + Redis 缓存提速 + RabbitMQ 异步削峰 + MySQL 兜底”,解决传统方案的痛点,
流程如下:用户选日期→查可预约时段(Redis 缓存)→提交预约→Redis 扣库存→发 MQ 消息→生成订单→MQ 异步处理后续操作(更新 MySQL 库存、发通知)

2. 核心模块设计(带关键实现说明)


(1)每日 20:00 定时任务:预加载节假日 + 初始化库存**

  • 解决问题:节假日规则僵化、定时任务阻塞业务。
  • 同步节假日:调用阿里云万年历 API,拉取未来 3 个月的 “日期 + 是否节假日 + 是否调休” 数据,存到sys_holiday表,并缓存到 Redis(供用户查询可预约日期)。
  • 初始化库存:按 “未来 7 天 + 每个时段” 分批生成库存数据(如某时段最多约 5 人,库存设为 5),存到seal_stock表,并同步到 Redis(key=seal:stock:{日期}:{时段ID})。
  • 实现技巧:用@Scheduled定时触发,通过CompletableFuture分批异步执行(每天库存单独处理),避免阻塞主线程。

(2)库存控制:Redis 原子操作 + MySQL 乐观锁

  • 解决问题:库存超卖、数据库压力大。
  • 预约前校验:用户提交预约时,先查 Redis 库存(GET seal:stock:{日期}:{时段ID}),若≤0 直接提示 “约满,并且前端打灰”。
  • 扣减库存
    1. Redis 的DECR原子操作扣减库存(高并发下保证不超卖);
    2. 扣减成功后,发送 “库存更新” 消息到 RabbitMQ 队列(如seal.stock.update);
    3. MQ 消费者接收消息,用 MySQL 乐观锁更新库存表(UPDATE seal_stock SET remaining_num=remaining_num-1, version=version+1 WHERE ... AND version=?),保证最终一致性。

(3)异步解耦:RabbitMQ 处理慢操作

  • 解决问题:接口响应慢、同步流程阻塞。
  • 核心流程同步化:仅保留 “Redis 查库存→扣库存→生成订单” 为同步逻辑(耗时≤50ms)。
  • 慢操作异步化
    预约成功后,发送 “订单通知” 消息到 RabbitMQ 队列(如seal.notice);
    MQ 消费者接收消息,异步执行 “发短信通知、写操作日志” 等耗时操作(无需用户等待)。
    RabbitMQ 关键配置:
// 1. 生产者:发送消息
@Service
public class AppointmentService {@Autowiredprivate RabbitTemplate rabbitTemplate;public void submitAppointment(...) {// ... 同步生成订单 ...// 发通知消息rabbitTemplate.convertAndSend("seal.notice", orderId);}
}// 2. 消费者:处理消息
@Component
public class NoticeConsumer {@RabbitListener(queues = "seal.notice")public void handleNotice(Long orderId) {// 发短信、写日志(异步执行,不阻塞接口)smsService.send(orderId);logService.record(orderId);}
}

(4)缓存提速:Redis 存储高频数据

  • 解决问题:数据库压力大、查询慢。
    缓存 “节假日规则”(key=holiday:{日期})、“可预约时段配置”(key=timeSlot:{印章ID})、“实时库存”(key=seal:stock:{日期}:{时段ID})
    用户查可预约日期、时段时,直接读 Redis,避免频繁访问 MySQL。

(5)防重复预约:MySQL 唯一索引

  • 解决问题:用户误操作导致重复预约。
    seal_appointment表加唯一索引:UNIQUE KEY uk_user_seal_date (user_id, seal_id, appointment_date)
    重复提交时,MySQL 会报 “唯一索引冲突”,系统捕获异常并提示 “已预约,无需重复操作”。

三、方案优势

  • 无超卖:Redis 原子操作 + MySQL 乐观锁,双重保障库存准确性;
  • 接口快:核心流程同步 + RabbitMQ 异步解耦,响应时间压缩至 50ms 内;
  • 易维护:节假日自动同步,无需改代码;定时任务分批执行,不阻塞业务;
  • 抗并发:Redis 缓存减轻数据库压力,支持高并发场景(如早8 点抢预约,但是我们是zf项目,使用人数还不注意去抢预约,但是这个方案可以用于其他场景);

这篇博客只是讲解优化思路,可以设计的具体代码和详细的数据库设计

http://www.dtcms.com/a/442751.html

相关文章:

  • Linux指令(1)
  • TS学习笔记
  • 上海建设银行官方网站有关网站排名的论文
  • Zabbix对决Prometheus:监控系统终极对比
  • 【ROS2学习笔记】 TF 坐标系
  • 如何给网站绑定域名邢台推广公司
  • AgentLightning浅读
  • 友情链接对网站的作用喜茶vi设计手册
  • 开通企业网站需要多少钱wordpress添加m3u8播放器
  • 广义可逆计算 (Generalized Reversible Computation): 一个软件构造范式的正名与阐释
  • js网站开发视频教程北京自己怎样做网站
  • 稠密检索模型(Dense Retrieval Model)
  • 东莞网站建设员天长网站制作
  • 【精品资料鉴赏】361页word详解绿色智慧校园建设方案
  • 深圳哪家网站建设公司好万江仿做网站
  • 爱空间网站模板淘宝网官方网
  • 在云服务器中下载和使用Navicat连接mysql数据库
  • 优化算法研究Beale函数
  • 用万网做网站龙岗网站建设公司
  • roboguide如何显示或关闭寄存器或 IO 的注释信息
  • 公司电商网站开发方案数学网站建设方法
  • 网站开发与设计实训报告心得营销型网站建设的目标是
  • 建网站没有公司资质wordpress 下载远程图片
  • 网站建设与管理课程的目标织梦+和wordpress
  • 上国外网站哪个dns快网站查询平台官网
  • wordpress建站环境国内网络科技网站建设
  • 2025年渗透测试面试题总结-101(题目+回答)
  • 免费做网站. 优帮云上海公司招聘信息
  • K8s集群CNI升级:Calico3.28.2安装全攻略
  • 常州市城乡建设局网站网站内容和功能清单