缓存组件设计复盘:从硬编码到带模式参数的缓存进化
缓存组件设计复盘从硬编码到带模式参数的缓存进化电子面单对接实录 · 技术深潜 前情《Token刷新与缓存失效一对被忽视的上下游》新架构里有一个缓存组件专门缓存各平台的Token配置避免每次取号都查数据库。最初的设计很简单平台编码加组织ID做Key查不到就查库查到就缓存。跑了一段时间后发现一个隐患同一个平台的不同业务模式缓存会互相覆盖。这篇文章完整复盘这个缓存组件的设计演进过程——从最初的两层缓存结构到新增六个方法、提取公共查询逻辑、处理JDK版本兼容以及最重要的给缓存Key加一个模式后缀。01 初始设计两层缓存按平台加组织路由缓存组件的最初版本结构清晰两层缓存平台应用配置缓存Key 平台编码存平台基础配置平台Token配置缓存Key 平台编码 分隔符 组织ID存Token的数据库记录查询逻辑先从缓存取缓存未命中就查数据库查到后放入缓存。支持手动清除指定缓存支持定时全量刷新。平台差异处理大部分平台通过通用Token配置表查Token但有一个社交电商平台的Token存在专门的授权表里需要特殊处理——直接跳过通用查询走白名单通道。这个设计跑了一段时间没问题。直到有一天我在梳理Token刷新逻辑时发现了一个隐患。02 问题发现两种业务模式在抢同一个缓存Key系统里有一个短视频电商平台它有两种业务模式普通商家模式和代发模式。两种模式用同一个平台编码但Token存在不同的字段——普通Token和代发Token是两套独立的凭证。问题来了缓存Key是平台编码_组织ID两种模式的Key完全一样。普通取号缓存Key PLAT_A_123 → 查到的是普通Token 代发取号缓存Key PLAT_A_123 → 缓存命中返回的还是普通Token应该是代发Token先刷新普通Token再刷代发Token或者反过来缓存会被互相覆盖。当前没出问题是因为两种模式的刷新在同一个定时任务里几乎同时更新缓存清空后重新加载的值恰好是正确的。但未来如果把普通和代发的刷新任务分离比如普通每小时刷一次代发每两小时刷一次就会出现缓存加载到过期Token的情况。03 解决方案给缓存Key加一个模式后缀最简单的方案在缓存Key中增加业务模式维度。// 原Key平台编码 _ 组织IDStringkeyplatCode_orgId;// 新Key平台编码 _ 组织ID _ 业务模式StringkeyplatCode_orgId;if(bizMode!null!bizMode.isEmpty()){keykey_bizMode;}不同模式存在不同的Key下互不干扰普通取号缓存Key PLAT_A_123_normal → 缓存未命中 → 查库 → 拿到普通Token 代发取号缓存Key PLAT_A_123_daifa → 缓存未命中 → 查库 → 拿到代发Token设计约束bizMode为null或空字符串时退化为原有Key格式。完全向后兼容——现有调用方不需要任何修改只有需要区分模式的场景才传入bizMode。04 方法扩展新增六个方法覆盖所有场景加了一个参数就需要配套的查询和清除方法。最终新增了六个方法方法用途getTokenConfig(platCode, org, bizMode)带模式参数的查询evictToken(platCode, org, bizMode)带模式参数的单个清除evictTokenById(platCode, orgId, bizMode)带模式参数的按ID清除evictByPlatform(platCode, bizMode)带模式参数的按平台批量清除evictTokenById(platCode, orgId)按组织ID清除不需要完整对象evictByPlatform(platCode)按平台批量清除无模式参数按组织ID清除原本的清除方法需要传入完整的组织对象。但有些调用场景比如外部监控系统检测到Token过期只知道组织ID没有完整对象。新增一个重载方法只传ID即可。按平台批量清除原本只能单个清除或全部清除。如果某个平台的AppKey全局变更需要失效该平台下所有组织的缓存只能遍历组织逐个清除。新增按平台批量清除一次操作搞定。带模式参数的批量清除更进一步——如果只是代发模式的AppKey变更只清除代发模式的缓存不影响普通模式。批量清除时按模式后缀匹配。05 JDK兼容removeIf不能用批量清除的核心逻辑是遍历缓存Map删除匹配前缀和后缀的Key。Java 8 有现成的方法// Java 8简洁优雅cache.keySet().removeIf(key-key.startsWith(prefix));但项目的运行环境是旧版本JDK不支持removeIf。只能改为迭代器模式// 旧版本JDK兼容迭代器遍历IteratorStringitcache.keySet().iterator();while(it.hasNext()){Stringkeyit.next();if(key.startsWith(prefix)){it.remove();}}带模式参数的批量清除需要在匹配前缀的基础上再加后缀判断// 匹配以 PLAT_A_ 开头、以 _daifa 结尾的KeyIteratorStringitcache.keySet().iterator();while(it.hasNext()){Stringkeyit.next();if(key.startsWith(prefix)key.endsWith(suffix)){it.remove();}}代码量多了几行但逻辑完全一致。遗留系统的技术栈约束就是这样——新版本JDK的流式API、Lambda表达式都用不了设计方案时必须考虑向下兼容。06 代码重构提取公共查询方法加带模式参数的查询方法时发现整个数据库查询逻辑在两个重载方法中完全重复——包括白名单判断、通用表查询、各平台分支的判断。提取一个公共方法loadTokenFromDBprivateOrgTokenConfigloadTokenFromDB(StringplatCode,OrgInfoorg){// 白名单社交电商平台直接查授权表if(isWhiteListPlatform(platCode)){returnqueryFromAuthTable();}// 其他平台查通用Token表TokenRecordrecordqueryFromTokenTable(org.getId());if(recordnull){returnnull;}// 根据平台编码获取对应的配置对象if(isPlatformA(platCode)){returnrecord.getConfigA();}elseif(isPlatformB(platCode)){returnrecord.getConfigB();}// ... 其他平台分支}关键细节每个分支保留了原有的日志输出包括平台中文名。这确保了回归测试时日志一字不差不会因为日志格式变化触发监控告警。重构后两个查询方法只剩缓存Key构建方式的差异——一个带模式后缀一个不带。数据库查询完全委托给公共方法。07 向后兼容旧代码一行不动所有新增方法都是可选的扩展原有方法的行为完全不变原有查询方法两个参数行为不变原有清除方法按对象清除行为不变原有全部清除方法行为不变新方法是额外的工具旧代码不需要任何修改。当需要区分模式时调用方传入bizMode参数即可。回归测试验证通过所有平台分支的日志输出与原有代码完全一致。08 核心收获1. 缓存Key的粒度设计在系统演进中会被重新审视。最初设计时只有普通模式代发是后来加的。一个后缀解决两个模式抢Key的问题改动量很小——但前提是Key的构建逻辑是收敛在一处的而不是散落在各调用方。2. 公共方法提取的价值不在当下在未来。提取数据库查询公共方法后后续新增平台只需要在判断分支中加一个条件两个查询方法自动生效。如果没提取新增平台要改两个地方忘了一个就是Bug。3. 向后兼容是遗留系统改造的底线。bizMode为 null 时退化为原有行为——这行判断保证了新老代码可以并存。新增方法、提取公共逻辑都不影响已有调用方。4. 技术栈约束影响设计决策。removeIf一行代码能解决的问题在旧版本JDK上要多写四行。这不是设计缺陷是工程现实。讨论话题你做缓存设计时遇到过Key粒度不够导致数据互相覆盖的情况吗是加后缀还是重新设计了Key结构评论区聊聊。

