m6长宽高-一套能保命的高并发实战指南
你的位置:m6长宽高 > 新闻动态 > 一套能保命的高并发实战指南
一套能保命的高并发实战指南
发布日期:2025-05-22 08:44     点击次数:68

沉默是金,总会发光大家好,我是沉默上篇文章我们聊了:“扛住高并发,得有限流、缓存、异步这些武器。”如果还没看的朋友,可以看看:京东外卖上线就挂了,高并发架构该这么扛!今天这篇,就来把这些武器细细拆开讲透——限流算法怎么选?缓存更新怎么做?消息队列细节怎么踩稳?一篇吃透,真正掌握抵御高并发的底气。-01-限流为什么要限流?想象下:你开一辆小车,在高速路口突然涌来10万辆车,不管不顾往里冲。你的发动机再好、刹车再灵,都必然“嗝屁”。系统也是一样:负载过大,不崩才怪。所以限流,就是设置一道闸门:——来多少车,按节奏、按流速放行,保护后端系统。常见限流算法限流,主要靠两大算法流派:漏桶(Leaky Bucket) 和 令牌桶(Token Bucket)。我们来逐个看看:1. 漏桶算法(Leaky Bucket)坚持匀速,不怕狂风暴雨。原理:系统有一个漏桶,水(请求)不断灌进来。桶底的小洞以固定速率漏水(处理请求)。桶满了,新的水就溢出,直接丢弃。举个栗子🌰:排队办证大厅,一个号一个号叫,叫得再快也要等叫号,急没用。特点总结:

适合场景:后台批处理系统对抖动极为敏感的金融、结算业务2. 令牌桶算法(Token Bucket)灵活发牌,允许短时爆发。原理:桶里定时加入令牌(token)。请求来时,先拿一个令牌,才能被处理。没令牌的请求,要么排队,要么丢弃。举个栗子🌰:麦当劳点单机,后台根据顾客数发小票号,允许一阵快一阵慢。特点总结:

适合场景:电商秒杀系统短时高峰的营销活动漏桶 VS 令牌桶,对比总结

实际工程应用一般系统组合使用:网关层:漏桶,兜住整体流速业务接口:令牌桶,允许高峰弹性再配合限流框架,比如:SentinelNginx限速模块建议:别一味丢请求,高并发系统要做智能限流+友好降级提示。比如:“系统繁忙,请稍后再试。” 而不是直接500爆掉。-02-缓存 为什么缓存是高并发第一护盾?因为内存访问(比如Redis)是纳秒级的,数据库IO是毫秒级的。直接查DB?卡得飞起。打Cache?秒回。所以,缓存搞不好,系统直接废。缓存和数据库常见问题缓存用得多了,必然碰到这些:缓存与数据库数据不一致缓存击穿、穿透、雪崩每一个,都是血泪史。那,怎么做对?常见的缓存更新策略1. Cache Aside(旁路缓存)流程:查缓存 → 缓存没命中 → 查数据库 → 写入缓存更新时 → 更新数据库 → 删除缓存举个栗子🌰:你找车钥匙,先翻抽屉(缓存),找不到再去问爸妈(DB),拿到后用完放回抽屉。优点:简单直观读多写少的场景很适合缺点:写更新期间,可能出现缓存和DB短暂不一致2. Write Through(写穿缓存)流程:写的时候直接同步更新缓存和数据库。举个栗子🌰:新买了车钥匙,马上放抽屉一份,保险箱也一份。优点:保证一致性更好缺点:写入链路变长,性能开销大3. Refresh Ahead(提前刷新)流程:缓存快过期时,自动后台刷新。举个栗子🌰:知道抽屉钥匙快坏了,提前重新配好一把放进去。优点:热点数据持续在线防止击穿缺点:需要定时任务维护缓存一致性怎么搞?要记住一条大原则:更新数据库 → 删除缓存 → 允许下次查询时再重建缓存而不是:更新缓存 → 更新数据库(会乱套)高并发下加一招:延迟双删:第一次删缓存延迟几十ms,再次删缓存(兜住并发写冲突)如何防击穿、穿透、雪崩?防击穿(单热点爆缓存):缓存空对象+短TTL防穿透(查不存在的key):布隆过滤器拦截防雪崩(大批量缓存同时过期):加随机TTL分散过期时间-03-消息队列为什么需要消息队列?因为再快的后端,也扛不住一波洪水直接冲。MQ就像一个缓冲池,把高并发的请求拦下来,慢慢处理。消息队列应用场景秒杀抢购:下单请求排队大促结算:异步写账单积分发放:异步通知MQ用得好,三个关键细节1. 幂等性(Idempotent)MQ消息可能重复发送,如果消费端不防,业务就炸了。解决方案:消费前先查数据库:看操作是否已完成每条消息带唯一业务ID(如订单ID)举个栗子🌰:像快递签收,不能重复签一份。2. 消费重试(Retry)网络闪断、临时异常,导致消费失败。解决方案:设置消费重试机制达到重试上限,打入死信队列(DLQ)举个栗子🌰:快递员三次派件失败,快递放驿站。3. 顺序性保障(Ordering)某些场景(比如库存扣减),消息顺序不能乱。解决方案:同一业务key(如订单ID)哈希分到同一个分区单线程顺序消费举个栗子🌰:像考场排队入场,按准考证号顺序一个个进门。消息堆积怎么处理?当消费跟不上生产:加消费并发(多线程、多实例)限速生产(源头削峰)按优先级消费(重要业务优先)要记住一句话:削峰填谷,才是MQ最大的价值。-04-实战案例项目基本搭建用一个常规 Spring Boot 项目来演示:环境配置:

