首页 / 缓存 / 基础数据与进程内缓存
基础数据与进程内缓存
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了基础数据与进程内缓存,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3953字,纯文字阅读大概需要6分钟。
内容图文
前言
就目前的大环境来说,说到缓存,可能大部分小伙伴第一反应就会是redis。很多人往往忽视了进程内缓存这一利器。
分布式缓存和进程内缓存的优势和劣势不用多说,大家都略知一二。
我个人还是更倾向于将基础数据,这些变动少的东西,丢到进程内缓存而不是放到redis中,然后定时去更新。
碰到的一些业务情景对这些基础数据的实时要求并不会太高,可以容忍20?30分钟的延迟,即允许这一小段时间内的脏读,而不影响系统的整体结果。针对不同的业务,就要视情况而定了。
目前的做法是基于.NET Core的HostedService
,在程序启动的时候先把数据加载到缓存中,同时有个定时器,每隔一个时间刷新一次。
具体实现
首先是刷新缓存的后台任务
public class RefreshCachingBgTask : IHostedService, IDisposable
{
private readonly ILogger _logger;
private readonly IEasyCachingProviderFactory _providerFactory;
private Timer _timer;
private bool _refreshing;
public RefreshCachingBgTask(ILoggerFactory loggerFactory, IEasyCachingProviderFactory providerFactory)
{
this._logger = loggerFactory.CreateLogger<RefreshCachingBgTask>();
this._providerFactory = providerFactory;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation($"Refresh caching backgroud taks begin ...");
_timer = new Timer(async x =>
{
if (_refreshing)
{
_logger.LogInformation($"Latest manipulation is still working ...");
return;
}
_refreshing = true;
await RefreshAsync();
_refreshing = false;
}, null, TimeSpan.Zero, TimeSpan.FromSeconds(20));
return Task.CompletedTask;
}
private async Task RefreshAsync()
{
_logger.LogInformation($"Refresh caching begin at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
try
{
var cachingProvider = _providerFactory.GetCachingProvider("m1");
// mock query data from database or others
var time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
var random = new Random().NextDouble();
// only once
var dict = new Dictionary<string, string>()
{
{ ConstValue.Time_Cache_Key, time },
{ ConstValue.Random_Cache_Key, random.ToString() }
};
await cachingProvider.SetAllAsync(dict, TimeSpan.FromDays(30));
//// one by one
//await cachingProvider.SetAsync(Time_Cache_Key, time, TimeSpan.FromSeconds(10));
//await cachingProvider.SetAsync(Random_Cache_Key, random.ToString(), TimeSpan.FromSeconds(10));
}
catch (Exception ex)
{
_logger.LogError(ex, $"Refresh caching error ...");
}
_logger.LogInformation($"Refresh caching end at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}");
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation($"Refresh caching backgroud taks end ...");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}
注: 因为是演示,所有这里设置的时间比较短,正常来说,这里是要设置一个超长的缓存时间,以便在获取这个缓存的时候,永远能取到值。
在Startup
中注册EasyCaching和刷新缓存的后台任务
public void ConfigureServices(IServiceCollection services)
{
services.AddEasyCaching(options=>
{
options.UseInMemory("m1");
});
// register backgroud task
services.AddHostedService<RefreshCachingBgTask>();
// others ..
}
然后是控制器中的使用
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly IEasyCachingProviderFactory _providerFactory;
public ValuesController(IEasyCachingProviderFactory providerFactory)
{
this._providerFactory = providerFactory;
}
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
var provider = _providerFactory.GetCachingProvider("m1");
var time = provider.Get<string>(ConstValue.Time_Cache_Key);
// do something based on time ...
var random = provider.Get<string>(ConstValue.Random_Cache_Key);
// do something based on random ...
return new string[] { time.Value, random.Value };
}
}
效果大致如下:
当然,可能有人会提出问题,如果在程序启动的时候,缓存没能正确的写入,比如从数据库读数据的时候引发了异常,或者其他原因导致没能写进去。
这里也给出下面几个解决方案:
- 引入Polly进行重试操作
- 在读的时候,如果失败,重新load一次数据,这里一定要加互斥锁,避免同一时间n个请求同时去load数据
文中示例代码:
内容总结
以上是互联网集市为您收集整理的基础数据与进程内缓存全部内容,希望文章能够帮你解决基础数据与进程内缓存所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。