本地缓存更新方案探索

文章目录

  • 本地缓存更新方案探索
    • 1 背景
    • 2 方案探索
      • 2.1 初始化
      • 2.2 实时更新
        • 2.2.1 长轮询
          • 2.2.1.1 client
          • 2.2.2.2 server

本地缓存更新方案探索

1 背景

  • 大家在工作中是否遇到过某些业务数据需要频繁使用,但是数据量不大的情况,一般就是几十条甚至几百条这种。
  • 一般的解决方案就是业务维护数据,然后同步redis缓存,C端使用缓存的数据。但是这里不免会出现大key/热key的问题,另外还有缓存穿透、缓存击穿等问题。
  • 那么接下来我们一起探索一下如何解决上述问题吧。

2 方案探索

  • 首先我们评估数据量,发现这类数据一般只有百条左右。那么在技术选型上使用本地缓存无疑是最好的方案。现在应对C端场景基本选型的都是Caffeine。详见:https://blog.csdn.net/for62/article/details/147494533
  • 我们选择了本地缓存一方面可以抗大流量,做到无状态横向扩容。另一方面可以提高服务稳定性降低tp99。
  • 那么接下来我们就要设计缓存一致性的实现方案了,如何将redis中的数据近实时同步到本地缓存,C端只读本地缓存,可以降级读redis。
  • 这里我们参考长轮询实现配置中心的方案:https://mp.weixin.qq.com/s/YjvL0sUTGHxR3GJFqrP8qg。客户端长轮询监听服务端数据变更,感知到数据变更后更新本地缓存数据。设计图如下:
    在这里插入图片描述

2.1 初始化

  • 这里我们先假设刷新本地缓存的方法为:LocalCacheRefresher.refresh();
    public void refresh() {Caffeine<String, Object> cacheInfo = getLocalCacheInstance();String redisCacheKey = getRedisCacheKey();Set<String> keys = redisCache.hKeys(redisCacheKey);for (String key : keys) {String data = redisCache.hGet(redisCacheKey, key);cacheInfo.put(key, data);}}
  • 服务启动时数据加载
@Component
public class LocalCacheInitRunner implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {LocalCacheRefresher.refresh();}}

2.2 实时更新

2.2.1 长轮询
  • 这里我们用长轮询的方案监听源数据的变更来刷新本地缓存。
