当前位置: 首页 > news >正文

后端_本地缓存:零抖动的极速缓冲层

为什么要“本地缓存”?

把“不会变”或“缓慢变”的热数据拉到 JVM,性能直接提升 1~2 个数量级,同时 零网络、零序列化、零 GC 压力

2. 架构全景图

┌-----------------┐        ┌-----------------┐
│  Admin 后台改数据 │ ----► │  写操作触发刷新   -> XXXProducer.send()
└-----------------┘        └-----------------┘│                           │▼ Redis Pub/Sub 广播        ▼
┌-----------------┐        ┌-----------------┐
│  JVM-1 本地缓存  │◄-------┤  XXXRefreshConsumer
└-----------------┘        └-----------------┘▲│----┐│        各实例并行刷新▼----┘
┌-----------------┐
│  JVM-n 本地缓存  │
└-----------------┘

关键约定

  • 只缓存“读多写少”数据(角色、部门、字典)
  • 缓存对象 不可变,杜绝并发修改隐患
  • 刷新动作 幂等(全量 Map 替换,无并发锁)

3. 编码三步曲

3.1 定义接口:把“刷新”暴露出去
// 目的:Consumer 与 Service 解耦,方便单元测试 Mock。
public interface XxxService {/*** 全量刷新本地缓存,幂等*/void initLocalCache();
}
3.2 启动时一次性预热
@Service
public class XxxServiceImpl implements XxxService {//  Map 替换是原子操作/**  volatile 保证可见性,刷新即“指向替换”  */private volatile Map<Long, XXXDto> xxxCache = Collections.emptyMap();@PostConstruct  // ← 项目启动完成即执行public void initLocalCache() {List<XXXDto> list = roleMapper.selectList();   // ① 读库xxxCache = list.stream().collect(Collectors.toMap(XXXDto::getId, Function.identity()));log.info("[initLocalCache] 角色缓存预热完成,size={}", xxxCache.size());}/** 对外查询接口,O(1) */public RoleDO getXxxFromCache(Long xxxId) {return xxxCache.get(xxxId);   // 直接内存命中}
}
3.3 Redis 广播刷新(多实例一致)

为什么需要使用 Redis Pub/Sub 来实时刷新缓存?考虑到高可用,线上会部署多个 JVM 实例,需要通过 Redis 广播到所有实例,实现本地缓存的刷新。

① 消息实体

// AbstractRedisChannelMessage 自行实现或者参考网上开源源码
@Data
public class XxxRefreshMessage extends AbstractRedisChannelMessage {// 空即可,只做信号
}

② 生产者(写操作后发送)

@Component
@RequiredArgsConstructor
public class XxxProducer {private final RedisMQTemplate redisMQTemplate;public void sendRoleRefreshMessage() {redisMQTemplate.send(new XxxRefreshMessage());}
}

在 Service 的 save/update/delete 方法最后一行调用即可。

③ 消费者(所有实例同时刷新)

@Component
@Slf4j
public class XxxRefreshConsumer extends AbstractRedisChannelMessageListener<XxxRefreshMessage> {private final XxxService xxxService;@Overridepublic void onMessage(XxxRefreshMessage msg) {log.info("<<Redis<< 收到Xx刷新信号");xxxService.initLocalCache();   // 全量重新加载}
}

4. 高级增强(按需取用)

能力实现思路收益
局部刷新消息体带上 changedXxxIds,只替换指定条目大表场景减少 GC
延迟刷新发送端使用 RedissonDelayedQueue 聚合 3 s 内的变更削峰填谷
灰度刷新在消息附加 grayFlag,结合 SpringProfile 判断预发环境先验证

5. 常见问题

  • “我改了数据库,但别的实例没生效”
    → 检查 Redis 订阅是否成功 MONITOR 频道。
  • “偶尔出现旧数据”
    → Map 未加 volatile 或返回的是原对象引用(需深拷贝)。
  • “刷新瞬间 CPU 飙高”
    → 数据量过大,改为分页加载 + 增量更新。
  • “项目启动报 NPE”
    @PostConstruct 里调用了其他未初始化完的 Bean,改用 ApplicationRunner

6. 结语

本地缓存是投入产出比最高的性能优化手段,但务必遵守两条铁律:

  1. 只缓存“读多写少”数据
  2. 刷新必须“幂等 + 广播”

照本指南落地,平均接口 RT 从 30 ms 降至 1 ms 以内,数据库连接数下降 60 % 以上——实打实的“老板看得见”的优化。

http://www.dtcms.com/a/419459.html

相关文章:

  • 【笔试强训Day02】1. ⽜⽜的快递(模拟)
  • 建设网站找哪家简洁页面心情网站
  • 广州站有高铁吗域名不变 网站改版
  • 防爬虫逆向日志爆炸,精简追踪不崩浏览器控制台
  • DevExpress WinForms v25.2新功能预览 - 即将升级富文本编辑器控件功能
  • C#知识学习-015(修饰符_4)
  • 有做分期海淘的网站吗苏州建设网站找网络公司
  • 全缓冲和行缓冲
  • 【C++语法】C++11——右值引用
  • 如何给网站做app平台网站建设 厦门
  • 鞍山网站建设工作室北京交易中心网站
  • 现代C++ Lambda表达式:最佳实践、深入理解和资源推荐
  • CUDA 内核中计算全局线程索引的标准方法
  • 刚做网站做多用户还是单用户企业建站的作用是什么
  • CUDA 13.0深度解析:统一ARM生态、UVM增强与GPU共享的革命
  • 佛山外贸网站建设咨询php网站上做微信支付功能
  • 公司网站中新闻中心怎样做优化网页设计图片怎么居中
  • 网站运营经验山东查询网站备案
  • 巴塘网站建设网站开发的论文课题
  • GuavaCache
  • 免费空间如何放网站搜索引擎优化培训免费咨询
  • LeetCode 53 最大子数字和(动态规划)
  • 如何为100Tops机器人“退烧”?世强芯片热管理方案,释放100%算力!
  • 【NodeJS】使用 NVM 安装 Node.js 22 并配置国内镜像加速
  • 边缘计算与AI:移动端设计软件的实时性能突破
  • 芜湖有没有网站建设公司吗wordpress邮件分析插件
  • 网上做外贸都有哪些网站组织架构及营销网络怎么填写
  • 网站建设费开票税收代码模板网站好还是自助建站好
  • 苏州网站建设数据网络wordpress添加广告插件
  • 江西哪里可以做企业网站h5案例网站