技术探索与实践优化:我在一个高并发项目中的实战经验
引言:为什么是“技术探索+实践优化”?

在我过去几年的工作中,经历过多个大小不一的项目。但真正让我意识到「技术探索」和「实践优化」重要性的,是一个高并发、多模块协作的在线支付平台开发项目。
这个项目最初的需求看似常规:为某个电商平台搭建一套可扩展、高可用的后端支付系统。但我们很快发现,需求背后隐藏着很多复杂的挑战——高并发下的性能瓶颈、接口调用延迟过高、分布式事务一致性难以保障……
这篇文章,我想以第一人称视角,从项目背景出发,带大家走进我在这次技术探索过程中的真实经历和思考,也希望我的一些踩坑教训和总结能够帮到正在面临类似问题的你。
项目背景介绍

2023年初,我们团队接手了一个企业级支付平台的架构设计和开发任务。项目目标是:
- 支持高峰期每秒上万笔订单创建与支付
- 集成多种第三方支付渠道(如微信、支付宝、银联)
- 实现统一交易流水管理、对账、风控等功能
- 系统需具备良好的伸缩性,便于后期接入新的业务线
我们的开发团队由前后端共6人组成,使用Java Spring Boot作为后端框架,前端则是Vue + Element UI。数据库使用MySQL集群,中间件包括Redis、RocketMQ、Zookeeper等。
初版方案在功能层面看起来很完整,但在测试阶段暴露的问题却让人头疼不已:
- QPS(每秒请求量)始终上不去,压测时出现严重毛刺
- 多个服务间协调困难,超时、断连频繁发生
- Redis缓存击穿导致部分接口响应时间飙升至5秒以上
- 本地事务与消息队列配合不当,出现数据状态不一致的情况
于是,我们不得不重新审视整个系统的设计结构和技术选型,并逐步引入新的技术和实践来优化系统表现。
遇到的核心问题与挑战


挑战1:性能瓶颈明显
我们最初的支付下单接口平均响应时间控制在180ms左右,这在单机压力小的时候没问题。但一到压测(模拟2000TPS),响应时间直接跳升到800ms,甚至超过1s。CPU利用率飙到90%+,GC频率也显著上升。
挑战2:分布式协调复杂度高
整个支付流程需要协调多个子系统:用户中心、积分系统、优惠券系统、库存系统等。每个系统都封装成独立的服务,通过RPC或HTTP进行通信。
一旦某一环节出错(比如远程调用失败),就会触发重试机制,进而引发连锁反应,比如重复扣减积分、订单状态混乱等问题。
挑战3:缓存穿透 & 击穿问题严重
为了加速用户信息获取,我们在Redis里做了热点数据缓存,但每次大促期间,某些热门商品详情页被疯狂访问,缓存失效后直接打到DB,造成短时间高负载,甚至宕机风险。
挑战4:异步消息一致性难保证
我们初期使用 RocketMQ 向外部通知系统发送支付结果,但由于消费者未做好幂等性和ACK处理,导致部分消息丢失或者重复消费。
我们选择的技术方案与优化路径