2.2.1.1 client
@Slf4j
public class LongPollClient {private CloseableHttpClient httpClient;private RequestConfig requestConfig;public ConfigClient() {this.httpClient = HttpClientBuilder.create().build();// httpClient 客户端超时时间要大于长轮询约定的超时时间this.requestConfig = RequestConfig.custom().setSocketTimeout(6000).build();}public void longPolling(String url, String dataId) {String endpoint = url + "?dataId=" + dataId;HttpGet request = new HttpGet(endpoint);CloseableHttpResponse response = httpClient.execute(request);switch (response.getStatusLine().getStatusCode()) {case 200: {BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));StringBuilder result = new StringBuilder();String line;while ((line = rd.readLine()) != null) {result.append(line);}response.close();String configInfo = result.toString();log.info("dataId: [{}] changed, receive configInfo: {}", dataId, configInfo);longPolling(url, dataId);break;}// ② 304 响应码标记配置未变更case 304: {log.info("longPolling dataId: [{}] once finished, configInfo is unchanged, longPolling again", dataId);longPolling(url, dataId);break;}default: {throw new RuntimeException("unExcepted HTTP status code");}}}
}
2.2.2.2 server
@RestController
@Slf4j
@SpringBootApplication
public class LongPollServer {@Dataprivate static class AsyncTask {// 长轮询请求的上下文,包含请求和响应体private AsyncContext asyncContext;// 超时标记private boolean timeout;public AsyncTask(AsyncContext asyncContext, boolean timeout) {this.asyncContext = asyncContext;this.timeout = timeout;}}// guava 提供的多值 Map,一个 key 可以对应多个 valueprivate Multimap<String, AsyncTask> dataIdContext = Multimaps.synchronizedSetMultimap(HashMultimap.create());private ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("longPolling-timeout-checker-%d").build();private ScheduledExecutorService timeoutChecker = new ScheduledThreadPoolExecutor(1, threadFactory);// 配置监听接入点@RequestMapping("/listener")public void addListener(HttpServletRequest request, HttpServletResponse response) {String dataId = request.getParameter("dataId");// 开启异步AsyncContext asyncContext = request.startAsync(request, response);AsyncTask asyncTask = new AsyncTask(asyncContext, true);// 维护 dataId 和异步请求上下文的关联dataIdContext.put(dataId, asyncTask);// 启动定时器,30s 后写入 304 响应timeoutChecker.schedule(() -> {if (asyncTask.isTimeout()) {dataIdContext.remove(dataId, asyncTask);response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);asyncContext.complete();}}, 3000, TimeUnit.MILLISECONDS);}// 配置发布接入点@RequestMapping("/publishConfig")@SneakyThrowspublic String publishConfig(String dataId, String configInfo) {log.info("publish configInfo dataId: [{}], configInfo: {}", dataId, configInfo);Collection<AsyncTask> asyncTasks = dataIdContext.removeAll(dataId);for (AsyncTask asyncTask : asyncTasks) {asyncTask.setTimeout(false);HttpServletResponse response = (HttpServletResponse)asyncTask.getAsyncContext().getResponse();response.setStatus(HttpServletResponse.SC_OK);response.getWriter().println(configInfo);asyncTask.getAsyncContext().complete();}return "success";}public static void main(String[] args) {SpringApplication.run(ConfigServer.class, args);}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/81446.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入理解 requestIdleCallback:浏览器空闲时段的性能优化利器

requestIdleCallback 核心作用 requestIdleCallback 是浏览器提供的 API&#xff0c;用于将非关键任务延迟到浏览器空闲时段执行&#xff0c;避免阻塞用户交互、动画等关键任务&#xff0c;从而提升页面性能体验。 基本语法 const handle window.requestIdleCallback(callb…

51单片机——交通指示灯控制器设计

设计目标 1、设计一交通灯控制&#xff0c;控制东西方向的红、黄、绿灯和南北方向的红、黄、绿灯。 2、可手动控制和自动控制&#xff0c;设置两个输入控制开关。 手动/自动开关&#xff0c;通过P11的按键输入控制 3、手动&#xff1a;设置开关P11&#xff0c;两种情况&#x…

神经网络语言模型(前馈神经网络语言模型)

神经网络语言模型 什么是神经网络&#xff1f;神经网络的基本结构是什么&#xff1f;输入层隐藏层输出层 神经网络为什么能解决问题&#xff1f;通用近似定理为什么需要权重和偏置&#xff1f;为什么需要激活函数&#xff1f;权重是如何确定的&#xff1f;1. 穷举2. 反向传播主…

信息系统项目管理师高级-软考高项案例分析备考指南(2023年案例分析)

个人笔记整理---仅供参考 计算题 案例分析里的计算题就是进度、挣值分析、预测技术。主要考査的知识点有:找关键路径、求总工期、自由时差、总时差、进度压缩资源平滑、挣值计算、预测计算。计算题是一定要拿下的&#xff0c;做计算题要保持头脑清晰&#xff0c;认真读题把PV、…

unordered_map和unordered的介绍和使用

目录 unordered系列关联式容器 unordered_map unordered_map的接口说明 unordered_map的定义方式 unordered_map接口的使用 unordered_map的容量 unordered_map的迭代器 unordered_map的元素访问 unordered_map的查询 unordered_map的修改操作 unordered_multimap u…

设计模式7大原则与UML类图详解

设计模式7大原则与UML类图详解 引言 &#x1f31f; 在软件工程领域&#xff0c;设计模式和UML&#xff08;统一建模语言&#xff09;是提高代码质量、增强系统可维护性的重要工具。设计模式提供了解决软件设计中常见问题的通用方案&#xff0c;而UML则为我们提供了一种可视化的…

计算机视觉与深度学习 | Python实现ARIMA-LSTM时间序列预测(完整源码和数据)

ARIMA-LSTM混合模型 1. 环境准备2. 数据生成(示例数据)3. 数据预处理4. ARIMA建模5. LSTM残差建模6. 混合预测7. 结果可视化完整代码说明1. **数据生成**2. **ARIMA建模**3. **LSTM残差建模**4. **混合预测**5. **性能评估**参数调优建议扩展方向典型输出以下是使用Python实现…

Docker部署单节点Elasticsearch

1.Docker部署单节点ES 1.前置条件 配置内核参数 echo "vm.max_map_count262144" >> /etc/sysctl.conf sysctl -w vm.max_map_count262144准备密码 本文所有涉及密码的配置&#xff0c;均使用通用密码 Zzwl2024。 生产环境&#xff0c;请用密码生成器生成20…

pe文件二进制解析(用c/c++解析一个二进制pe文件)

pe文件二进制解析 c解析pe文件控制台版本 #include<iostream> #include<windows.h> #include<vector>/*RVA&#xff08;相对虚拟地址&#xff09;与FOA&#xff08;文件偏移地址&#xff09;的转换1.得到 的值&#xff1a;内存地址 - ImageBase2.判断是否位…

融智学视域下的系统性认知增强框架——基于文理工三类AI助理赋能HI四阶跃迁路径

融智学视域下的系统性认知增强框架 ——基于文理工三类AI助理赋能HI四阶跃迁路径 一、如何排除50个认知偏差&#xff1a;消除50类偏差的精准矫正系统 1. 技术架构 文科AI&#xff1a; 构建文化语义场&#xff08;Cultural Semantic Field, CSF&#xff09;&#xff0c;通过…

MMDetection环境安装配置

MMDetection 支持在 Linux&#xff0c;Windows 和 macOS 上运行。它需要 Python 3.7 以上&#xff0c;CUDA 9.2 以上和 PyTorch 1.8 及其以上。 MMDetection 至今也一直更新很多个版本了&#xff0c;但是对于最新的pytorch版本仍然不支持&#xff0c;我安装的时候仍然多次遇到m…

如何实现k8s高可用

一、控制平面高可用设计 多主节点部署 • API Server 冗余&#xff1a;部署至少 3 个 Master 节点&#xff0c;每个节点运行独立的 API Server&#xff0c;通过负载均衡器&#xff08;如 Nginx、HAProxy、云厂商 LB&#xff09;对外提供统一入口。 • 选举机制&#xff1a;Sche…

记录心态和工作变化

忙中带闲的工作 其实工作挺忙的, 总是在赶各种功能点. 好巧的是iOS那边因为上架的问题耽搁了一些时间, 从而让Android的进度有了很大的调整空间. 更巧的是后端那边因为对客户端的需求不是很熟悉, 加上Android海外这块的业务他也是第一次接触. 所以需要给他留一些时间把各个环节…

JVM 双亲委派机制

一、从 JDK 到 JVM&#xff1a;Java 运行环境的基石 在 Java 开发领域&#xff0c;JDK&#xff08;Java Development Kit&#xff09;是开发者的核心工具包。它不仅包含了编译 Java 代码的工具&#xff08;如 javac&#xff09;&#xff0c;还内置了 JRE&#xff08;Java Run…

java开发之异常

一 结构 Throwable分为Exception和error Exception分为RuntimeException&#xff08;运行时异常&#xff09;和其他异常 主动抛出运行时异常和非运行时异常的区别 1、throw RuntimeException&#xff08;或运行时异常的子类&#xff09; 编译时不会报错。 2、throw Excepti…

MySQL 中 JOIN 和子查询的区别与使用场景

目录 一、JOIN:表连接1.1 INNER JOIN:内连接1.2 LEFT JOIN:左连接1.3 RIGHT JOIN:右连接1.4 FULL JOIN:全连接二、子查询:嵌套查询2.1 WHERE 子句中的子查询2.2 FROM 子句中的子查询2.3 SELECT 子句中的子查询三、JOIN 和子查询的区别3.1 功能差异3.2 性能差异3.3 使用场…

2025年第三届盘古石杯初赛(智能冰箱,监控部分)

前言 所以去哪里可以取到自己家里的智能家居数据呢&#xff1f;&#xff1f;&#xff1f;&#xff1f; IOT物联网取证 1、分析冰箱&#xff0c;请问智能冰箱的品牌&#xff1f; [答案格式&#xff1a;xiaomi] Panasonic2、请问智能冰箱的型号&#xff1f; [答案格式&#x…

【强化学习】强化学习算法 - 马尔可夫决策过程

文章目录 马尔可夫决策过程 (Markov Decision Process, MDP)1. MDP 原理介绍2. MDP 建模/实现步骤3. MDP 示例&#xff1a;简单网格世界 (Grid World) 马尔可夫决策过程 (Markov Decision Process, MDP) 1. MDP 原理介绍 马尔可夫决策过程 (MDP) 是强化学习 (Reinforcement L…

用户现场不支持路由映射,如何快速将安防监控EasyCVR视频汇聚平台映射到公网?

一、方案背景​ 随着数字化安防与智能交通管理发展&#xff0c;视频监控远程管理需求激增。EasyCVR作为专业视频融合平台&#xff0c;具备多协议接入等核心功能&#xff0c;是智能监控的重要工具。但实际部署中&#xff0c;当EasyCVR处于内网且路由器无法进行端口映射时&#…

MODBUS RTU调试助手使用方法详解

一、软件简介 485调试助手是一款常用的串口通信调试工具&#xff0c;专门用于RS-485总线设备的测试、调试和通信监控。它支持多种串口参数设置&#xff0c;提供数据收发功能&#xff0c;是工业现场调试的必备工具之一。 二、软件安装与启动 1. 系统要求 Windows 7/10/11操作…