1. 面对这个面试题,先想明白面试官在考察什么前阵子面了一家金融科技公司的后端岗位,二面的时候面试官抛了个问题:假如当前系统QPS只有100,你作为负责人,怎么把成本降下来?听到这个题我愣了一下,不是因为难,而是因为很多人一上来就会列一堆优化手段:上缓存、加消息队列、搞微服务拆分、上K8s做弹性伸缩。但说真的,流量只有100 QPS的时候,这些操作大概率不是在降本,而是在增加成本。我当时的思路是反过来问自己几个问题:这100 QPS是怎么分布来的?是平均100还是峰值100?单机能不能扛住?现在的资源利用率有多少?有哪些固定成本是明显浪费的?如果这些问题没有想清楚,任何优化方案都是在猜。面试官想考察的,其实是你对“成本”这件事的理解深度——你有没有成本意识,能不能用数据说话,会不会在低流量场景下做出合理的取舍。先把这个题的底层逻辑捋清楚。100 QPS是什么概念?假设单请求平均耗时50ms,单实例可以支撑大约20并发。而100 QPS意味着期望并发约5个(100×0.05)。这连一台普通虚拟机都能轻松扛住。如果不加思考就引入一堆中间件和冗余节点,不客气地说,这是在花钱买复杂度。所以这道题的正确打开方式,不是“如何通过高端技术省钱”,而是“如何识别并砍掉那些超出实际负载的过度供给”。把系统当前所有资源列出来,逐个问一句:真的需要这么多吗?这才是降本的第一性原理。1.1 成本优化不等于性能优化,也不等于架构重构很多人容易掉进一个误区,觉得降本就要把架构搞得很大,用最前沿的技术。实际上,对于100 QPS的系统,如果现状是30台ECS放在那里,你第一反应应该是“这30台里面有多少台是多余的”,而不是“我要不要引入Service Mesh”。成本优化的核心动作是“做减法”,不是“做加法”。性能优化关注的是单位资源能处理多少请求,而成本优化关注的是“花出去的钱是否都产生了对应的业务价值”。举个最简单的例子:如果一台4核8G的机器能支撑500 QPS,你的业务只需要100 QPS,那1台机器就够。但如果因为打了某些高可用要求,非要部署3个节点,那也行,但成本是3台。这时合理的降本方向是:评估真的需要3副本吗?如果不那么核心,降成2副本甚至单节点+快速恢复机制,成本直接少了三分之一。这些判断靠的不是技术炫技,而是对业务等级和风险容忍度的清晰认知。1.2 面试时容易被忽略的边界:先区分“峰值流量”与“平均流量”我在回答时特意问了一句:这个100 QPS是平均还是峰值?如果平均100,峰值可能到300甚至更高。如果是峰值100,平时只有二三十,那最优解和前者完全不同。这个细节很关键,因为降本方案里,流量模型决定了你能不能缩容、该不该留buffer、要不要上弹性。比如一个典型业务系统,白天时段平均QPS 120,夜间只有20。这种有明显的波峰波谷,直接用固定实例数就很浪费。这时候引入定时扩缩容或者基于指标的自动伸缩,可以让低成本时段只保留一两台机器。如果峰值和均值相差不大,倒是可以维持固定容量,减少不必要的弹性组件维护成本。反正记住一句话:没有流量画像,就没有降本方案。2. 先算清账本:QPS 100 的系统的成本构成与浪费点识别设计降本方案前,我最推荐先做一次“成本体检”。把每个月云账单拉出来,按资源类型拆开看:计算、存储、网络、数据库、中间件、人力运维成本。为什么要拆?因为不同系统成本结构完全不同。有些系统数据库是大头,有些是日志存储爆炸,有些是容器集群空转。如果让我给一个典型QPS 100的后端系统画像,大概率成本分布是这样的:成本项常见占比典型浪费点计算资源(ECS/容器)30%-50%实例规格过剩、副本过多、长期低负载运行数据库与缓存20%-30%规格过高、慢查询导致扩容需求、为“未来”预留存储与备份10%-20%日志不归档、备份保留周期过长、冷数据占用热存储网络与带宽5%-10%单机多副本间传输、跨可用区流量中间件与治理组件5%-15%注册中心、配置中心、监控系统自身耗资源人力与运维开销隐性过多微服务带来的部署、联调、维护成本从这个表能看出,计算和数据库是主战场。但我要特别提醒,别忽视“中间件成本”。很多团队为了追求某种架构美感,给100 QPS的系统挂了完整的微服务全家桶:网关、注册中心、配置中心、链路追踪、监控大盘、多套环境。每样东西本身要占用资源,还要有人维护。这些固定成本不会随着QPS下降自动消失,是降本时要重点审视的沉没成本。2.1 通过QPS反推实例数量:一顿估算,心里就有底在面试时,我直接和面试官算了一笔账。假设单请求平均处理时间50ms,那么单个实例能够支撑的最大QPS约为1/0.05=20 QPS(单线程模型下)。如果是4核8G的机器,配合合理连接池和并发配置,单机支撑100 QPS通常没有问题。实际上很多Java服务单机跑到几百QPS很常见,主要看CPU密集还是IO密集。如果平均耗时更高,比如200ms,那并发模型下单机可能只能支撑50 QPS(假设10个并发都能处理)。所以100 QPS也未必单机就能扛,需要先测量接口的TP99延迟。这里想说明的是:不要看到100就拍脑袋说一台机器搞定,而是要有能力根据实际指标估算。我是这样做的:找监控系统拉出线上接口的耗时分布,再结合机器配置,做容量预估。如果当前机器CPU使用率只有10%,内存占用不到一半,那答案很明显——资源冗余。2.2 常见成本浪费的三个画像结合我见过的一些低流量系统,浪费基本集中在三个画像上。第一个是“高配低用”。申请ECS时选了当时最新款高配规格,比如16核32G,但业务请求量根本跑不满,CPU长期在5%以下。这种资源浪费最直接,降配就能省一大笔钱。云厂商的计费不是线性的,很多情况下8核16G和16核32G的价格差很远,但对你这个业务而言实际差异微乎其微。第二个是“大马拉小车”的数据库。MySQL或者云上RDS选了高规格,连接数和IOPS远远用不满。还有的上了Redis集群,实际只有两个键在被高频访问。这时完全可以降规格、换单节点、甚至把部分缓存去掉。第三个是“面板好看,钱包受罪”的中间件。一个100 QPS的系统,非要把服务拆成十几个微服务,每个服务都要分配开发、测试、生产三套环境。每套环境里跑着注册中心、配置中心、监控agent。这样算下来,光环境开销就够养好几个服务了。更重要的是,人力和维护成本是隐性的,很难量化但真实存在。2.3 找到大头再动手,别在无关紧要的角落抠钱我见过有些人一说降本就去调云厂商的折扣、换更便宜的套餐、洽谈预留实例。这些当然可以做,但前提是先把架构层面的浪费解决掉。就像一家餐厅,你拼命砍纸巾的成本,但后厨食材浪费一大堆,那再怎么抠也没意义。所以我的降本流程是:先找影响面最大的点,通常是实例数量和数据库规格;再处理次要项,比如日志和存储;最后才去谈计费策略,比如包年包月、Spot实例、预付折扣等。把这个顺序记牢,面试时回答也会更有逻辑。3. 分层降本:从架构、数据到链路,一层一层挤出水分算清楚账之后,就可以开始设计方案了。我用“架构层—数据层—链路层”三个层次来拆解,这样在面试中不会乱,实际落地时也好推进。3.1 架构层:微服务不是万能的,低QPS下该合就合这个话题可能有点招微服务爱好者的反对,但我还是要说:对于一个只有100 QPS的系统,微服务带来的收益大概率小于成本。微服务的初衷是应对超大规模团队协作和超高流量弹性,而100 QPS的场景,单体应用或者极少数服务拆分反而更省心。我在处理类似系统时,优先考虑把多个业务模块合并部署。比如原来拆了用户服务、订单服务、支付服务、通知服务,每个服务独立注册、独立部署、独立配资源。如果流量不高,直接合并成一个应用,用内部模块划分来隔离开代码边界。这样减少了至少三套部署单元,节省了容器内存和网络开销,也缩短了链路耗时。当然,如果团队真的很庞大、各团队需要独立发布,合并会带来协作成本,那另说。但这是个权衡,而不是技术对错问题。架构层还有一个经常被忽视的点:环境实例。很多系统在开发、测试环境都常开着集群,即便晚上没人用。如果这些环境不是24小时需要,完全可以用定时开关机的方式,只在工作时间内启动。省下的费用不是小数目,而且几乎不影响研发效率。3.2 数据层:缓存、数据库与存储的一次大扫除数据层是成本重灾区。先从缓存说起——不是所有系统都需要Redis。如果业务缓存命中率不到50%,而且数据本身就在数据库里,加缓存只会增加一致性风险和额外的运维成本。100 QPS下,直接查询MySQL的QPS也就是几百,完全没问题。所以我会先做缓存必要性分析:如果是为了缩短几十毫秒的响应时间,而这些时间用户感知不强,那就把缓存砍掉,数据层成本直接下降。数据库方面,第一件事是检查规格。很多系统的RDS规格远远超用。可以观察CPU使用率、内存占用、连接数峰值、慢查询数量。如果CPU几乎不超过10%,连接数常年个位数,那么降一个规格甚至两个规格都没有问题。第二件事是清理无效索引。索引不是越多越好,每多一个索引,写操作都要维护,还占用额外存储。在100 QPS的写入量下,保留必要索引即可。第三件事是历史数据归档。把一年前的订单、日志等冷数据迁到对象存储或者归档存储,数据库体积变小,日常查询变快,也就不用为了承载大数据量而升级规格。存储层面,日志是很多人忽略的钱坑。按100 QPS计算,每天请求量约864万,如果每条请求产生200字节日志,一天就是1.7GB左右。听起来不多,但如果日志保留30天、且多副本冗余,也有几十GB甚至上百GB。关键是,这些日志里真正被捞出来看的,可能不到1%。我的做法是:降低访问频率低日志的保留周期,只用近7天;对超过30天的日志转归档存储,成本能低一个数量级。再加上日志压缩、采样上报,存储成本能砍掉一半以上。3.3 链路层:减少无用功,让每个请求都划算链路层的降本,核心是“用最小的资源完成同样的业务目标”。最简单有效的是减少重复计算。比如某些接口查询结果在短时间内不变,却每次都查库、做复杂计算,这就是白烧CPU。可以考虑在应用内存里做短暂缓存,命中后直接返回。100 QPS下,一个请求从100ms降到10ms,理论上单机承载能力能翻十倍,虽然你不需要真的翻十倍,但你可以借此缩小实例规格。另一个方向是异步化。如果一个请求里有两步操作,其中一步不是核心路径,比如发邮件、推送通知,就可以丢进队列或线程池异步处理,让调用方更快返回,也降低阻塞。虽然异步不会直接减少资源消耗,但可以减少线程数、减少等待占用,从而让同样资源支撑更多请求。对于降本来说,少用一台机器就是实打实的省。还有接口合并。如果前端一次要调3个接口才能拿到页面数据,这3个请求都要走网络、DNS、负载均衡、业务逻辑。如果后端提供一个聚合接口,一次搞定,请求量就从300 QPS降到100 QPS,链路负载和日志量都同步下降。这种优化在100 QPS场景下尤其难得,因为请求量少,改动风险也相对可控。4. 弹性与容量治理:让成本跟着真实流量走,而非拍脑袋预留前面聊的都是“砍掉多余资源”,但在一个长期运行的系统中,真正让成本回归合理的手段是弹性策略和容量治理。即使你不做大的架构改造,只要把弹性做对,就能把很多成本自动抹平。4.1 定时扩缩容与指标扩缩容,才能让夜间流量不白烧钱100 QPS的系统,往往白天忙、晚上闲。这种情况下,最浪费的就是24小时跑满固定数量的实例。如果你用的是容器平台,可以为工作负载配置HPA(水平自动伸缩),依据CPU使用率或请求量伸缩副本数。白天流量上来,自动加副本;晚上没人访问,缩到最小副本。如果平台能力不支持,至少可以搞个定时脚本,在每晚8点把无状态服务缩到1个副本,次日早上7点再扩回来。需要注意的是,缩容不是粗暴地减少副本就完事。你得先保证服务能平滑缩容,比如设置优雅停机、在缩容前断开流量、让正在处理的请求完成。这些细节不做好的话,缩容带来的服务抖动比省下的钱更让人头疼。还有,如果服务依赖数据库连接池,缩容后连接数要重新调整,不然会出现连接池占满的假象。我在一次实战中就遇到过类似问题,后面第五章会详细讲。4.2 建立成本水位线,让资源利用率可见除了弹性,还要有“成本水位线”的监控。简单说,就是对每个服务设定合理的CPU、内存使用率目标区间。如果连续几天使用率低于20%,就触发资源整理提醒;如果高于80%,则考虑是否需要扩容或优化。这个机制能防止成本悄悄反弹。低QPS系统最怕的是“反正流量不高,就多留点buffer吧”,这种心态会让资源一点点堆起来,最终成本变成刚性的。我们可以用表格做一个资源水位样例:服务当前实例数平均CPU平均内存建议订单服务48%40%缩到2实例,规格不变用户服务215%60%可降至1实例(若容忍短时故障)支付回调25%30%合并至订单服务,取消独立部署定时任务12%20%保留,可降配表格只是示意,核心在于把抽象的成本消耗变成一眼可见的指标。有了这个水位表,你每次做降本决策都有依据,而不是凭感觉。团队里也可以约定一条规则:新申请的资源必须提供容量预估和使用率预期,避免“怕不够,先申请多”。5. 从面试题到落地:我的一次低成本改造实操复盘说完了理论,我把一个真实的改造过程分享出来。为了不涉及具体公司信息,就叫它“某旧系统”好了。这套系统对外提供数据查询能力,平均QPS不到100,峰值也才150左右。它的问题是每月云成本高得离谱,而且团队每次开会都被质疑为什么这么高的费用。5.1 改造前的状态和关键数据系统原有部署情况如下:8台4核8G的ECS,前后端分离,部分服务各部署2个实例1套4核16G的MySQL主从,从库基本没读过2个Redis节点,其中一个只有某个列表缓存用得到十几个微服务,很多只依赖同一个核心库,各自部署日志存储保留45天,未压缩,未归档我拉出一个月的监控数据,做了成本归因。计算资源占了大头,约55%;数据库与缓存占25%;存储日志占15%;其他占5%。CPU利用率超过20%的服务只有两个,其余常年个位数。很明显,这不是“性能不够”,而是“供给过剩”。5.2 三步改造过程第一步,合并服务。我把依赖关系简单、没有独立扩展需求的6个服务合并成了2个。合并之后,原本需要12个实例的服务,现在只保留4个实例。这个动作最省成本,同时也暴露了很多隐藏问题:不同服务原本有独立的日志目录、配置项,合并后需要统一;端口冲突、依赖包版本冲突也需要慢慢收拾。好在流量不高,灰度验证压力不大。第二步,数据库降配与清理。将MySQL从4核16G降为2核8G,关闭了从库,改为用主库+备份机策略。原因是读流量极低,从库只起到了“摆设”作用。同时清理了20多个无用索引,归档了两年前的历史数据到便宜的对象存储。Redis也从双节点变为单节点,且只保留真正高频访问的数据。第三步,弹性与开关。所有应用接入了弹性伸缩,夜间自动缩容到2个实例。日志从45天调整为热日志7天,超过7天的自动压缩并转移到低频存储。这一步之后,存储成本直线下降。5.3 效果对比与踩过的坑改造后,月度云成本降了约48%。服务可用性没有明显下降,平均响应时间反而缩短了,因为合并后的调用链路更短。从效果上看,这次改造是成功的。但有几个坑我必须提醒。第一个坑是合并服务时的“连坐问题”。原本两个服务各自部署,一个出问题不影响另一个;合并后,某个模块的Bug会导致整包重启。为了安全,我给合并后的服务增加了更精细的线程池隔离,比如订单处理线程池和通知发送线程池分开,避免互相耗尽。第二个坑是缩容时的连接风暴。有一次夜间缩容从4个实例缩减到2个,结果所有服务重新建立数据库连接,瞬间把一个本来很空闲的数据库打出了大量连接。最后靠限制每个实例的数据库连接池上限,以及延长缩容的冷却时间,才解决。第三个坑是日志归档被“忽略”。因为压缩任务执行时间过长,导致当天的日志没有及时归档,存储量短暂反弹。后来调整了压缩任务的调度频率,并分片处理,就正常了。6. 如果面试官追问:这些降本手段的边界与风险在哪面试官通常会顺着你的方案继续追问,比如“你合并服务后,如果流量涨到10000 QPS怎么办?”或者“你降数据库规格,万一突然有热点活动怎么办?”这时候不要慌,答案的核心是“降本不是一锤子买卖,而是动态平衡”。任何优化方案都有前提和边界,你能说出来,反而说明你考虑全面。先说合并服务的边界。服务合并适用于低流量、单团队维护的系统。如果业务复杂度高、团队多人并行迭代,强行合并会造成代码耦合和发布互相制约。所以我在方案里会强调:合并不等于消灭模块边界,代码层面依然保持清晰的分包,只是部署时放到一起。再说降低数据库规格的边界。降规格的前提是性能监控数据支持,并且有快速回退机制。比如云数据库通常支持在控制台一键升配,用时也就几分钟。所以在降低成本的同时,要把“升配预案”写清楚,一旦流量突增或者大促来临,能及时恢复容量。这也是云厂商比自建机房有优势的地方。还有缓存和异步的边界。砍缓存的前提是数据库撑得住,一旦访问量增加或者出现热点,数据库压力会迅速上升。所以砍缓存时要谨慎评估读放大和热点场景。异步本来是降耗时的手段,但引入队列也要维护,如果只是100 QPS,完全可以用进程内线程池,没必要额外搭建消息队列中间件。最后,其实我想说,这类面试题没有标准答案。面试官想听的,是你能不能把一个具体问题落到可执行、可度量的方案中,并且能意识到方案的风险和盲区。如果你在面试时能把成本构成表拉出来,再把“先诊断—再治理—后评估”的思路说清楚,基本上已经是一个很完整的回答了。我在实际做降本的过程中,最大的体会是:在低流量场景下,最简单的方法往往最有效。合并一台机器、关掉一个不用的Redis、把日志保留期缩短,这些事情听起来不够“高大上”,但每个月省下来的钱是实实在在的。优化完所有技术项之后,记得把账单拉出来对比一下,这就是你最好的面试案例和绩效素材。
1. 面对这个面试题,先想明白面试官在考察什么前阵子面了一家金融科技公司的后端岗位,二面的时候面试官抛了个问题:假如当前系统QPS只有100,你作为负责人,怎么把成本降下来?听到这个题我愣了一下,不是因为难,而是因为很多人一上来就会列一堆优化手段:上缓存、加消息队列、搞微服务拆分、上K8s做弹性伸缩。但说真的,流量只有100 QPS的时候,这些操作大概率不是在降本,而是在增加成本。我当时的思路是反过来问自己几个问题:这100 QPS是怎么分布来的?是平均100还是峰值100?单机能不能扛住?现在的资源利用率有多少?有哪些固定成本是明显浪费的?如果这些问题没有想清楚,任何优化方案都是在猜。面试官想考察的,其实是你对“成本”这件事的理解深度——你有没有成本意识,能不能用数据说话,会不会在低流量场景下做出合理的取舍。先把这个题的底层逻辑捋清楚。100 QPS是什么概念?假设单请求平均耗时50ms,单实例可以支撑大约20并发。而100 QPS意味着期望并发约5个(100×0.05)。这连一台普通虚拟机都能轻松扛住。如果不加思考就引入一堆中间件和冗余节点,不客气地说,这是在花钱买复杂度。所以这道题的正确打开方式,不是“如何通过高端技术省钱”,而是“如何识别并砍掉那些超出实际负载的过度供给”。把系统当前所有资源列出来,逐个问一句:真的需要这么多吗?这才是降本的第一性原理。1.1 成本优化不等于性能优化,也不等于架构重构很多人容易掉进一个误区,觉得降本就要把架构搞得很大,用最前沿的技术。实际上,对于100 QPS的系统,如果现状是30台ECS放在那里,你第一反应应该是“这30台里面有多少台是多余的”,而不是“我要不要引入Service Mesh”。成本优化的核心动作是“做减法”,不是“做加法”。性能优化关注的是单位资源能处理多少请求,而成本优化关注的是“花出去的钱是否都产生了对应的业务价值”。举个最简单的例子:如果一台4核8G的机器能支撑500 QPS,你的业务只需要100 QPS,那1台机器就够。但如果因为打了某些高可用要求,非要部署3个节点,那也行,但成本是3台。这时合理的降本方向是:评估真的需要3副本吗?如果不那么核心,降成2副本甚至单节点+快速恢复机制,成本直接少了三分之一。这些判断靠的不是技术炫技,而是对业务等级和风险容忍度的清晰认知。1.2 面试时容易被忽略的边界:先区分“峰值流量”与“平均流量”我在回答时特意问了一句:这个100 QPS是平均还是峰值?如果平均100,峰值可能到300甚至更高。如果是峰值100,平时只有二三十,那最优解和前者完全不同。这个细节很关键,因为降本方案里,流量模型决定了你能不能缩容、该不该留buffer、要不要上弹性。比如一个典型业务系统,白天时段平均QPS 120,夜间只有20。这种有明显的波峰波谷,直接用固定实例数就很浪费。这时候引入定时扩缩容或者基于指标的自动伸缩,可以让低成本时段只保留一两台机器。如果峰值和均值相差不大,倒是可以维持固定容量,减少不必要的弹性组件维护成本。反正记住一句话:没有流量画像,就没有降本方案。2. 先算清账本:QPS 100 的系统的成本构成与浪费点识别设计降本方案前,我最推荐先做一次“成本体检”。把每个月云账单拉出来,按资源类型拆开看:计算、存储、网络、数据库、中间件、人力运维成本。为什么要拆?因为不同系统成本结构完全不同。有些系统数据库是大头,有些是日志存储爆炸,有些是容器集群空转。如果让我给一个典型QPS 100的后端系统画像,大概率成本分布是这样的:成本项常见占比典型浪费点计算资源(ECS/容器)30%-50%实例规格过剩、副本过多、长期低负载运行数据库与缓存20%-30%规格过高、慢查询导致扩容需求、为“未来”预留存储与备份10%-20%日志不归档、备份保留周期过长、冷数据占用热存储网络与带宽5%-10%单机多副本间传输、跨可用区流量中间件与治理组件5%-15%注册中心、配置中心、监控系统自身耗资源人力与运维开销隐性过多微服务带来的部署、联调、维护成本从这个表能看出,计算和数据库是主战场。但我要特别提醒,别忽视“中间件成本”。很多团队为了追求某种架构美感,给100 QPS的系统挂了完整的微服务全家桶:网关、注册中心、配置中心、链路追踪、监控大盘、多套环境。每样东西本身要占用资源,还要有人维护。这些固定成本不会随着QPS下降自动消失,是降本时要重点审视的沉没成本。2.1 通过QPS反推实例数量:一顿估算,心里就有底在面试时,我直接和面试官算了一笔账。假设单请求平均处理时间50ms,那么单个实例能够支撑的最大QPS约为1/0.05=20 QPS(单线程模型下)。如果是4核8G的机器,配合合理连接池和并发配置,单机支撑100 QPS通常没有问题。实际上很多Java服务单机跑到几百QPS很常见,主要看CPU密集还是IO密集。如果平均耗时更高,比如200ms,那并发模型下单机可能只能支撑50 QPS(假设10个并发都能处理)。所以100 QPS也未必单机就能扛,需要先测量接口的TP99延迟。这里想说明的是:不要看到100就拍脑袋说一台机器搞定,而是要有能力根据实际指标估算。我是这样做的:找监控系统拉出线上接口的耗时分布,再结合机器配置,做容量预估。如果当前机器CPU使用率只有10%,内存占用不到一半,那答案很明显——资源冗余。2.2 常见成本浪费的三个画像结合我见过的一些低流量系统,浪费基本集中在三个画像上。第一个是“高配低用”。申请ECS时选了当时最新款高配规格,比如16核32G,但业务请求量根本跑不满,CPU长期在5%以下。这种资源浪费最直接,降配就能省一大笔钱。云厂商的计费不是线性的,很多情况下8核16G和16核32G的价格差很远,但对你这个业务而言实际差异微乎其微。第二个是“大马拉小车”的数据库。MySQL或者云上RDS选了高规格,连接数和IOPS远远用不满。还有的上了Redis集群,实际只有两个键在被高频访问。这时完全可以降规格、换单节点、甚至把部分缓存去掉。第三个是“面板好看,钱包受罪”的中间件。一个100 QPS的系统,非要把服务拆成十几个微服务,每个服务都要分配开发、测试、生产三套环境。每套环境里跑着注册中心、配置中心、监控agent。这样算下来,光环境开销就够养好几个服务了。更重要的是,人力和维护成本是隐性的,很难量化但真实存在。2.3 找到大头再动手,别在无关紧要的角落抠钱我见过有些人一说降本就去调云厂商的折扣、换更便宜的套餐、洽谈预留实例。这些当然可以做,但前提是先把架构层面的浪费解决掉。就像一家餐厅,你拼命砍纸巾的成本,但后厨食材浪费一大堆,那再怎么抠也没意义。所以我的降本流程是:先找影响面最大的点,通常是实例数量和数据库规格;再处理次要项,比如日志和存储;最后才去谈计费策略,比如包年包月、Spot实例、预付折扣等。把这个顺序记牢,面试时回答也会更有逻辑。3. 分层降本:从架构、数据到链路,一层一层挤出水分算清楚账之后,就可以开始设计方案了。我用“架构层—数据层—链路层”三个层次来拆解,这样在面试中不会乱,实际落地时也好推进。3.1 架构层:微服务不是万能的,低QPS下该合就合这个话题可能有点招微服务爱好者的反对,但我还是要说:对于一个只有100 QPS的系统,微服务带来的收益大概率小于成本。微服务的初衷是应对超大规模团队协作和超高流量弹性,而100 QPS的场景,单体应用或者极少数服务拆分反而更省心。我在处理类似系统时,优先考虑把多个业务模块合并部署。比如原来拆了用户服务、订单服务、支付服务、通知服务,每个服务独立注册、独立部署、独立配资源。如果流量不高,直接合并成一个应用,用内部模块划分来隔离开代码边界。这样减少了至少三套部署单元,节省了容器内存和网络开销,也缩短了链路耗时。当然,如果团队真的很庞大、各团队需要独立发布,合并会带来协作成本,那另说。但这是个权衡,而不是技术对错问题。架构层还有一个经常被忽视的点:环境实例。很多系统在开发、测试环境都常开着集群,即便晚上没人用。如果这些环境不是24小时需要,完全可以用定时开关机的方式,只在工作时间内启动。省下的费用不是小数目,而且几乎不影响研发效率。3.2 数据层:缓存、数据库与存储的一次大扫除数据层是成本重灾区。先从缓存说起——不是所有系统都需要Redis。如果业务缓存命中率不到50%,而且数据本身就在数据库里,加缓存只会增加一致性风险和额外的运维成本。100 QPS下,直接查询MySQL的QPS也就是几百,完全没问题。所以我会先做缓存必要性分析:如果是为了缩短几十毫秒的响应时间,而这些时间用户感知不强,那就把缓存砍掉,数据层成本直接下降。数据库方面,第一件事是检查规格。很多系统的RDS规格远远超用。可以观察CPU使用率、内存占用、连接数峰值、慢查询数量。如果CPU几乎不超过10%,连接数常年个位数,那么降一个规格甚至两个规格都没有问题。第二件事是清理无效索引。索引不是越多越好,每多一个索引,写操作都要维护,还占用额外存储。在100 QPS的写入量下,保留必要索引即可。第三件事是历史数据归档。把一年前的订单、日志等冷数据迁到对象存储或者归档存储,数据库体积变小,日常查询变快,也就不用为了承载大数据量而升级规格。存储层面,日志是很多人忽略的钱坑。按100 QPS计算,每天请求量约864万,如果每条请求产生200字节日志,一天就是1.7GB左右。听起来不多,但如果日志保留30天、且多副本冗余,也有几十GB甚至上百GB。关键是,这些日志里真正被捞出来看的,可能不到1%。我的做法是:降低访问频率低日志的保留周期,只用近7天;对超过30天的日志转归档存储,成本能低一个数量级。再加上日志压缩、采样上报,存储成本能砍掉一半以上。3.3 链路层:减少无用功,让每个请求都划算链路层的降本,核心是“用最小的资源完成同样的业务目标”。最简单有效的是减少重复计算。比如某些接口查询结果在短时间内不变,却每次都查库、做复杂计算,这就是白烧CPU。可以考虑在应用内存里做短暂缓存,命中后直接返回。100 QPS下,一个请求从100ms降到10ms,理论上单机承载能力能翻十倍,虽然你不需要真的翻十倍,但你可以借此缩小实例规格。另一个方向是异步化。如果一个请求里有两步操作,其中一步不是核心路径,比如发邮件、推送通知,就可以丢进队列或线程池异步处理,让调用方更快返回,也降低阻塞。虽然异步不会直接减少资源消耗,但可以减少线程数、减少等待占用,从而让同样资源支撑更多请求。对于降本来说,少用一台机器就是实打实的省。还有接口合并。如果前端一次要调3个接口才能拿到页面数据,这3个请求都要走网络、DNS、负载均衡、业务逻辑。如果后端提供一个聚合接口,一次搞定,请求量就从300 QPS降到100 QPS,链路负载和日志量都同步下降。这种优化在100 QPS场景下尤其难得,因为请求量少,改动风险也相对可控。4. 弹性与容量治理:让成本跟着真实流量走,而非拍脑袋预留前面聊的都是“砍掉多余资源”,但在一个长期运行的系统中,真正让成本回归合理的手段是弹性策略和容量治理。即使你不做大的架构改造,只要把弹性做对,就能把很多成本自动抹平。4.1 定时扩缩容与指标扩缩容,才能让夜间流量不白烧钱100 QPS的系统,往往白天忙、晚上闲。这种情况下,最浪费的就是24小时跑满固定数量的实例。如果你用的是容器平台,可以为工作负载配置HPA(水平自动伸缩),依据CPU使用率或请求量伸缩副本数。白天流量上来,自动加副本;晚上没人访问,缩到最小副本。如果平台能力不支持,至少可以搞个定时脚本,在每晚8点把无状态服务缩到1个副本,次日早上7点再扩回来。需要注意的是,缩容不是粗暴地减少副本就完事。你得先保证服务能平滑缩容,比如设置优雅停机、在缩容前断开流量、让正在处理的请求完成。这些细节不做好的话,缩容带来的服务抖动比省下的钱更让人头疼。还有,如果服务依赖数据库连接池,缩容后连接数要重新调整,不然会出现连接池占满的假象。我在一次实战中就遇到过类似问题,后面第五章会详细讲。4.2 建立成本水位线,让资源利用率可见除了弹性,还要有“成本水位线”的监控。简单说,就是对每个服务设定合理的CPU、内存使用率目标区间。如果连续几天使用率低于20%,就触发资源整理提醒;如果高于80%,则考虑是否需要扩容或优化。这个机制能防止成本悄悄反弹。低QPS系统最怕的是“反正流量不高,就多留点buffer吧”,这种心态会让资源一点点堆起来,最终成本变成刚性的。我们可以用表格做一个资源水位样例:服务当前实例数平均CPU平均内存建议订单服务48%40%缩到2实例,规格不变用户服务215%60%可降至1实例(若容忍短时故障)支付回调25%30%合并至订单服务,取消独立部署定时任务12%20%保留,可降配表格只是示意,核心在于把抽象的成本消耗变成一眼可见的指标。有了这个水位表,你每次做降本决策都有依据,而不是凭感觉。团队里也可以约定一条规则:新申请的资源必须提供容量预估和使用率预期,避免“怕不够,先申请多”。5. 从面试题到落地:我的一次低成本改造实操复盘说完了理论,我把一个真实的改造过程分享出来。为了不涉及具体公司信息,就叫它“某旧系统”好了。这套系统对外提供数据查询能力,平均QPS不到100,峰值也才150左右。它的问题是每月云成本高得离谱,而且团队每次开会都被质疑为什么这么高的费用。5.1 改造前的状态和关键数据系统原有部署情况如下:8台4核8G的ECS,前后端分离,部分服务各部署2个实例1套4核16G的MySQL主从,从库基本没读过2个Redis节点,其中一个只有某个列表缓存用得到十几个微服务,很多只依赖同一个核心库,各自部署日志存储保留45天,未压缩,未归档我拉出一个月的监控数据,做了成本归因。计算资源占了大头,约55%;数据库与缓存占25%;存储日志占15%;其他占5%。CPU利用率超过20%的服务只有两个,其余常年个位数。很明显,这不是“性能不够”,而是“供给过剩”。5.2 三步改造过程第一步,合并服务。我把依赖关系简单、没有独立扩展需求的6个服务合并成了2个。合并之后,原本需要12个实例的服务,现在只保留4个实例。这个动作最省成本,同时也暴露了很多隐藏问题:不同服务原本有独立的日志目录、配置项,合并后需要统一;端口冲突、依赖包版本冲突也需要慢慢收拾。好在流量不高,灰度验证压力不大。第二步,数据库降配与清理。将MySQL从4核16G降为2核8G,关闭了从库,改为用主库+备份机策略。原因是读流量极低,从库只起到了“摆设”作用。同时清理了20多个无用索引,归档了两年前的历史数据到便宜的对象存储。Redis也从双节点变为单节点,且只保留真正高频访问的数据。第三步,弹性与开关。所有应用接入了弹性伸缩,夜间自动缩容到2个实例。日志从45天调整为热日志7天,超过7天的自动压缩并转移到低频存储。这一步之后,存储成本直线下降。5.3 效果对比与踩过的坑改造后,月度云成本降了约48%。服务可用性没有明显下降,平均响应时间反而缩短了,因为合并后的调用链路更短。从效果上看,这次改造是成功的。但有几个坑我必须提醒。第一个坑是合并服务时的“连坐问题”。原本两个服务各自部署,一个出问题不影响另一个;合并后,某个模块的Bug会导致整包重启。为了安全,我给合并后的服务增加了更精细的线程池隔离,比如订单处理线程池和通知发送线程池分开,避免互相耗尽。第二个坑是缩容时的连接风暴。有一次夜间缩容从4个实例缩减到2个,结果所有服务重新建立数据库连接,瞬间把一个本来很空闲的数据库打出了大量连接。最后靠限制每个实例的数据库连接池上限,以及延长缩容的冷却时间,才解决。第三个坑是日志归档被“忽略”。因为压缩任务执行时间过长,导致当天的日志没有及时归档,存储量短暂反弹。后来调整了压缩任务的调度频率,并分片处理,就正常了。6. 如果面试官追问:这些降本手段的边界与风险在哪面试官通常会顺着你的方案继续追问,比如“你合并服务后,如果流量涨到10000 QPS怎么办?”或者“你降数据库规格,万一突然有热点活动怎么办?”这时候不要慌,答案的核心是“降本不是一锤子买卖,而是动态平衡”。任何优化方案都有前提和边界,你能说出来,反而说明你考虑全面。先说合并服务的边界。服务合并适用于低流量、单团队维护的系统。如果业务复杂度高、团队多人并行迭代,强行合并会造成代码耦合和发布互相制约。所以我在方案里会强调:合并不等于消灭模块边界,代码层面依然保持清晰的分包,只是部署时放到一起。再说降低数据库规格的边界。降规格的前提是性能监控数据支持,并且有快速回退机制。比如云数据库通常支持在控制台一键升配,用时也就几分钟。所以在降低成本的同时,要把“升配预案”写清楚,一旦流量突增或者大促来临,能及时恢复容量。这也是云厂商比自建机房有优势的地方。还有缓存和异步的边界。砍缓存的前提是数据库撑得住,一旦访问量增加或者出现热点,数据库压力会迅速上升。所以砍缓存时要谨慎评估读放大和热点场景。异步本来是降耗时的手段,但引入队列也要维护,如果只是100 QPS,完全可以用进程内线程池,没必要额外搭建消息队列中间件。最后,其实我想说,这类面试题没有标准答案。面试官想听的,是你能不能把一个具体问题落到可执行、可度量的方案中,并且能意识到方案的风险和盲区。如果你在面试时能把成本构成表拉出来,再把“先诊断—再治理—后评估”的思路说清楚,基本上已经是一个很完整的回答了。我在实际做降本的过程中,最大的体会是:在低流量场景下,最简单的方法往往最有效。合并一台机器、关掉一个不用的Redis、把日志保留期缩短,这些事情听起来不够“高大上”,但每个月省下来的钱是实实在在的。优化完所有技术项之后,记得把账单拉出来对比一下,这就是你最好的面试案例和绩效素材。