相关新闻

AutoJs6应用打包:从脚本到独立应用的完整转型指南

AutoJs6应用打包:从脚本到独立应用的完整转型指南

AutoJs6应用打包:从脚本到独立应用的完整转型指南 【免费下载链接】AutoJs6 安卓平台 JavaScript 自动化工具 (Auto.js 二次开发项目) 项目地址: https://gitcode.com/gh_mirrors/au/AutoJs6 你是否曾想过将精心编写的JavaScript自动化脚本变成独立的安卓应用…

2026/8/18 7:20:01 阅读更多 →
三菱PLC工具包升级:从兼容性审计到工程化部署的完整指南

三菱PLC工具包升级:从兼容性审计到工程化部署的完整指南

最近在整理工控项目资料时,发现一个挺有意思的现象:很多工程师朋友,无论是刚入行的新手还是有一定经验的熟手,在拿到一个新版本的PLC编程软件或工具包时,第一反应往往是“赶紧装上试试”。结果呢?要么是安装…

2026/8/17 8:45:16 阅读更多 →
如何在Linux上实现毫秒级文件搜索:FSearch深度指南与实战技巧

如何在Linux上实现毫秒级文件搜索:FSearch深度指南与实战技巧

如何在Linux上实现毫秒级文件搜索:FSearch深度指南与实战技巧 【免费下载链接】fsearch A fast file search utility for Unix-like systems based on GTK3 项目地址: https://gitcode.com/gh_mirrors/fs/fsearch 在Linux系统中查找文件时,你是否…

