ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

互联网后端必备的10个基础组件:从MySQL到监控日志

互联网后端必备的10个基础组件:从MySQL到监控日志 做后端开发这些年我见过太多项目一开始是散装起步的。数据库裸奔、缓存靠本地 map、服务间直连、日志靠 print、没人看监控……等用户量和请求量上来各种问题扎堆冒出来最后只能周末加班重构。其实这些问题几乎都能靠一套标准化的基础组件体系提前规避。所谓互联网后端的 10 个基础组件就是我这些年总结下来的“后端标配”MySQL、Redis、Elasticsearch、Nginx、注册中心、API 网关、消息队列、对象存储、定时任务调度、监控与日志系统。这篇内容适合刚转后端的同学建立全局视角也适合正在做架构梳理的团队拿来当对照清单。我会把每个组件说清楚它解决什么问题、核心原理长什么样、实际部署的时候有哪些关键参数以及最容易踩的坑是什么。1. 为什么后端绕不开这 10 个组件1.1 从一次用户请求看组件的分工要理解这 10 个组件为什么会成为互联网后端的“标准件”最好的方式不是背概念而是跟着一次真实请求走一遍。假设用户在小程序里点了一下“提交订单”。请求最先到达的是 Nginx它把流量转发到内网接着 API 网关接住请求做统一鉴权、限流然后按路由规则把请求转发到订单服务的某个实例。订单服务启动的时候把自己注册到了注册中心网关正是从注册中心拿到了一份可用的服务实例列表才知道该把请求打给谁。进入业务代码后订单服务先查 Redis 缓存里有没有商品信息没有再去查 MySQL下单成功后会往消息队列里发一条“订单已创建”的消息通知积分服务、库存服务、短信服务各自去干活。用户上传的头像、图片验证码这些非结构化数据则统一扔进对象存储。整个过程产生的接口日志、业务日志会被采集到日志系统每个节点的 CPU、内存、QPS、延迟则被监控系统盯得死死的每天早上八点给用户推优惠券的活则交给分布式定时任务调度平台。你看10 个组件各管一段又互相配合。它们的共性是不直接写业务逻辑但业务系统离开任何一个都会很难受。组件核心职责常见产品MySQL持久化存储业务数据MySQL 8.x、Percona、TDSQLRedis缓存、计数器、分布式锁Redis 6.x、RedissonElasticsearch搜索、日志分析、聚合查询ElasticsearchNginx反向代理、负载均衡、静态资源Nginx、OpenResty注册中心服务注册与发现、配置下发Nacos、etcd、ConsulAPI 网关统一入口、鉴权、限流、灰度Spring Cloud Gateway、APISIX消息队列异步解耦、削峰填谷Kafka、RocketMQ、RabbitMQ对象存储海量文件与静态资源存储云 OSS、MinIO定时任务周期性任务调度与分片执行XXL-Job、PowerJob监控与日志可观测性、告警、排查Prometheus、Grafana、ELK、Loki1.2 选型的底层逻辑别追新追稳很多新人问为什么必须选这些组件有没有替代品当然有但互联网行业经过十几年沉淀每个领域都已经跑出了几个“经过大规模验证”的默认选项。选型时我通常只看三件事团队能不能运维、成本扛不扛得住、生态熟不熟。自建 Kafka 和直接用云上的 MQ 各有取舍自建要养维护人力上云要花真金白银开源组件最怕的是有 Bug 没人修所以尽量选大厂开源或者社区活跃的项目。还有一点很容易被忽略如果你团队的主力语言是 Java那 Spring Cloud Gateway、RocketMQ、Nacos 这些 Java 生态的组件会更顺手如果团队偏 Goetcd、Kafka、Consul、APISIX 可能更自然。基础组件是给业务系统打底子的最重要的属性是稳定而不是看起来新潮。用业界默认方案能搜到最多的踩坑文章能招到最熟悉的人这才是最大的成本优势。2. 数据三件套MySQL、Redis、Elasticsearch2.1 MySQL所有业务数据的最终归宿先说数据库。互联网后端可以没有很多中间件但绝大多数业务最终都长在 MySQL 上或者至少把 MySQL 作为核心数据源之一。选它不是因为性能天花板高而是因为关系模型、事务和 SQL 生态这三样东西太适合业务系统了。MySQL 的底层存储引擎我基本只看 InnoDB。它支持事务ACID、行级锁、崩溃恢复B 树索引结构把随机读写变成了相对可控的磁盘访问。B 树的好处是所有叶子节点在同一层数据有序存储范围查询和排序都很友好它还有双向链表天然适合走索引扫区间。理解这一点你就明白为什么主键那么关键主键决定了数据在 B 树里的物理顺序如果主键是无序的 UUID数据插入会导致页分裂写性能和空间利用率都会下降。实际部署中有几个点比引擎更值得关注主键别用 UUID自增 ID 或雪花 ID 都行。雪花 ID 还能避免分库分表后的全局唯一性问题。索引不是越多越好联合索引要遵循最左前缀原则。比如建了(user_id, status)查询条件里只有status是走不上这个索引的。连接池别乱调。很多人一看连接池默认 8 就往上加加到几百结果数据库线程被拖垮。连接数是给业务用的不是越大越快。慢查询日志必须开。long_query_time设 1 秒定期把慢 SQL 拿出来打磨这是数据库运维里投入产出比最高的一件事。我在真实项目里踩过最重的坑是什么是无脑分库分表。单表数据量几十万其实连索引优化都还没做到位就把订单表拆成 64 张结果跨库查询、分布式事务、全局 ID、数据迁移一个个全来了。分库分表真的应该放到最后一步先试索引优化、归档冷数据、升级硬件、读写分离扛不住了再分。2.2 Redis把热数据扛在肩上Redis 能火核心原因是快。它把所有数据放在内存里又用了单线程事件循环加 I/O 多路复用避免锁竞争和线程切换开销。这个“单线程”常让新人误会其实 Redis 6 之后某些子命令也有多线程但主线程处理命令依然是单线程所以它天生适合做缓存、计数器、排行榜、分布式锁这些对延迟极度敏感的场景。部署上首先要搞懂持久化。RDB 是周期性快照恢复快但可能丢最近一段时间的数据AOF 是追加写日志最多丢几秒但文件大、重写开销高。生产一般是 AOF RDB 组合业务允许少量丢失就把appendfsync设成everysec既兼顾性能又不会丢太多数据。高可用方面主从复制加哨兵是入门标配哨兵负责故障自动切换数据量大了要分片再上 Redis Cluster。使用 Redis 一定会遇到三个“缓存经典问题”缓存穿透查询一个根本不存在的 key每次都打到数据库。解决用布隆过滤器挡一层或者缓存空值。缓存击穿某个热点 key 刚好过期大量请求瞬间压到数据库。解决用互斥锁重建缓存或者逻辑过期。缓存雪崩大量 key 在同一时间过期或者 Redis 整体宕机。解决是过期时间加随机值、做多级缓存关键业务接口加本地进程缓存兜底。还有一个新人必踩的坑是 Big Key。一个 string 存了几 MB 的序列化对象读它的时候主线程处理时间长其他命令全部排队删除大 key 也可能阻塞 Redis。线上要定期用redis-cli --bigkeys扫描发现大 key 及时拆分。记住一个边界Redis 是缓存/加速器不是主存储。它的持久化机制决定了极端情况下会丢数据拿它存核心订单状态出事就是大事故。2.3 Elasticsearch把“找东西”变成秒级响应业务量上来之后你会遇到两类搜索问题。第一类是“电商需求帮我按关键词搜商品、按价格排序”第二类是“排查需求帮我把最近一小时的错误日志过滤出来”。用 MySQL 的LIKE %关键词%去做数据量一大就性能崩盘这时候就得请出 Elasticsearch。ES 的核心是倒排索引。普通数据库正排索引是“文档 → 关键词”倒排索引反着来“关键词 → 包含它的所有文档 ID”。搜索时先查词项再拿到文档列表速度跟命中文档数相关而不是跟全表数据量强相关。所以它在全文搜索、聚合统计、日志分析上特别能打。它会把数据分到多个分片shard每个分片又是一个完整的 Lucene 索引分布在集群节点上副本分片则提供高可用和查询吞吐。建索引的时候有个原则mapping 一旦建好字段类型就不能改了。我见过最典型的错误是把订单金额字段定义成了text然后发现无法做范围查询只能重建索引。所以设计 mapping 要谨慎需要精确匹配和范围查询的字段用keyword或long需要分词搜索的字段用text中文搜索要配好 IK 分词器和自定义词典。写入数据时ES 要走“主分片 → 副本分片”的复制流程频繁的 update/delete 会产生大量段合并开销所以它特别不适合做高频强一致更新。深分页也有坑from size超过一万就会性能断崖正确姿势是用search_after或滚动查询。更本质的认知是ES 不是“另一个数据库”它是搜索与分析引擎。你需要保证 MySQL 是事实源ES 是同步出来的检索视图。数据同步可以用 Canal 监听 binlog也可以直接用消息队列的异步事件来更新索引别想着让业务在 ES 上跑事务。3. 流量接入与服务治理Nginx、注册中心、API 网关3.1 Nginx反向代理与负载均衡的第一道门Nginx 是互联网后端的“迎宾”。它站在最前面用户流量先进它再由它转发给内部的网关或服务。为什么几乎所有团队都用它因为性能好、配置灵活、稳定性极高处理静态文件、做反向代理、做负载均衡一件不落。要理解 Nginx先把正向代理和反向代理分清楚。正向代理代理的是客户端比如你开着代理去访问外部网站外面只看到代理服务器的 IP反向代理代理的是服务端客户端只知道 Nginx 的地址它把请求分发到后面的多台业务服务器。Nginx 就是典型反向代理它的 upstream 支持多种负载均衡算法默认的 round-robin 轮询、按客户端 IP 散列的 ip_hash、按最少连接数的 least_conn。大部分场景轮询就够用了如果需要同源请求进同一台实例处理ip_hash 会方便些。实际配置里最容易写错的是proxy_pass带不带斜杠# 不带斜杠保留原始 URI 中的 /api/xxx proxy_pass http://backend; # 带斜杠把 location 匹配部分替换掉 # location /api/ { proxy_pass http://backend/; } # 访问 /api/user 实际转发到 /user这一条我起码见过五六个人在这里踩过坑。线上改配置前一定要先跑nginx -t校验语法再reload平滑重载不要直接 restart否则连接会瞬间中断。worker_processes一般设为 CPU 核数worker_connections决定单进程能扛的连接数如果服务端要同时处理大量长连接还要调keepalive_timeout和 upstream 的 keepalive 连接池。Nginx 适合做 L4/L7 层的流量分发、TLS 卸载和静态资源缓存但千万别在里面写复杂业务逻辑那会让它变得又慢又难排查。3.2 注册中心服务之间的通讯录服务多了以后最麻烦的问题不是写代码而是“互相怎么找到对方”。订单服务有三个实例A 服务的 IP 变了B 服务怎么知道一个个写死 IP 不现实这就是注册中心的用处每个服务启动时把自己连同 IP、端口、元数据一起注册上去同时定期发心跳续约调用方不再记住具体实例地址而是从注册中心动态拿一份“活着的实例列表”。市面上主流选择有 Nacos、etcd、ZooKeeper、Consul。ZooKeeper 算老一辈临时节点 watcher 机制很经典特殊文件系统和会话机制让很多团队觉得难维护etcd 在 K8s 生态里最顺滑强一致公司如果全面云端原生化etcd 是不错的选择Consul 在功能上和 Nacos 很像但国内社区热度相对低。我目前最常用的是 Nacos因为它不只做服务发现还自带配置中心支持命名空间、分组、灰度发布Java 生态的集成度也高。用注册中心有两条铁律。第一心跳参数别乱调。服务下线到被感知通常有几秒延迟如果心跳超时时间设置过长故障实例残留的时间就越久调用方会不停把请求打到死节点上。第二注册中心绝对不能成为单点至少 3 节点集群起步。注册中心一旦抖动线上服务批量摘除实例整个系统的服务发现就崩了。这类事故我亲身经历过一次网络抖动导致注册中心短暂不可用客户端缓存全部过期所有服务互相找不到界面一片 5xx。所以客户端 SDK 的本地缓存必须打开就算注册中心短暂失联服务间的调用也要能靠缓存撑住。3.3 API 网关把横切能力统一收口早期系统没有网关登录鉴权写在每个服务里限流各写各的接口文档满天飞。后来大家发现这些横切问题完全可以放在入口层统一处理于是 API 网关成了标配。网关至少做这几件事路由转发、统一鉴权、黑白名单、限流熔断、灰度发布、协议转换。方案怎么选Java 团队最常见是 Spring Cloud Gateway内置了 Route、Predicate、Filter 三层抽象开发体验很好和 Spring Boot 无缝衔接。如果追求极致性能或者需要 OpenResty 生态的动态脚本能力APISIX 和 Kong 是更硬的选择它们基于 Nginx/OpenResty支持热更新路由天然适合大规模流量入口。国内还有阿里开源的 Higress云原生友好也很适合新项目。网关上的限流是面试和实战的高频点。令牌桶和固定窗口、滑动窗口这些算法虽然简单但很实用。令牌桶用一个“桶”匀速放令牌请求来了就取令牌取不到就拒绝允许一定程度的突发流量比固定窗口那种“最后一秒打死所有请求”要平滑不少。实际落地时限流阈值不要拍脑袋拿压测数据说话先压出单节点极限 QPS再乘 0.6 到 0.8 做安全水位。网关本身也要多实例部署、前置负载均衡因为网关一旦挂了入口就没了。有一条很重要的边界网关里别塞业务逻辑。我在一些项目里看到有人把订单校验、商品价格填充写在网关过滤器里结果业务每次改需求都要改网关网关变成了第二个业务系统性能还差。网关只做通用能力和业务相关的交给下游服务这样才能保持网关轻薄稳定。4. 异步与海量存储消息队列与对象存储4.1 消息队列削峰填谷与系统解耦消息队列MQ解决两个经典问题解耦和削峰。拿下单场景举例用户下单后要通知积分服务、库存服务、短信服务、推荐统计服务如果同步调用任何一个下游卡顿都会拖慢下单接口发到 MQ 里以后订单服务只管投递消息下游各自消费互不影响。大促时瞬间流量冲到平时十倍数据库扛不住MQ 先把消息攒起来下游按自己节奏消费这就是削峰填谷。选择 MQ 的核心思路看场景中间件优势适合场景Kafka吞吐量极高、生态最大日志采集、大数据管道、实时计算RocketMQ事务消息、延迟消息、可靠性强电商订单、金融交易、业务解耦RabbitMQ轻量灵活、路由模型丰富、社区资料多中小团队通用业务、传统企业集成Kafka 的核心模型是 Topic 加 Partition。一个 Topic 分成多个分区分区内消息有序分区间并行处理所以它能扛住海量写入。消费的时候每个消费者组里的多个消费者会瓜分分区这带来一个非常实际的问题消息至少被投递一次重复消费是常态。所以消费端业务逻辑必须幂等数据库插入用唯一索引去重或者消费前先查状态同一订单号的处理只执行一次。另一个高频事故是消息积压往往是因为某个消费者宕机、出现异常消息反复重试、或者下游数据库抖动。排查思路是先看消费组 lag再看消费者日志里的异常最后看消费线程是不是被阻塞住了。积压期间不要轻率重启消费者最好的办法是临时增加消费者实例来横向扩容先把堆积清掉再定位根因。顺序性也要聊一句。Kafka 能保证的是分区内有序不是全局有序。如果你要保证同一订单的事件严格按顺序消费那把业务主键比如订单号作为 key 投递让同一订单的消息进同一个分区。跨分区的全局顺序基本没有中间件能优雅保证更好的方式是上游只发最终状态下游直接对齐最终状态而不是依赖一串顺序事件。4.2 对象存储海量非结构化数据的统一底座业务跑起来以后图片、视频、PDF、日志包这些文件会越来越多。这些东西最不适合放 MySQL 的 BLOB 字段里也不适合塞服务器的本地磁盘一是容量扩展难二是单机磁盘坏了文件就全没了三是静态内容如果走业务服务器还会白白占用带宽和 CPU。正确做法是统一丢进对象存储。对象存储和传统文件系统不一样它没有目录层级核心就是一个大桶Bucket加一个个对象Object。对象通过 HTTP API 访问支持水平无限扩展天然带多副本冗余还能通过生命周期规则把冷数据自动迁移到低频存储甚至归档存储。生产环境我会区分几个桶公开读的静态资源桶、私密的用户文件桶、日志归档桶权限策略分开配。自建还是上云上云 OSS 最省心CDN 加速、防盗链、数据处理功能都有按量付费但流量和 API 请求量大时账单非常吓人我有一次误把备份任务写成高频 API 调用月底账单直接翻倍。自建 MinIO 也不错开源、S3 协议兼容、部署简单适合数据不出私网、成本敏感的公司。MinIO 集群的纠删码配置要按磁盘数量仔细算默认配置未必适合你的硬件。接入方式上比较推荐用签名 URL 直传。客户端拿到一个有有效期、限定路径和文件类型上限的预签名地址直接往对象存储上传服务端只下发 token 和存元数据完全不经过应用服务器中转带宽压力小很多。大文件上传要支持分片和断点续传生命周期规则至少要设置过期清理否则时间一长桶里的临时文件和备份会侵占大量成本。权限策略是另一个频发事故点桶策略一旦写成public-read就意味着任何人知道 URL 就能下载文件包括用户的身份证照片。每次改桶策略我都要反复确认“这个桶真的需要公开读吗”。5. 稳定与可观测定时任务、监控告警、日志5.1 分布式定时任务别再用服务器 Cron 硬扛定时任务是后端最容易忽略的组件但几乎所有业务都会用到每天凌晨跑数据报表、定时关闭超时未支付订单、定期清理过期 token、给用户推送提醒。早期团队常用服务器 Cron这在单机阶段没什么问题一旦服务水平扩展到多实例问题就来了同一套代码在三个实例上跑Cron 会在三个实例同时触发同一个订单被关三次、同一批优惠券发三次。解决思路是把调度和业务执行拆开。XXL-Job 是我用得比较早也最多的方案调度中心负责到点触发执行器业务服务负责干活执行器启动时自动注册到调度中心。它支持失败重试、超时控制、告警通知还支持分片广播——把所有执行器分成片每片处理一部分数据这在大批量任务里特别好用。比如跑一个 1000 万用户的数据刷新可以分 5 片每台执行器处理 200 万并行度直接拉满。用定时任务平台最关键的是任务幂等。不管调度平台怎么做失败重试任务执行时的网络抖动、重启、重复触发都可能导致同一条数据被处理两次。所以任务逻辑里一定要有防重手段分布式锁、数据库状态字段判断、或者限制任务只能由负责人手动点一次。我在实践中专门给所有任务加了一个“执行批次号”每次任务把批次号落库消费消息和数据更新都带上它配合唯一索引重复执行也不会有副作用。还有一个经验长耗时任务一定设超时和分片一个任务跑超过半小时就会影响调度中心的心跳判定容易被误判为执行失败然后重复调度。5.2 监控告警先于用户发现问题没有监控的系统就像没有仪表的飞机飞着全靠感觉。基础组件堆得越多越需要监控把所有节点的运行状态汇总到一个地方否则每个组件都是信息孤岛。监控体系我习惯分三层。第一层是基础设施监控CPU、内存、磁盘、网络 IO对象是每台机器和中间件节点第二层是应用监控接口 QPS、响应时间、错误率、JVM 内存、线程池状态第三层是业务监控订单量、注册量、支付成功率这些指标直接反映用户体验。技术上最主流的搭配是 Prometheus 采集指标 Grafana 可视化 Alertmanager 告警。业务服务用 Prometheus 客户端暴露/metrics端点Prometheus 定时来拉取MySQL、Redis、Nginx 都有对应的 exporter 可以直接采集。监控指标不用贪多Google 的黄金信号四个维度就够了延迟请求处理耗时特别是 P95/P99。流量QPS、TPS、并发连接数用来判断负载趋势。错误HTTP 5xx 比例、接口异常率、消息消费失败数。饱和度CPU 使用率、内存使用率、连接池占用、磁盘剩余空间。告警规则的设计比很多人想的更难。最常见的失败是告警风暴一点小抖动几十条告警同时轰炸真正的故障反而被淹没。我现在按优先级分三类P0 严重订单成功率下降、核心库主从切换失败、网关大面积 5xxP1 警告单节点 CPU 超过 85% 持续 5 分钟、消息积压超过阈值P2 信息磁盘使用率超过 70%提前提醒扩容。阈值不能拍脑袋要基于一周到一个月的历史基线来定。还有一条反直觉的经验告警消息里必须带上排查入口比如 Grafana 面板链接、最近变更记录、相关服务负责人不然告警发了也没人知道从哪查起。5.3 日志系统排障的第一手现场最后看日志。日志系统和监控不一样监控告诉你系统出问题了日志告诉你问题到底出在哪儿。没有日志系统的项目排查线上问题全靠登服务器一个个tail -f效率极低。日志系统的价值就是把分散在几百台机器上的日志统一采集、集中检索、长期留存。典型采集链路是 Filebeat 采集日志文件 → 发到 Kafka缓冲削峰→ Logstash 清洗解析 → 存入 Elasticsearch → Kibana 查询展示。链路有点重但胜在稳定可靠日志量大时还有缓冲兜底。小团队想轻量可以试试 Loki它不建全文索引只按标签索引Grafana 原生集成部署成本低很多。日志排障最关键的是链路追踪。如果只是单机日志看不出一个请求经过了哪些服务。解决思路是每次请求进来时生成一个 traceId用 MDC 塞进日志上下文调用下游时通过 HTTP Header 传递整个链路的所有服务日志都带上同一个 traceId。后续排查只要拿 traceId 去日志平台搜一条请求从头到尾的全部日志就串起来了。日志平台里搜同一个 traceId能把 Nginx、网关、订单服务、支付服务的日志按时间戳排成一条时间线定位性能瓶颈特别快。日志这边有三个我反复强调的雷区一是不要打敏感信息用户手机号、身份证、支付报文别透传进日志真要用来排查就脱敏二是日志不能同步写用异步 appender 或日志管道否则高并发下磁盘同步 IO 会阻塞业务线程三是日志分级和保留策略要明确debug 日志只在临时排查时开默认 info别把所有日志不分青红皂白存一年磁盘再大也扛不住。6. 一套最小可运行的后端架构怎么搭6.1 简化拓扑10 个组件如何连接起来很多同学看完前面一大篇脑子里的组件还都是孤立的。这里我把一套常见的小规模后端架构画成一个文本拓扑帮你把关系理清楚客户端 ↓ Nginx2 台做接入和负载均衡 ↓ API 网关2 台或更多鉴权、限流、路由 ↓ 业务服务集群订单、用户、商品各自多实例 ↓ 读写 ↓ 注册/发现 ↓ 异步 MySQL1主2从 Nacos服务注册配置 Kafka主题消息 Redis3节点哨兵 ↓ 消费 Elasticsearch3节点搜索/日志 下游服务、数据同步任务 对象存储 MinIO/OSS存放图片、文件、备份 监控 Prometheus Grafana 覆盖所有节点 日志 Filebeat → Kafka → Logstash → ES → Kibana 定时任务 XXL-Job 调度中心 执行器业务服务内置这套架构里所有组件分摊的角色一清二楚Nginx 管入口流量网关管统一治理Nacos 管服务发现MySQL 管事实数据Redis 管热数据和速度Kafka 管异步流转ES 管搜索和日志对象存储在管非结构化文件定时任务管周期操作监控日志管可观测性。一句话总结入口、业务、数据、异步、存储、可观测六层全齐了。6.2 搭建顺序与资源估算先跑通最小闭环新项目落地时不要一上来就全量铺开大概率会翻车。我的建议是先搭最小闭环再加组件第一阶段Nginx 业务服务Spring Boot/Go MySQL Redis。这套已经能支撑一个日活几万的单体应用先把业务跑通。第二阶段业务继续拆分成多个微服务时引入 Nacos 做服务注册发现和配置中心再引入 API 网关收敛入口。第三阶段出现跨服务异步通知、削峰需求时引入 Kafka 或 RocketMQ搜索需求明确时再上 Elasticsearch有文件上传需求就接对象存储。第四阶段服务实例多到排障困难时补齐日志链路和 Prometheus 监控再逐步把核心定时任务从服务器 Cron 迁到 XXL-Job。资源估算是个很现实的成本问题。假设你是 1000 QPS 的读写混合业务单台 4C8G 的业务服务实例乐观时可以扛 200 到 300 QPS保守按每实例 200 算业务服务至少准备 4 到 6 个实例。MySQL 用 1 主 2 从主库扛写从库扛读和离线任务Redis 用 3 节点哨兵或者直接 3 主 3 从的 ClusterKafka 3 节点起步每个 Topic 先设 6 到 12 个分区后面按消费压力和延迟数据再调ES 至少 3 节点避免脑裂节点少时一定要配discovery.zen.minimum_master_nodes。这个规模大概是3 台数据库、3 台缓存、3 台消息队列、3 台 ES、2 台 Nginx、2 台网关、4 台业务服务共 20 台左右的虚机对中小团队来说已经是覆盖所有关键路径的完整体系了。7. 常见问题与排查技巧实录7.1 十个组件最经典的坑速查表下面这张表是十年来被踩得最多的故障点直接照着排查可以少走很多弯路。组件经典故障现象排查方向建议解法MySQL慢查询激增、锁等待慢日志、SHOW ENGINE INNODB STATUS补索引、优化 SQL、避免大事务MySQL主从延迟过大SHOW SLAVE STATUS看 Seconds_Behind_Master优化主从同步、大事务拆分、考虑并行复制Redis缓存击穿/雪崩监控 key 过期时间和热点访问加随机过期、多级缓存、布隆过滤器Redis主线程阻塞、延迟抖动SLOWLOG、redis-cli --bigkeys拆分 bigkey、淘汰危险命令Nginx转发后路径丢失检查proxy_pass是否带斜杠按环境固定一套写法并加测试注册中心服务实例批量消失看心跳超时、注册中心负载调大心跳容忍、客户端加本地缓存网关限流误伤正常用户看限流日志、令牌桶参数按压测水位调整阈值、增加白名单MQ消息大量积压查消费组 lag、消费者日志扩容消费者、修异常消息、临时跳过死信对象存储文件访问报 403检查桶策略、签名有效期重新配置权限、检查 URL 签名定时任务同一任务被重复执行看调度日志、执行记录任务幂等设计、加执行批次号监控告警风暴检查告警规则和抖动源按优先级分级、基于基线设阈值日志全链路查不到 traceId检查 Header 传递和 MDC 配置统一请求过滤器、日志框架异步化7.2 几条亲身踩出来的独家心得最后聊几个普通文档里不太会写的经验。第一连接池不是越大越好。很多人觉得 Redis 连接池调到 1000 就更快其实大量并发线程抢同一批连接只会增加等待和上下文切换。Redis 客户端连接池我一般保持在 16 到 64 之间压测数据反而更好看。MySQL 连接池同理设到 200 之前先看看数据库的max_connections能不能扛得住。第二基础组件升级别追太急。我有一次把 Redis 从 5 升到 7结果部分客户端版本不兼容线上频繁断连。中间件的升级要当作一次小型项目来管理先在测试环境完全复现业务链路再用金丝雀实例观察流量最后才逐步切量。稳定运行的组件不要去赌它没风险。第三每个组件都要做容量预留和压测。Kafka 分区数不是越多越好分区太多会增加文件句柄、延长 leader 切换时间ES 分片太多会引起小分片风暴分片太少又扛不住查询并发放。最靠谱的方法只有一条拿接近真实的流量做压测看延迟和资源使用率的拐点在哪再定容量水位。第四排查问题时永远先看基础设施再看业务代码。一个接口超时先确认是不是 CPU 跑满、磁盘满了、网络抖动、连接池耗尽再去看代码逻辑。我见过太多人一上来就查代码最后发现是磁盘 IO 报废浪费了几个小时。监控系统存在的意义就是让你在陷入代码之前先看到系统层到底发生了什么。这个领域有个很朴素的道理基础组件本身并不难难的是对每个组件边界的尊重。数据库就安安稳稳存事实数据缓存就负责扛热点消息队列就处理异步日志监控就是你的眼睛和耳朵。先跑通最小闭环再按业务增长慢慢把组件补全比一次性铺开十个中间件要稳妥得多。希望这篇梳理能给你的后端架构打下一个清晰的地基。
返回列表