【技术底稿 39】自测阶段看不下去:一次缓存 + MyBatis-Plus 联合性能改造
一、背景:还没上线,我自己先受不了了
项目还在自测阶段,功能刚跑通,按理说性能可以先放一放。
但我自己测着测着,实在忍不下去了:
用户登录一次:近300ms
字典树第一次:2.5s
字典树第二次:3.7s(缓存完全失效,越查越慢)
这要是上线,前端同学绝对天天来敲门。
再加一个硬性要求:必须兼容国产化数据库(达梦、人大金仓)。原来一堆 MyBatis XML 联表查询、统计 SQL,到时候适配能改到崩溃。
于是我决定:上线前,主动把性能和代码结构一起盘一遍。
二、整体改造方案
两条线并行,互不冲突,只做增量优化,不推翻重来:
| 改造线 | 目标 | 覆盖模块 |
|---|---|---|
| MyBatis-Plus 改造 | 简化 CRUD、干掉冗余 XML、兼容国产数据库 | 用户、字典、权限、菜单、项目、里程碑、成果、成员、文件、邀请、论坛 |
| 缓存体系改造 | 降低延迟、减轻 DB 压力、解决字典树巨慢问题 | 用户、字典、角色/权限、资源菜单、人员组织类型 |
三、MyBatis-Plus 改造:干掉 80% 的 MyBatis XML
3.1 为什么要改
每个表都写 XML,简单 CRUD 也要手写 SQL
复杂查询、统计、联表全堆在一起,维护爆炸
后续要适配达梦、人大金仓,MP 兼容性远优于原生 MyBatis
3.2 改造策略(非常关键)
不是一刀切,而是二八原则:
80%单表 CRUD、分页、条件查询 → 交给 MP
20%复杂联表、递归、统计 → 保留 XML
这次一共迁移 7 个核心模块:项目、里程碑、成果、项目成员、文件、邀请、论坛。
3.3 踩坑记录(真实!)
改造时漏了一个统计方法countByProjectId,编译不报错,但运行结果不对。
解决方案:把 XML 里所有 SQL 过一遍,确保要么被 MP 覆盖,要么明确保留。
四、缓存体系改造:从 3.7s → 100ms
4.1 问题有多严重
| 场景 | 耗时 |
|---|---|
| 用户登录 | ~300ms |
| 字典树首次 | 2.5s |
| 字典树二次 | 3.7s(缓存不生效,反而更慢) |
4.2 改造方案
| 模块 | 缓存策略 | 效果 |
|---|---|---|
| 用户信息 | Redis + 主动清理 | 登录 ↓66% |
| 字典树 | Redis + Gzip 压缩 | 二次请求 ↓97% |
| 角色/权限 | Redis + 实时更新 | 变更立即生效 |
| 资源菜单 | Redis 缓存 | 菜单加载加速 |
| 组织类型 | Redis 12h 过期 | 减少 DB 查询 |
4.3 字典树巨慢的真凶:大 JSON 反序列化
字典树结构复杂,JSON 体积巨大。从 Redis 读出来后,光解析就要几秒钟。
最终方案:Gzip 压缩存储——体积减少约70%,反序列化开销直接消失。
4.4 缓存预热(细节拉满)
服务启动就自动加载常用数据,不让第一个用户等待。
@Component @RequiredArgsConstructor public class CachePreheater { private final SysDictService dictService; private final ResourceService resourceService; private final RoleService roleService; @EventListener(ApplicationReadyEvent.class) public void preheat() { CompletableFuture.runAsync(() -> { dictService.getDictTree(); resourceService.getAllVisibleMenus(); roleService.getByRoleCode("manager"); }); } }五、顺手修复的小问题
| 问题 | 解决方案 |
|---|---|
| 角色多选过滤 | UserQuery 增加roleCodes |
| 统计方法遗漏 | 恢复countByProjectId等 SQL |
| 审批状态更新 | 改用 MPLambdaUpdateWrapper |
PageResult.empty()泛型缺失 | 补充泛型方法,代码清爽 |
六、最终性能成果(数据说话)
| 场景 | 优化前 | 优化后 |
|---|---|---|
| 用户登录 | ~300ms | ~100ms |
| 字典树首次 | 2.5s | 1s |
| 字典树二次 | 3.7s | 100ms |
| 项目列表 | 每次 JOIN 查库 | 缓存 + MP 分页 |
自测阶段就把坑全部填平,上线后安安心心。
七、待办(后续规划)
| 任务 | 优先级 | 说明 |
|---|---|---|
| 项目名称缓存 | 中 | 目前还是实时查库 |
| 批量分享话题优化 | 低 | 使用频率不高,先不动 |
| 国产化数据库兼容测试 | 待排期 | MP 已铺好路,等环境到位 |
八、文末总结
此文由自测阶段主动发起的性能优化实战整理而成,从字典树 3.7s、登录 300ms 的性能痛点切入,逐步落地 MyBatis-Plus 精简改造与 Redis 缓存优化,梳理出一套 “不推翻重来、增量优化” 的实战方案。
全文收录 MyBatis-Plus 改造技巧、Redis 缓存优化(含 Gzip 压缩、缓存预热)、真实踩坑复盘及性能对比数据,覆盖国产化数据库适配前置准备,属于后端开发刚需性能优化干货。
《技术底稿》系列第 39 篇,收藏留存,上线前性能优化、MyBatis-Plus 迁移、缓存体系搭建可直接照搬参考,提前排坑,避免上线后被动运维。