2026/8/22 1:00:07 阅读更多 →

最新新闻

如何用scrcpy把安卓手机投屏到电脑:5分钟上手的完整教程

如何用scrcpy把安卓手机投屏到电脑:5分钟上手的完整教程

如何用scrcpy把安卓手机投屏到电脑:5分钟上手的完整教程 【免费下载链接】scrcpy Display and control your Android device 项目地址: https://gitcode.com/GitHub_Trending/sc/scrcpy scrcpy 是一款免费的开源 Android 投屏工具:它通过 USB 或 …

2026/8/24 12:16:10 阅读更多 →
Not your weights,not your brain

Not your weights,not your brain

对于X-plore仓库: 技术含量不是最高的,商业模式是没有的,代码是AI写的。用持续性和学习能力证明:在信息爆炸的时代,帮别人省时间,本身就是巨大的价值

2026/8/24 12:16:10 阅读更多 →
AI Agent在商超场景的工程化落地:从需求拆解到生产部署

AI Agent在商超场景的工程化落地:从需求拆解到生产部署

1. 这篇文章真正要解决的问题如果你正在负责一个线下零售门店的数字化升级项目,或者你是一名对AI落地实体商业感兴趣的技术人,那么最近你一定被各种“AI Agent”刷屏了。从写代码的Devin到能规划行程的GPTs,AI似乎无所不能。但当你真的想把一…

2026/8/24 12:16:10 阅读更多 →
蜂巢智控HiveOps四项产品业务分工与抖音运营总控使用指南

蜂巢智控HiveOps四项产品业务分工与抖音运营总控使用指南

内容说明:本文依据客户已提供资料整理,实际服务以沟通确认的范围为准。 蜂巢智控 HiveOps 四项产品业务分工与抖音运营总控使用指南 蜂巢智控 HiveOps 是一家面向企业、商家和专业团队的 AI 自动化产品品牌,当前提供股票研究信号池、微信自动…

2026/8/24 12:16:10 阅读更多 →
单片机毕设选题推荐:基于 STM32 的光敏人体复合感应照明控制系统设计 基于 STM32 单片机的双模智能调光设备开发(018304)

单片机毕设选题推荐:基于 STM32 的光敏人体复合感应照明控制系统设计 基于 STM32 单片机的双模智能调光设备开发(018304)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/8/24 12:16:10 阅读更多 →
Spaceship Generator 完整指南:3 步在 Blender 里生成无限 3D 太空船

Spaceship Generator 完整指南:3 步在 Blender 里生成无限 3D 太空船

Spaceship Generator 完整指南:3 步在 Blender 里生成无限 3D 太空船 【免费下载链接】SpaceshipGenerator A Blender script to procedurally generate 3D spaceships 项目地址: https://gitcode.com/gh_mirrors/sp/SpaceshipGenerator 这是一份 Spaceship …

2026/8/24 12:15:10 阅读更多 →

日新闻

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践

前端内容安全与依赖审计实践 前端安全依赖分层防护。没有任何单一配置能替代输出编码、权限校验和依赖更新。 把不可信内容当作数据 默认使用框架的转义能力;确需渲染 HTML 时,先在服务端或可信的客户端库中进行白名单过滤。避免把用户输入直接赋给 inne…

2026/8/24 1:08:15 阅读更多 →
Windows登录密码存储机制全解析:从哈希算法到安全加固实战

Windows登录密码存储机制全解析:从哈希算法到安全加固实战

1. 项目概述:Windows登录密码的“黑匣子”每次你按下CtrlAltDel,输入密码,然后看到那个熟悉的桌面,这背后发生了一系列复杂而精密的操作。作为一名长期与Windows系统打交道的从业者,我经常被问到:“我的密码…

2026/8/24 1:08:15 阅读更多 →
AI面试系统安全挑战与解决方案

AI面试系统安全挑战与解决方案

1. 项目概述:AI面试系统的安全挑战去年参与某跨国企业AI面试系统部署时,遇到一个典型案例:候选人在视频面试中无意提到竞争对手产品名称,系统竟自动将该信息关联到企业知识库并生成竞品分析报告。这个看似"智能"的功能&…

2026/8/24 1:08:15 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/24 0:06:02 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/24 0:20:20 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/24 0:14:11 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/24 11:20:22 阅读更多 →