关于技术探索与实践的一些经验
上周五晚上十一点半,我瘫在工位上,盯着屏幕里 Spring Boot 应用启动日志里那行 Started Application in 8.234 seconds 发呆。窗外国贸的霓虹灯还亮着,通勤一小时回家也得凌晨了,干脆再调会儿代码吧——反正明天是周末,产品经理应该不会半夜在钉钉@我改需求(天真如我)。
我是北京一家小厂的后端开发,独立负责一条业务线。说“独立负责”,其实就是一个人扛起从需求评审、接口设计、数据库建模、联调测试到线上运维的全链路。团队不到十个人,老板信奉“小而美”,所以没有专职测试、没有 SRE,连 CI/CD 都是我用 Jenkins 搭的(别问,问就是被逼的)。最近除了搞业务,还在偷偷啃 AI 相关的东西——毕竟听说大模型要取代程序员了,得先学会怎么 prompt 才能保住饭碗(笑)。
今天想和大家聊聊我在技术探索与实战中踩过的坑、攒下的经验。不讲高大上的理论,全是血泪换来的实战经验,尤其围绕我们主力框架 Spring Boot 展开。如果你也在小厂单打独斗,或许能共鸣一二。
起因:一个“简单”的需求,差点让我原地爆炸
事情发生在去年双11前两周。产品经理突然找我:“咱们加个实时库存预警吧,商品快卖光的时候自动发企业微信通知运营。”
听起来挺简单?但现实是:
- 我们的库存服务是单体架构,基于 Spring Boot 2.6
- 没有消息队列(老板说“没必要,省点钱”)
- 数据库用的是 MySQL,高并发下频繁读写已有点吃力
我当时内心 OS:这不就是典型的“又要马儿跑,又要马儿不吃草”?但 deadline 就在眼前,只能硬着头皮上。
第一版方案:定时任务轮询 + 睡觉式优化
最朴素的想法:写个 @Scheduled 定时任务,每 30 秒扫一遍库存表,发现低于阈值就发通知。
@Scheduled(fixedDelay = 30_000)
public void checkLowStock() {
List<Product> lowStockProducts = productRepository.findByStockLessThan(10);
for (Product p : lowStockProducts) {
wechatService.sendAlert("【库存告急】" + p.getName() + "仅剩" + p.getStock() + "件!");
}
}
结果上线第二天,DBA 找上门:“你这定时任务把主库 CPU 干到 90% 了!能不能别这么暴力?”
我:……(默默打开监控面板,看到 QPS 瞬间飙升)
教训一:别在生产环境裸奔轮询,尤其当数据量上去后,数据库不是你的玩具。
第二版:引入缓存 + 异步非阻塞
痛定思痛,我决定用 Redis 缓存库存状态,并采用事件驱动的方式触发检查。
具体做法:
- 每次下单成功后,通过
ApplicationEventPublisher发布StockReducedEvent - 监听该事件,在异步线程中检查库存是否低于阈值
- 若低于阈值且未通知过,则发送预警并标记“已通知”
// 下单服务中
@Transactional
public void placeOrder(Order order) {
// ...扣减库存逻辑
stockService.reduce(order.getProductId(), order.getQuantity());
// 发布事件
applicationEventPublisher.publishEvent(
new StockReducedEvent(order.getProductId())
);
}
// 事件监听器
@Component
public class StockAlertListener {
@Async // 开启异步
@EventListener
public void handleStockReduced(StockReducedEvent event) {
Long productId = event.getProductId();
Integer currentStock = stockService.getCurrentStock(productId);
if (currentStock < 10 && !redisTemplate.hasKey("alert_sent:" + productId)) {
wechatService.sendAlert("【库存告警】商品ID=" + productId + "库存不足!");
redisTemplate.opsForValue().set("alert_sent:" + productId, "1", Duration.ofHours(24));
}
}
}
同时在 application.yml 中开启异步支持:
spring:
task:
execution:
pool:
core-size: 4
max-size: 8
效果:数据库压力骤降,预警延迟控制在毫秒级,且避免重复通知。
但问题又来了:某天测试同学反馈,“为什么我本地调试时事件没触发?”
一查才发现:@Async 默认使用的是 SimpleAsyncTaskExecutor,每个任务新建线程,但在测试环境下事务回滚导致事件丢失。
教训二:异步 + 事务 = 高危组合。务必确保事件发布在事务提交之后,或使用可靠的消息中间件(可惜我们没有)。
技术选型的权衡:小厂的“将就”哲学
其实我知道,最佳实践是引入 Kafka/RabbitMQ 做解耦。但现实很骨感:
| 方案 | 优点 | 缺点 | 是否可行(小厂视角) |
|---|---|---|---|
| 定时轮询 | 实现简单 | DB 压力大、实时性差 | ❌ 已被 DBA 列入黑名单 |
| Spring Event + Async | 无外部依赖、响应快 | 事务边界模糊、可靠性低 | ✅ 勉强可用 |
| 引入消息队列 | 可靠、解耦、削峰 | 运维成本高、需额外服务器 | ❌ 老板不同意 |
最后我们选择了“够用就好”的中间路线。虽然不够完美,但在资源受限下,快速交付 + 可维护性比“架构洁癖”更重要。
最近的新尝试:用 AI 辅助写 CRUD?
说到技术探索,最近我在研究怎么把 AI 融入日常开发。比如让 Copilot 帮我生成 Spring Boot 的 Repository 方法:
“帮我写一个根据商品分类和价格区间查询商品的方法”
它真能吐出:
List<Product> findByCategoryAndPriceBetween(String category, BigDecimal minPrice, BigDecimal maxPrice);
但有一次它建议我用 @Query("SELECT * FROM products WHERE ...") 写原生 SQL,结果忘了加 nativeQuery = true,直接报错:
org.hibernate.QueryException: Named parameter not bound : category
我:……AI 啊,你还是太年轻。
不过说实话,AI 确实提升了我的编码效率,尤其是在写样板代码、单元测试、文档注释时。但它替代不了我对业务的理解和对系统边界的判断——比如什么时候该加缓存,什么时候该熔断,这些还得靠人。
总结:在夹缝中成长
回顾这段经历,我最大的体会是:
- 实战经验 ≠ 理论正确,而是在资源、时间、人力限制下找到最优解
- Spring Boot 很强大,但别滥用它的便利性(比如乱用
@Async或@Transactional) - 小厂开发者必须“全栈思维”:既要懂代码,也要看监控、读日志、和 DBA 聊索引
- 技术探索不能停,哪怕每天只学 30 分钟,积少成多
现在,我的库存预警服务已经稳定运行半年多,没再出过 P0 事故。上周运维甚至夸我:“你这服务,CPU 曲线平得像我的发际线。”
深夜写代码的日子还在继续,通勤依旧一小时,但每次看到自己写的系统稳稳扛住流量高峰,那种成就感,真的值了。
共勉, fellow coder。

评论 0