技术选型上的权衡与调整
起初,我们尝试用Spring Cloud Feign做服务间通信,但在压测过程中发现Feign+Ribbon组合存在性能瓶颈。最终我们转向了自研轻量级RPC客户端 + Netty 的方式,提升了接口调用性能约30%,同时降低了上下文切换开销。
此外,为了缓解高并发压力,我们引入了如下优化手段:
✅ 使用CompletableFuture实现异步编排
原本我们采用同步调用的方式,依次调用各个子系统,流程非常线性。后来,我们将可并行执行的部分抽离出来,使用CompletableFuture并行执行,并加入异常回滚逻辑:
public void processPayment() {
CompletableFuture<Void> userFuture = CompletableFuture.runAsync(() -> userService.getUserInfo(userId));
CompletableFuture<Void> inventoryFuture = CompletableFuture.runAsync(() -> inventoryService.checkStock(productId));
CompletableFuture.allOf(userFuture, inventoryFuture).exceptionally(ex -> {
rollbackAll();
return null;
}).join();
}
这种做法虽然增加了代码复杂度,但大幅降低了整体耗时,接口响应时间稳定在200ms以内。
✅ 缓存穿透 & 击穿优化方案
我们采用了两种策略来解决缓存问题:
- 布隆过滤器预判:对不存在的数据ID做前置拦截;
- 缓存空值与随机过期时间:避免同一时间大量Key失效;
- 缓存互斥锁:当Key失效时只允许一次请求查询数据库并重建缓存;
public User getUserById(String userId) {
String cacheKey = "user:" + userId;
String result = redis.get(cacheKey);
if (result == null) {
synchronized (this) {
result = redis.get(cacheKey);
if (result == null) {
// 数据库查一次
result = db.queryUser(userId);
// 设置随机过期时间,避免集中失效
int expireTime = 60 * 60 + new Random().nextInt(600);
redis.setex(cacheKey, expireTime, result);
}
}
}
return JSON.parseObject(result);
}
这一系列策略使得我们成功避开了多次因缓存雪崩带来的故障。
✅ 最终一致性保障 - 幂等+消息补偿机制
对于异步通知场景,我们做了以下改造:
- 在消息体中加上唯一业务编号
bizId - 消息消费者保存已处理记录到本地DB
- 增加补偿Job定时扫描未确认消息,并发起回调
例如在消费端:
@KafkaListener(topic = "payment_notify")
public void onMessage(Message message) {
String bizId = message.getBizId();
if (redis.exists("consumed:" + bizId)) {
log.warn("Already processed: {}", bizId);
return;
}
try {
paymentCallback(message);
redis.setex("consumed:" + bizId, 7 * 24 * 3600, "done");
} catch (Exception e) {
log.error("Fail to consume msg: {}, retry later", message);
messageProducer.sendAgain(message);
}
}
这种设计虽然略显繁琐,但在实际运行中很好地解决了消息重复或丢失的问题。
踩过的坑及应对建议
坑点1:没有做好容量评估,导致前期架构过度设计
刚开始我们盲目追求“微服务化”,把本该聚合在一起的功能拆成了七八个微服务。结果部署复杂、网络调用链变长,反而拖慢了响应速度。后来我们做了合并调整,将核心链路的几个服务聚合为“支付核心域”模块,性能提升2倍不止。
建议:不要一开始就微服务切得过细,尤其是业务模型还不清晰的情况下。
坑点2:忽略监控埋点,调试成本陡增
初期我们对日志监控体系考虑不周,出现问题往往靠打印日志排查,效率极低。后来接入SkyWalking做全链路追踪,在压测和线上环境中迅速定位性能瓶颈和异常节点。
建议:越早接入APM越好,能省下大量的排查时间。
坑点3:忽视压测环境的真实模拟
刚开始压测只是模拟单一接口,忽略了真实业务场景下的复合操作。结果上线前才发现多个服务交叉调用下产生了资源争抢、死锁等问题。
建议:一定要构建基于真实业务场景的压测脚本,否则就是无效压测。
效果与收益
经过一系列优化与重构之后,项目的整体表现发生了翻天覆地的变化:
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 平均QPS | ~1200 | ~6800 |
| 接口成功率 | 93.2% | 99.95% |
| 日志追踪能力 | 无 | SkyWalking 全链路支持 |
| 发布周期 | 2周/次 | 自动化CI/CD后2小时 |
最直观的一个例子是,我们在双十一大促当天,面对峰值流量突破每分钟3万次下单请求时,系统整体保持平稳,未出现服务不可用或订单数据丢失的问题。
经验与建议总结
作为一名开发者,我也想分享几点心得体会给正在走在这条路上的同学:
📌 不要迷信新技术,适合自己的才是最好的
技术选型永远不是堆砌新名词,而是要结合业务场景、团队能力、维护成本等多个维度来做取舍。
📌 代码可以写快,设计要慢慢磨
早期设计的随意往往会导致后期巨大的返工成本。花时间做好模块划分、领域建模、接口抽象是非常值得的。
📌 要学会站在运维的角度看问题
很多时候,一个问题的背后不仅仅是代码,还可能涉及到部署方式、资源配置、监控报警等环节。只有站在全局视角去思考问题,才能真正做到心中有数。
📌 团队协作是项目成功的基石
在这个项目中,我深刻体会到沟通的重要性。定期站会、白板讨论、文档沉淀……这些看似“老套”的流程,其实是推动团队高效运作的关键。
结语
技术探索从来不是一条直线,它更像是在黑暗中摸索的一束光,有时方向错误、有时绕了远路,但只要坚持下去,总会迎来破晓时刻。
我希望这篇来自真实项目的分享,能让你看到技术落地背后的波折与成长。愿你在接下来的每一个项目中,都能少走弯路、多出成果。
如果你也有类似的实战经验,欢迎留言交流。技术的路上,我们一起走。

评论 0