高并发应用场景
一、秒杀 / 抢购 / 限时下单最经典核心问题超卖、库存扣减不一致、接口被刷爆、数据库被打挂。实现方案前端限流按钮防抖、验证码、排队页网关层限流Nginx Lua 限流、IP 限流、令牌桶 / 漏桶服务层限流 削峰Sentinel / Hystrix 限流、熔断、降级MQ 异步削峰RabbitMQ/RocketMQ/Kafka缓存层抗流量Redis 预减库存decr缓存商品信息、活动信息数据库最终一致性乐观锁update stock set numnum-1 where id? and num0分布式锁Redisson 防止重复下单兜底策略库存预热、下单失败重试、异步通知、数据对账1. 防止超卖超卖的本质是并发下库存扣减失去原子性用三层防护可以彻底解决用Redis 的 decr 原子命令做预减库存拦截绝大部分无效请求数据库层用乐观锁兜底确保最终扣减安全通过幂等控制和定时对账保证缓存与数据库一致。2. Redis 扣库存和数据库不一致Redis 和数据库库存不一致分四层处理下单超时未完成订单自动回补 Redis库存修改数据库库存后主动删缓存采用延迟双删先删缓存 → 更新数据库 → 延迟一小段时间再删一次缓存保证缓存干净定时任务以数据库为准定时校正 Redis库存业务最终库存判断依赖数据库兜底就算缓存不一致也不会发生超卖。3.消息堆积的处理方法消息堆积的原因有以下几点消费者消费速度 生产者发送速度消费者宕机、重启、报错停止消费消费逻辑太重、同步阻塞、慢 SQL 拖慢消费死信没处理、重试次数过多堵塞队列线上出现消息堆积一般分三步处理紧急扩容消费者节点提升消费能力暂停非核心流量稳住现场优化消费逻辑去掉阻塞慢操作开启批量消费提高吞吐失败消息及时转入死信队列提前做好队列分区拆分、上游限流削峰配上堆积监控告警从源头避免大量堆积保证业务正常流转。4. 分布式锁用 Redlock 还是 Redisson线上高并发场景只用 Redisson 分布式锁不会使用 Redlock。原因如下Redlock 是 Redis 作者提出的强一致性算法但需要 5 套独立 Redis性能差、架构重、生产环境不推荐。Redisson 性能高、自带看门狗自动续期、支持可重入锁主从、集群环境都能稳定运行完全满足秒杀、订单、支付场景。主从切换带来的极小概率锁丢失问题可以通过数据库乐观锁兜底既保证并发性能又保证数据安全。二、 接口高并发优化通用接口性能核心问题QPS 高、RT 高、数据库压力大。优化链路读写分离主库写、从库读多级缓存本地缓存 (如Caffeine) → 分布式缓存(如Redis) → 数据库异步化日志、通知、统计、消息推送全部异步CompletableFuture / MQ批量 并行批量查询、批量插入并行调用下游接口分库分表Sharding-JDBC / MyCat 按用户 ID / 订单 ID 分片索引优化避免回表、覆盖索引、联合索引连接池优化Dubbo、Tomcat、Redis、DB 连接池参数调优1. 多级缓存本地缓存特点内存读取、无网络开销、速度最快存放热点数据、配置、字典、首页热门商品分布式缓存特点跨服务共享、集群统一数据、可持久化存放用户信息、订单、库存、活动数据数据库最终持久化数据源兜底查询数据库更新流程更新数据库 → 删除 Redis 缓存 → 清空本地缓存避免多节点本地缓存脏数据P常见问题本地缓存过期时间设多久普通字典 5~10 分钟热点商品 1~3 分钟保证快速一致性。集群环境怎么保证本地缓存统一更新数据后发消息通知所有服务清除本地缓存。2. 实现异步的几种方式原生 Thread 线程new Thread(() - { // 异步业务 }).start();线程池 ThreadPoolExecutor最基础核心线程、最大线程、队列、拒绝策略Spring 注解异步Async项目最常用启动类加EnableAsync、方法上加Async、返回值用Future获取结果CompletableFutureJDK8 异步高性能首选JDK 自带异步编排支持回调、组合、串行并行CompletableFuture.runAsync(() - { // 无返回异步 }); CompletableFuture.supplyAsync(() - { // 有返回异步 });消息队列 MQ 异步分布式最终异步适用秒杀削峰、订单创建、支付回调、日志、推送、大数据导出P常见问题Async 失效场景同类内部调用、方法私有、无接口、没开 EnableAsyncCompletableFuture 常用方法runAsync、supplyAsync、thenApply、thenCombine、allOf、exceptionally异步如何保证事务异步方法独立事务不能和主线程共用事务异步丢数据怎么办本地异步加异常捕获MQ 异步开启事务消息 重试 死信队列异步和同步区别同步阻塞等待结果异步立即返回后台执行提升吞吐量三、 缓存高并发击穿、穿透、雪崩缓存穿透查不存在的数据 → 缓存空值 布隆过滤器缓存击穿热点 Key 失效 → 互斥锁 / 永不过期 / 逻辑过期缓存雪崩大量 Key 同时过期 → 随机过期时间 集群 降级1. 缓存更新策略Cache Aside PatternCache Aside 是项目最常用旁路缓存策略。读请求先查缓存没命中再查数据库并回填缓存写操作优先更新数据库再删除缓存让下次查询自动刷新。为解决并发脏读问题采用延迟双删优化再配合定时任务定时校正保证缓存最终一致。2. 双写一致性方案最终一致性先更库后删缓存 延迟双删 定时全量刷新。适合商品、订单、用户、秒杀、首页准实时一致用Canal监听 MySQL binlog数据库一旦变更自动推送消息删除 / 更新缓存。无业务侵入性能最好大厂主流强一致性读写加分布式锁同一时刻只允许一个线程读写该数据。优点绝对一致缺点并发降级性能低。适合金额、库存、账务核心数据过期兜底所有缓存统一设置过期时间就算出现脏数据到期自动刷新不会永久不一致3. 常见问题(1) 为什么不更新缓存而是删除缓存高并发连续更新时更新缓存会互相覆盖旧值删缓存让查询主动加载最新数据更安全。(2) 先删缓存再改库有什么问题删完缓存还没改库其他请求查询直接把旧数据写入缓存长期脏数据。(3) 延迟双删延迟多久合适业务正常 RT500ms~1s足够。(4) 高并发秒杀库存怎么保证一致Redis 预扣库存数据库乐观锁最终扣减库存变更删缓存 延迟双删定时任务以数据库为准全量校正 Redis(5) 读写分离架构怎么保证一致写主库删缓存读从库主从存在短暂延迟配合短过期缓存 延迟双删解决。四、 分布式锁高并发场景场景抢券、扣库存、重复支付、重复提交方案Redis 分布式锁SETNX EXPIRE→ Redisson 可重入锁Zookeeper 分布式锁一致性强性能低数据库乐观锁简单场景1. 锁超时了业务还没执行完怎么办用Redisson 看门狗WatchDog自动续期。绝对不要手动把锁超时时间设得很大会导致死锁风险。看门狗核心作用解决业务执行时间 锁过期时间业务还没跑完锁自动释放导致并发乱抢锁的问题原理流程加锁不指定过期时间。业务代码调用lock()无需加锁Redisson 默认给锁设置30 秒过期时间。启动后台看门狗定时线程。加锁成功后自动开启WatchDog 守护线程。定时自动续期。每隔10 秒默认是过期时间 1/3自动把锁续命重置回30 秒。业务执行完毕主动释放锁。代码执行完调用unlock()直接删除锁看门狗停止续期。程序宕机兜底。如果服务突然宕机没人续期锁最多 30 秒自动释放不会死锁。关键细节续期时间为什么是 10 秒默认锁过期 30s取三分之一 10s 续一次预留充足容错时间。指定过期时间还有看门狗吗没有。手动传lock(5, TimeUnit.SECONDS)关闭看门狗到期直接释放不会自动续期。可重入支持吗支持同一个线程多次加锁计数累加释放逐层减不影响续期。主从架构下续期同步吗续期命令同步到从节点保证集群环境锁有效。2. 主从切换锁丢失怎么解决主从切换锁丢失根本原因Redis 主从同步是异步复制客户端在主节点加锁成功锁数据还没同步到从节点主库突然宕机哨兵自动把从库提升为主库新主库无锁数据其他线程可再次加锁出现同一把锁被多人持有并发错乱、超卖解决方案(1)业务层兜底分布式锁只做流量控制不做最终数据判定库存扣减、订单创建、状态修改最终靠数据库乐观锁 / 唯一索引拦截就算锁失效并发进来数据库层面依旧拦得住不会产生资损(2) 强制主从同步 最小同步策略# 搭建 Redis 集群时配置 # 至少同步到 1 个从节点主库才返回写入成功 min-replicas-to-write 1 # 从库最大延迟 5 秒超时认为从库不可用 min-replicas-max-lag 5主库写入锁 key必须至少同步到 1 个从库才返回加锁成功大幅降低主从切换丢锁概率牺牲一点性能换一致性注使用注意点不要配太多从库同步min-replicas-to-write设 1 足够设多严重拖慢并发性能。设置超时时间防止从库宕机卡死主库写入。只给分布式锁这类关键 Key 用普通缓存数据不用强制同步只锁相关 Key 做半同步。(3) Redisson 架构优化优先使用Redis 集群模式而非简单主从锁 key 做哈希槽打散减少单节点故障影响加锁后短时间内重试校验锁状态(4) 极端强一致方案改用红锁 RedLock部署5 个独立 Redis 主节点加锁必须半数以上节点加锁成功才算成功就算一两个节点宕机切换依旧持有锁缺点性能低、成本高秒杀等高并发不推荐五、 高并发下的分页查询高并发下分页查询分场景优化(1) 主键分页最优大数据量首选直接使用limit(2) 延迟关联深分页优化先查主键再关联查数据(3) 书签分页 / 游标分页互联网 APP 主流不用页码只用游标 条数前端传lastId /createTime 作为游标后端用where 条件 游标分页完美适配下拉刷新、滚动加载高并发首选。(4) 分库分表分页先在各分片查出对应页数据内存统一排序、合并、截取避免跨库大偏移(5) 搜索引擎兜底MySQL 只存业务数据分页查询走 ES支持复杂筛选、排序、深度分页性能稳定综上同时限制最大查询页码热门分页做缓存排序字段建立合适索引彻底解决分页越查越慢问题。六、 高并发下的数据导出高并发大数据量导出统一采用异步导出架构(1) 同步改异步禁止接口直接同步导出具体流程如下用户点击导出 → 前端提交导出任务后端落库生成导出任务记录状态待执行立即返回任务提交成功稍后下载后台线程池 / MQ 消费者异步分批查询 写入文件导出完成更新任务状态推送消息 / 短信通知用户用户进入页面直接下载已生成文件(2) 数据库层分配流式查询使用流式查询fetchSize逐条拉取不一次性加载全量按主键 ID / 时间范围分片查询比如每次查 1 万条导出查询强制走只读从库绝不占用主库读写资源拆分时间区间按天、按小时拆分批量导出(3) 文件生成与存储本地临时文件 → 上传对象存储 OSS/MinIO生成CSV优先比 Excel 性能高、占用资源小大文件拆分压缩减少下载流量与耗时(4) 限流 防刷 资源隔离用户维度限流单个用户同一时间只允许 1 个导出任务全局任务限流限制同时运行导出任务数量防止打满线程单独线程池隔离导出任务不占用业务核心线程超时任务自动终止、清理临时文件(5) 超大批量终极方案定时预导出报表、对账数据凌晨低峰提前生成数仓离线导出业务库同步到数仓从数仓拉取数据导出ES 聚合导出日志、订单流水量大走 ES 查询导出