如何让你的系统抗住高并发的流量?

发布时间:2026/6/3 14:25:05

如何让你的系统抗住高并发的流量? 前言如何能让系统抗住高并发流量要考虑的因素有很多但是真的让你讲一下都有哪些很多人肯定就会说用Redis缓存啦用MQ做解耦啦总之就是想起来这一块儿就说一嘴想起来那一块儿也说一嘴总之就是说的不能成体系一些。一般面试官问这种问题的时候是想看你怎么回答有没有从架构的思想去思考这个问题就算有一些具体技术你记得可能不是很熟练了面试官也会相信你是能够解决问题的。这一次就整体来说一下如何让你的系统抗住高并发流量。第一步“拆”在面对高并发的时候第一步永远是拆核心思想就是分而治之。那具体怎么样拆呢服务的拆分与治理服务拆分我们可以把庞大的单体架构根据业务拆分成多个不同的服务这样哪个服务遇到瓶颈了可以单独拎出来进行扩容和优化也不会因为某一个阶段出问题导致整个系统都瘫了。例如一个电商系统按照业务领域拆分成用户、订单、支付、库存这些独立的服务。这样拆分主要是使用分布式架构来降低单点故障的风险提高系统的可伸缩性和性能。服务集群部署虽然说将单体系统拆分成多个系统来分摊了单体架构下容易出现的故障风险但实际上这样的操作只是将单点故障风险分摊到了各个子系统上这样还是存在单点故障风险的。因此需要进行集群部署:将一个服务通过集群进行部署来提升系统整体的吞吐量及响应速度并使用负载均衡技术将请求均衡分配给多个服务器以提高系统的性能和可用性。这样集群部署后让每个服务器都承担一部分的并发和流量提升整体系统的并发能力。服务治理拆服务和集群部署后原先的单体系统变成了多服务多节点的分布式架构了那么如果服务A想调用服务B怎么找到服务B呢当有几十个服务上百个节点并且每个节点的IP变来变去的该怎么治理这些服务呢这就需要一个通讯录用来专门记录每个服务的地址信息也就是注册中心。下面是一些常见的注册中心的对比注册中心CAP 模型健康检查方式多数据中心Spring Cloud 集成典型特点EurekaAP可用性优先客户端心跳30s不支持原生支持轻量、与 Spring Cloud 无缝集成适合入门和中小型项目ConsulCP一致性优先TCP/HTTP/gRPC 主动探测原生支持支持功能最全支持 KV 存储、ACL、DNS 服务等适合多语言、多数据中心场景ZookeeperCP临时节点存活监听需额外配置支持成熟稳定强一致性适合与 Dubbo 等框架配合使用NacosAP/CP 可切换TCP/HTTP/MySQL/自定义支持原生支持阿里开源集成注册中心配置中心 动态 DNS适合云原生和 Spring Cloud 项目那么它们是怎么工作的呢这里可以以Nacos为例服务启动时后端服务自动把自己的 ip、端口注册到 Nacos。调用方通过 Nacos 获取健康实例列表再配合 Ribbon 或者 Loadbalancer 做负载均衡。提到 Nacos 时可以说一下的动态配置管理。高并发下需要动态调整线程参数或者日志级别不用重启服务。Nacos 配置一改全量下发。Nacos 的“动态配置”指的是在应用运行期无需重启服务即可实时推送并生效配置变更的能力。它把“配置”从代码/包内解耦出来集中存储在 Nacos Server并通过 长轮询Long-Polling 版本号对比 机制让客户端在毫秒级感知到变化进而触发本地回调或 Bean 重新绑定实现“热更新”。数据的拆分读写分离、分片读写分离服务进行了拆分如果数据库还是用一个那么瓶颈肯定很容易出现在数据库所以我们可以根据业务场景读多写少/读少写多将数据库进行读写分离这样当读流量大了的时候也不会影响写的效率。读场景商品详情、评论走只读副本写场景下单、支付走主库。但是要做好监控当主从延迟过高时要及时处理。垂直拆分服务进行了拆分如果数据库还是用一个那么瓶颈肯定很容易出现在数据库所以垂直分库是必须的要做到专库专用这样可以解决服务太多数据库连接数太多的问题减少数据库的压力。水平拆分但是如果有的表一年产生上亿条数据并且保持持续增加。数据量真的太大了就不要再总纠结什么索引优化、事务优化这种小打小闹的了这个时候就得上水平分表了落地工具现在首选是 shardingsphere再加上一些自己的实现细节。比如我们利用 shardingjdbc 配置好分片键再通过一致性哈希算法把一张大表拆成一千零二十四张小表均匀分布在不同的物理磁盘上这样就把集中的I/O压力分散了。当涉及到分库分表就有一个绕不过去的问题那就是分布式事务。在单体服务架构下一个Transaction注解就能解决的问题但是在分布式场景下如何解决这里如果能说明白也是一个加分项。因为使用了shardingsphere可以使用数据库的 XA 协议或者引入 Seata用 AT 模式或者 TCC 模式来解决跨库的事务问题。第二步“缓”缓也可以说是缓冲服务和数据库的拆分只是解决了扩展性的问题但如果流量瞬间爆发比如秒杀节日大促数据库还是容易会被打挂。这时候我们就需要第二招缓冲。具体点说就是流量来了我们要挡和削当流量进来的时候可以通过前置措施先挡住一部分然后再将大量的并发请求变成有序的排队请求将服务的压力降下来。读流量处理当读流量很大时我们可以先做一些前置缓存也就是Redis。这一层的核心目标就是过滤无效请求读取热点数据。请求进来之后先别去查库先查 Redis。比如说秒杀场景库存没了直接在 redis 层返回已经售罄数据库根本感觉不到压力。因为加了Redis这个时候就很容易会被问到如果Redis挂了怎么办呢或者有的直接问缓存穿透、缓存击穿、缓存雪崩怎么处理呢缓存穿透大量的垃圾请求数据缓存中没有、DB中也没有查询缓存不存在则流量直接打到DB。解决方案缓存空值对不存在的数据也缓存一个较短时间使用布隆过滤器过滤不存在的数据。缓存击穿高频热点突然过期大量请求击穿缓存请求到DB。解决方案一些热点缓存数据可以不设置过期时间或访问后延长过期时间用一些互斥锁来锁住数据缓存失效时先锁住当从DB中加载完新缓存数据后再释放锁。缓存雪崩大量数据同时失效或缓存出问题了挂掉了。解决方案可以给缓存数据分散的设置过期时间防止同一时间失效热点数据可以不设置过期时间缓存出问题时不能直接打到DB做降级处理缓存集群部署提升可用性降低雪崩风险。写流量处理有了第Redis的缓冲接下来就是第二层MQ的缓冲了因为如果是大量的读请求可以用Redis抗住但是如果是大量的写请呢例如下单请求你如果直接给打到数据库那不但数据库会崩了连请求也都得丢了。这时就可以引入MQ消息队列引入MQ后的逻辑就变成了用户下单后发出一个消息给MQ然后立马返回给客户正在排队这样响应就变快了用户也能及时看到状态变化。订单服务根据自己的消费能力慢慢的从MQ中拉取消息来进行处理这就把高并发变成了低并发。实际落地选型通常来说比较建议Kafka或者是Rocketmq。但Kafka它更加适合像日志采集这些吞吐量极高的场景更多场景我们会习惯用Rocketmq它比较适合金融交易而且它支持事务消息可靠性非常的好。这里在讲到MQ的时候也有时会被问MQ消息如何不丢如何保证不重复消费如何不丢消息发送方只要保证MQ 消息发送成功即可剩下的由MQ自身保证MQ会有持久化以及分片副本机制消息接收方也要保证在真正处理成功消息后再提交offset。如何不重复消费可以在发送方发消息时进行一些防止重复发送的处理消息接收方也要做幂等处理例如用Redis记录消息ID。第三步“防”前面两步是进攻最后这一步就是防守了。如果流量真的超过了系统的物理极限或者某个服务代码写的烂报错了怎么办我们就需要建立一套多维的防御体系核心思路就是层层设防丢卒保帅。第一道防线网关层这是系统的大门我们在这里可以做一些 ip 维度的限流比如用 nginx 限流模块限制同一个 ip 每秒只能访问五次这就能把大部分恶意的爬虫脚本攻击直接挡在门外根本不让他们消耗后端的资源。第二道防线应用层这就是系统的内功了流量进了微服务内部现在推荐可以使用阿里的 Sentinel它比以前的 Hystrix 更强大可以支持控制台的可视化配置。在这里主要做三件事情限流、熔断、降级。限流设置当QPS 超过一千直接拒绝保护服务不被压垮。熔断下游支付服务挂了上游订单服务千万别死等直接熔断防止雪崩。降级大促高峰期把查看历史订单、商品推荐这些非核心业务直接降级返回降级提示或缓存数据把 CPU 和内存全让给下单和支付这些核心业务。限流 使用Sentinel说出来常用的两种限流模式线程数模式秒杀接口最大 300 并发超了直接返回“售罄”。QPS 模式短信接口 1000/s令牌桶匀速通过。熔断使用SentinelSentinel 把“统计窗口 三态熔断器CLOSE、OPEN、HALF_OPEN”做成可插拔的 Slot业务侧只需定义资源和 fallback其余状态流转、阈值判断、超时恢复全部由框架完成真正做到了“零侵入”的熔断保护。在应用层其实还有一招就是异地多活为了保证更极端的情况例如某城市大面积停电或者网络光缆被挖断了。异地多活三地五机房每个库至少两副本Paxos/Raft 保证一致性。任何城市级光纤断30 s 内完成 Leader 重新选主RPO0RTO30 s。复盘

相关新闻