1. 项目概述这个库存管理系统是我去年为一家中型电商企业开发的内部管理工具核心目标是解决他们长期存在的库存数据不准确、人工盘点效率低下问题。系统采用Spring Boot框架开发前后端分离架构对接了企业现有的ERP系统实现了从商品入库到出库的全流程数字化管理。提示在电商行业库存准确率每提升1%就能减少约3%的运营成本这是很多企业愿意投入资源做库存系统的根本原因。系统上线后运行稳定日均处理2万库存变动记录将原本需要4小时的日盘点工作缩短到15分钟完成。下面我会从技术选型、核心模块、实现细节和踩坑经验几个维度完整还原这个项目的开发过程。2. 技术架构设计2.1 技术栈选型选择Spring Boot作为基础框架主要基于以下考量快速启动内嵌Tomcat简化部署符合企业两周出原型的要求生态完整Spring Data JPA QueryDSL完美解决复杂库存查询需求可扩展性后期需要对接WMS系统时Spring Integration能提供现成方案核心组件版本spring-boot.version2.7.5/spring-boot.version hibernate.version5.6.12.Final/hibernate.version querydsl.version5.0.0/querydsl.version2.2 系统架构图[客户端] ←HTTP→ [Spring Boot] ←JDBC→ [MySQL] ↑ ↓ [Redis] [RabbitMQ]关键设计决策采用Redis缓存热点商品库存如促销品设置5分钟本地缓存Redis二级缓存库存变动通过RabbitMQ异步处理避免高并发下的数据库锁竞争使用MySQL窗口函数实现库存变化趋势分析3. 核心功能实现3.1 库存扣减设计最关键的库存扣减接口需要考虑并发安全问题我们最终采用方案Transactional public boolean deductInventory(Long skuId, int quantity) { // 使用SELECT...FOR UPDATE实现行级锁 Inventory inventory inventoryRepository.findBySkuIdForUpdate(skuId); if(inventory.getAvailableQuantity() quantity) { return false; } inventory.setAvailableQuantity(inventory.getAvailableQuantity() - quantity); // 记录库存变更流水 inventoryLogRepository.save(new InventoryLog(skuId, quantity, DEDUCT)); return true; }注意实际生产环境还需要处理分布式锁问题我们通过Redisson实现了跨JVM的锁管理3.2 库存预警模块预警规则配置采用策略模式实现public interface AlertStrategy { boolean check(Inventory inventory); } // 示例低于安全库存预警 Component public class SafetyStockStrategy implements AlertStrategy { Override public boolean check(Inventory inventory) { return inventory.getAvailableQuantity() inventory.getSafetyStock(); } }预警触发后系统会在企业微信发送通知在管理后台生成采购建议单记录预警历史供分析使用4. 性能优化实践4.1 热点库存优化针对秒杀商品这类热点数据我们设计了三级缓存方案本地缓存Caffeine有效期30秒最大1000个SKURedis集群库存预扣减采用Lua脚本保证原子性数据库最终一致性通过定时任务同步关键Redis Lua脚本local key KEYS[1] local change tonumber(ARGV[1]) local current tonumber(redis.call(GET, key) or 0) if current change 0 then redis.call(INCRBY, key, change) return 1 else return 0 end4.2 批量处理优化对于入库单这类批量操作我们改用了JDBC批量插入Transactional public void batchImport(ListInventory items) { jdbcTemplate.batchUpdate( INSERT INTO inventory(...) VALUES(...), new BatchPreparedStatementSetter() { // 实现批量参数设置 }); }实测数据处理1000条入库记录从原来的12秒降低到1.3秒5. 踩坑经验总结5.1 事务失效问题遇到过Transactional注解不生效的情况最终发现两个关键点自调用问题同类方法内调用不会触发AOP代理异常捕获catch住异常但没有重新抛出会导致事务不回滚解决方案// 错误示例 public void updateStock() { try { deductInventory(); // 同类调用 } catch (Exception e) { log.error(e); // 吞掉异常 } } // 正确做法 Transactional public void updateStock() { inventoryService.deductInventory(); // 通过Service调用 // 或者抛出RuntimeException }5.2 库存超卖排查曾出现凌晨促销时库存超卖问题最终定位原因是缓存与数据库不一致没有做库存预占机制改进方案引入库存预占表hold_stock增加库存校验定时任务实现自动补偿机制6. 监控与运维6.1 监控指标配置通过Micrometer暴露的关键指标inventory.change.count库存变动次数inventory.lock.time锁等待时间inventory.cache.hit缓存命中率Grafana监控看板包含实时库存水位库存变动频率预警触发统计6.2 数据迁移方案从旧系统迁移数据时我们采用分批次迁移先迁移基础商品数据再迁移当前库存快照最后迁移6个月内的流水记录迁移脚本示例INSERT INTO new_inventory(sku_id, quantity) SELECT product_code, stock_count FROM legacy_stock WHERE warehouse EAST LIMIT 5000 OFFSET 0;7. 扩展与演进系统后续迭代增加了两个重要功能7.1 库存预测基于历史销售数据的预测模型# 使用Prophet进行销量预测 model Prophet(seasonality_modemultiplicative) model.fit(df) future model.make_future_dataframe(periods30) forecast model.predict(future)7.2 移动端支持开发了PDA客户端功能扫码快速入库库存盘点实时同步库位导航功能实现技术使用WebSocket保持长连接采用QuaggaJS实现浏览器端扫码离线模式使用IndexedDB暂存数据这个项目让我深刻体会到一个好的库存系统不仅要考虑技术实现更要理解业务场景。比如我们最初设计的预警阈值是固定值后来改为根据销售旺季动态调整这个改进使无效预警减少了70%。在实际开发中一定要多和仓库管理员沟通了解他们的真实工作流程