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

C# --- 本地缓存失效形成缓存击穿触发限流

C# --- 本地缓存失效形成缓存击穿触发限流

  • 问题描述
  • 解决方案
    • 缓存Request Task
    • 加入信号量限制请求数量

问题描述

  • 某一接口前端会偶发返回400.
  • 通过检查日志发现是后端服务调用外部Api时,因为缓存失效导致并发请求数量过多 (QPS接近300), 外部Api返回429导致的.
  • 代码大致如下

private readonly MemoryCache _timeZoneCache = new(new MemoryCacheOptions())private MemeoryCacheEntryOptions EntryOption => new MemeoryCacheEntryOption().SetAbsoluteExpiraton(DataTimeOffset.Utc.Now.AddMinutes(1))public async Task Process()
{var elements = await GetAllElementsAsync();//如果elements数量过多,这里会并发发送大量请求var tasks = elements.Select(element -> GetTimeZoneAsync(element)).ToList();if (tasks.Any()){await Task.WhenAll(tasks)}}private async Task<string> GetTimeZoneAsync(Element element){if (_timeZoneCache.TryGetValue(element.QueryParameter, out string timeZone){return timeZone}//send reuqets to external Apivar reponse = await SendTimeZoneRequestAsync(element)//parse http responsevar result = ParseHttpResponse(response)//set cache_timeZoneCache.Add(element.QueryParameter, result)}
  • 当缓存失效时,如果elements的数量过多(比如300个),那么上面的代码会并发发送300个请求. 导致触发外部服务的限流,返回429

解决方案

缓存Request Task

  • 经过调查发现,被发送出去的大量请求其实很多是重复的请求
  • 那么可以利用C#的Task机制,加入一个新的缓存,这个缓存用来缓存发送出去的Request Task,避免重复发送请求

private readonly MemoryCache _timeZoneCache = new(new MemoryCacheOptions())private MemeoryCacheEntryOptions EntryOption => new MemeoryCacheEntryOption().SetAbsoluteExpiraton(DataTimeOffset.Utc.Now.AddMinutes(1))public async Task Process()
{var elements = await GetAllElementsAsync();//如果elements数量过多,这里会并发发送大量请求var tasks = elements.Select(element -> GetTimeZoneAsync(element)).ToList();if (tasks.Any()){await Task.WhenAll(tasks)}}private async Task<string> GetTimeZoneAsync(Element element){if (_timeZoneCache.TryGetValue(element.QueryParameter, out string timeZone){return timeZone}var response = await GetTimeZoneRequestTaskAsync(element);//parse http responsevar result = ParseHttpResponse(response)//set cache_timeZoneCache.Add(element.QueryParameter, result)}private async Task<HttpResponse> GetTimeZoneRequestTaskAsync(Element element){if (_timeZoneRequestCache.TryGetValue(element.QueryParameter, out string timeZoneRequest){return timeZoneRequest}//do not await herevar request = SendTimeZoneRequestAsync(element)//cache the request_timeZoneRequestCache(element.QueryParameter, request);return request;}

加入信号量限制请求数量

  • 如果都是不同的请求,那么可以使用信号量控制并发发送请求的数量
    参见 https://blog.csdn.net/weixin_38803409/article/details/135353000
http://www.xdnf.cn/news/17135.html

相关文章:

  • eclipse类IDE导入现有工程教程
  • 17day-人工智能-机器学习-分类算法-KNN
  • Spring IOC:Java开发中的依赖魔法
  • 【Qt开发】常用控件(一)
  • HTTP性能优化实战:解决高并发场景下的连接瓶颈与延迟问题
  • 【Spring Boot 快速入门】七、阿里云 OSS 文件上传
  • 家庭财务管理系统|基于java和小程序的家庭财务管理系统设计与实现(源码+数据库+文档)
  • 【含文档+PPT+源码】基于SSM的旅游与自然保护平台开发与实现
  • 3D 材质与纹理:让虚拟模型 “以假乱真” 的核心密码
  • 基于ARM+FPGA光栅数据采集卡设计
  • Datart:开源数据可视化的新星,赋能企业数据分析
  • Flink CDC 介绍
  • Linux 系统重置用户密码指南
  • docker镜像源配置教程,以及解决安装好docker配置镜像源后,出现报错。Job for docker.service failed
  • 【Canvas与文字】生存与生活
  • WPF中引用其他元素各种方法
  • 【Mac】OrbStack:桌面端虚拟机配置与使用
  • 机器学习05——正则化与逻辑回归
  • 数据结构:反转链表(reverse the linked list)
  • 华为OD机考2025C卷 - 开源项目热度榜单 (Java Python JS C++ C )
  • Android Espresso 测试框架深度解析:从入门到精通
  • 如何设计和实施高效的向量化数据检索解决方案
  • python基础:数据解析BeatuifulSoup,不需要考虑前端形式的一种获取元素的方法
  • 量子计算接口开发:Python vs Rust 性能对决
  • 我用一个 Postgres 实现一整套后端架构!
  • 分布式版本控制工具Git
  • javacc学习笔记 01、JavaCC本地安装与测试
  • HCIP笔记1
  • Mac中M系列芯片采用rbenv管理ruby版本
  • pytorch 学习笔记3-利用框架内网络训练糖尿病数据集