1. 创建Spring Boot工程选依赖时勾选:Spring WebSentinelRedisRabbitMQMaven pom.xml :<dependencies> <!-- Web服务 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Sentinel限流 --> <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-spring-boot-starter</artifactId> <version>1.8.6</version> </dependency> <!-- Redis缓存 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-redis</artifactId> </dependency> <!-- RabbitMQ消息队列 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency></dependencies>2. Sentinel 接入限流接口安装 Sentinel Dashboard(控制台),运行:java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -jar sentinel-dashboard-1.8.6.jarapplication.yml 配置:spring: cloud: sentinel: transport: dashboard: localhost:8080定义一个简单接口:@RestController@RequestMapping("/order")public class OrderController { @GetMapping("/create") @SentinelResource(value = "createOrder", blockHandler = "handleBlock") public String createOrder() { return "订单创建成功!"; } public String handleBlock(BlockException ex) { return "系统繁忙,请稍后再试~"; }}启动后,去 Sentinel 控制台添加流控规则:资源名:createOrder阈值类型:QPS单机阈值:10(每秒10次)效果:正常流量返回“订单创建成功”超过QPS,返回“系统繁忙”3. Redis 缓存-订单详情Redis配置(application.yml):spring: redis: host: localhost port: 6379服务类:@Servicepublic class OrderService { @Autowired private RedisTemplate<String, String> redisTemplate; private static final String ORDER_CACHE_PREFIX="order:"; public String getOrderDetail(String orderId) { String cacheKey= ORDER_CACHE_PREFIX + orderId; // 先查缓存 Stringdetail= redisTemplate.opsForValue().get(cacheKey); if (detail != null) { return "【缓存命中】" + detail; } // 模拟数据库查询 detail = "订单详情 - " + orderId; // 写入缓存 redisTemplate.opsForValue().set(cacheKey, detail, Duration.ofMinutes(10)); return "【数据库查询】" + detail; }}控制器调用:@RestController@RequestMapping("/order")public class OrderController { @Autowired private OrderService orderService; @GetMapping("/detail/{orderId}") public String getOrderDetail(@PathVariable String orderId) { return orderService.getOrderDetail(orderId); } }测试:第一次查 /order/detail/123,走数据库第二次查 /order/detail/123,走缓存4. RabbitMQ 异步下单application.yml 配置:spring: rabbitmq: host: localhost port: 5672 username: guest password: guest消息模型:队列:order.queue生产者发消息消费者监听并处理创建队列配置:@Configurationpublic class RabbitConfig { public static final String ORDER_QUEUE="order.queue"; @Beanpublic Queue orderQueue() { return newQueue(ORDER_QUEUE, true); }}生产者发送消息:@Servicepublic class OrderProducer { @Autowired private RabbitTemplate rabbitTemplate; public void sendOrder(String orderId) { rabbitTemplate.convertAndSend(RabbitConfig.ORDER_QUEUE, orderId); }}消费者监听处理:@Componentpublic class OrderConsumer { @RabbitListener(queues = RabbitConfig.ORDER_QUEUE) public void handleOrder(String orderId) { System.out.println("接收到订单处理请求:" + orderId); // 异步处理下单逻辑 }}控制器触发异步下单:@RestController@RequestMapping("/order")public class OrderController { @Autowired private OrderProducer orderProducer; @GetMapping("/asyncCreate/{orderId}") public String asyncCreate(@PathVariable String orderId) { orderProducer.sendOrder(orderId); return"订单异步创建中,请稍后查看结果~"; }}测试:调用 /order/asyncCreate/10001控制台打印:“接收到订单处理请求:10001”如果你看到这里,恭喜你已经掌握了一套真正能抗住高并发的硬核武器。后续还会继续带来进阶内容,比如:限流算法原理:漏桶 vs 令牌桶 深度讲解缓存更新策略(旁路、双写一致性、主动刷新)消息队列的消费顺序、幂等性处理秘籍想看的话,在评论区扣个 1!-05-粉丝福利点点关注,送你互联网大厂面试题库,如果你正在找工作,又或者刚准备换工作。可以仔细阅读一下,或许对你有所帮助!



相关资讯