【技术底稿 39】自测阶段看不下去:一次缓存 + MyBatis-Plus 联合性能改造
一、背景还没上线我自己先受不了了项目还在自测阶段功能刚跑通按理说性能可以先放一放。但我自己测着测着实在忍不下去了用户登录一次近300ms字典树第一次2.5s字典树第二次3.7s缓存完全失效越查越慢这要是上线前端同学绝对天天来敲门。再加一个硬性要求必须兼容国产化数据库达梦、人大金仓。原来一堆 MyBatis XML 联表查询、统计 SQL到时候适配能改到崩溃。于是我决定上线前主动把性能和代码结构一起盘一遍。二、整体改造方案两条线并行互不冲突只做增量优化不推翻重来改造线目标覆盖模块MyBatis-Plus 改造简化 CRUD、干掉冗余 XML、兼容国产数据库用户、字典、权限、菜单、项目、里程碑、成果、成员、文件、邀请、论坛缓存体系改造降低延迟、减轻 DB 压力、解决字典树巨慢问题用户、字典、角色/权限、资源菜单、人员组织类型三、MyBatis-Plus 改造干掉 80% 的 MyBatis XML3.1 为什么要改每个表都写 XML简单 CRUD 也要手写 SQL复杂查询、统计、联表全堆在一起维护爆炸后续要适配达梦、人大金仓MP 兼容性远优于原生 MyBatis3.2 改造策略非常关键不是一刀切而是二八原则80%单表 CRUD、分页、条件查询 → 交给 MP20%复杂联表、递归、统计 → 保留 XML这次一共迁移 7 个核心模块项目、里程碑、成果、项目成员、文件、邀请、论坛。3.3 踩坑记录真实改造时漏了一个统计方法countByProjectId编译不报错但运行结果不对。解决方案把 XML 里所有 SQL 过一遍确保要么被 MP 覆盖要么明确保留。四、缓存体系改造从 3.7s → 100ms4.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审批状态更新改用 MPLambdaUpdateWrapperPageResult.empty()泛型缺失补充泛型方法代码清爽六、最终性能成果数据说话场景优化前优化后用户登录~300ms~100ms字典树首次2.5s1s字典树二次3.7s100ms项目列表每次 JOIN 查库缓存 MP 分页自测阶段就把坑全部填平上线后安安心心。七、待办后续规划任务优先级说明项目名称缓存中目前还是实时查库批量分享话题优化低使用频率不高先不动国产化数据库兼容测试待排期MP 已铺好路等环境到位八、文末总结此文由自测阶段主动发起的性能优化实战整理而成从字典树 3.7s、登录 300ms 的性能痛点切入逐步落地 MyBatis-Plus 精简改造与 Redis 缓存优化梳理出一套 “不推翻重来、增量优化” 的实战方案。全文收录 MyBatis-Plus 改造技巧、Redis 缓存优化含 Gzip 压缩、缓存预热、真实踩坑复盘及性能对比数据覆盖国产化数据库适配前置准备属于后端开发刚需性能优化干货。《技术底稿》系列第 39 篇收藏留存上线前性能优化、MyBatis-Plus 迁移、缓存体系搭建可直接照搬参考提前排坑避免上线后被动运维。