.Net Core 缓存方式(二)分布式缓存
官方文档
分布式缓存是由多个应用服务器共享的缓存,通常作为外部服务在访问它的应用服务器上维护。 分布式缓存可以提高 ASP.NET Core 应用程序的性能和可伸缩性,尤其是在应用程序由云服务或服务器场托管时。
与其他缓存方案相比,分布式缓存具有多项优势,其中缓存的数据存储在单个应用服务器上。
当分布式缓存数据时,数据将:
(一致性) 跨多个服务器的请求。
置服务器重启和应用部署。
不使用本地内存。
IDistributedCache
IDistributedCache接口提供以下方法:
GetGetAsync:接受字符串键,并检索缓存项作为 byte[] 数组(如果在缓存中找到)。
SetSetAsync:使用字符串键将项 (作为 byte[] 数组) 添加到缓存中。
Refresh, RefreshAsync :基于其键刷新缓存中的项,如果有任何) ,则重置其可调过期超时 (。
RemoveRemoveAsync:根据缓存项的字符串键删除缓存项。
分布式内存缓存使用方式
Startup.ConfigureServices :
services.AddDistributedMemoryCache();
public class IndexModel : PageModel
{
private readonly IDistributedCache _cache;
public IndexModel(IDistributedCache cache)
{
_cache = cache;
}
public string CachedTimeUTC { get; set; }
public async Task OnGetAsync()
{
CachedTimeUTC = "Cached Time Expired";
var encodedCachedTimeUTC = await _cache.GetAsync("cachedTimeUTC");
if (encodedCachedTimeUTC != null)
{
CachedTimeUTC = Encoding.UTF8.GetString(encodedCachedTimeUTC);
}
}
public async Task<IActionResult> OnPostResetCachedTime()
{
var currentTimeUTC = DateTime.UtcNow.ToString();
byte[] encodedCurrentTimeUTC = Encoding.UTF8.GetBytes(currentTimeUTC);
var options = new DistributedCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(20));
await _cache.SetAsync("cachedTimeUTC", encodedCurrentTimeUTC, options);
return RedirectToPage();
}
}
实现方式
Microsoft.Extensions.Caching.Abstractions/src/IDistributedCache.cs
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.Extensions.Caching.Distributed
{
/// <summary>
/// Represents a distributed cache of serialized values.
/// </summary>
public interface IDistributedCache
{
/// <summary>
/// Gets a value with the given key.
/// </summary>
/// <param name="key">A string identifying the requested value.</param>
/// <returns>The located value or null.</returns>
byte[] Get(string key);
/// <summary>
/// Gets a value with the given key.
/// </summary>
/// <param name="key">A string identifying the requested value.</param>
/// <param name="token">Optional. The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the located value or null.</returns>
Task<byte[]> GetAsync(string key, CancellationToken token = default(CancellationToken));
/// <summary>
/// Sets a value with the given key.
/// </summary>
/// <param name="key">A string identifying the requested value.</param>
/// <param name="value">The value to set in the cache.</param>
/// <param name="options">The cache options for the value.</param>
void Set(string key, byte[] value, DistributedCacheEntryOptions options);
/// <summary>
/// Sets the value with the given key.
/// </summary>
/// <param name="key">A string identifying the requested value.</param>
/// <param name="value">The value to set in the cache.</param>
/// <param name="options">The cache options for the value.</param>
/// <param name="token">Optional. The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default(CancellationToken));
/// <summary>
/// Refreshes a value in the cache based on its key, resetting its sliding expiration timeout (if any).
/// </summary>
/// <param name="key">A string identifying the requested calue.</param>
void Refresh(string key);
/// <summary>
/// Refreshes a value in the cache based on its key, resetting its sliding expiration timeout (if any).
/// </summary>
/// <param name="key">A string identifying the requested value.</param>
/// <param name="token">Optional. The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task RefreshAsync(string key, CancellationToken token = default(CancellationToken));
/// <summary>
/// Removes the value with the given key.
/// </summary>
/// <param name="key">A string identifying the requested value.</param>
void Remove(string key);
/// <summary>
/// Removes the value with the given key.
/// </summary>
/// <param name="key">A string identifying the requested value.</param>
/// <param name="token">Optional. The <see cref="CancellationToken"/> used to propagate notifications that the operation should be canceled.</param>
/// <returns>The <see cref="Task"/> that represents the asynchronous operation.</returns>
Task RemoveAsync(string key, CancellationToken token = default(CancellationToken));
}
}
AddDistributedMemoryCache 的实现
- Microsoft.Extensions.Caching.Memory/src/MemoryCacheServiceCollectionExtensions.cs 依赖注入 IDistributedCache与 MemoryDistributedCache实现
public static IServiceCollection AddDistributedMemoryCache(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddOptions();
services.TryAdd(ServiceDescriptor.Singleton<IDistributedCache, MemoryDistributedCache>());
return services;
}
- MemoryDistributedCache : IDistributedCache
Microsoft.Extensions.Caching.Memory/src/MemoryDistributedCache.cs
namespace Microsoft.Extensions.Caching.Distributed
{
public class MemoryDistributedCache : IDistributedCache
{
private readonly IMemoryCache _memCache;
public MemoryDistributedCache(IOptions<MemoryDistributedCacheOptions> optionsAccessor)
: this(optionsAccessor, NullLoggerFactory.Instance) { }
public MemoryDistributedCache(IOptions<MemoryDistributedCacheOptions> optionsAccessor, ILoggerFactory loggerFactory)
{
if (optionsAccessor == null)
{
throw new ArgumentNullException(nameof(optionsAccessor));
}
if (loggerFactory == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}
_memCache = new MemoryCache(optionsAccessor.Value, loggerFactory);
}
public byte[] Get(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return (byte[])_memCache.Get(key);
}
public Task<byte[]> GetAsync(string key, CancellationToken token = default(CancellationToken))
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
return Task.FromResult(Get(key));
}
public void Set(string key, byte[] value, DistributedCacheEntryOptions options)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
var memoryCacheEntryOptions = new MemoryCacheEntryOptions();
memoryCacheEntryOptions.AbsoluteExpiration = options.AbsoluteExpiration;
memoryCacheEntryOptions.AbsoluteExpirationRelativeToNow = options.AbsoluteExpirationRelativeToNow;
memoryCacheEntryOptions.SlidingExpiration = options.SlidingExpiration;
memoryCacheEntryOptions.Size = value.Length;
_memCache.Set(key, value, memoryCacheEntryOptions);
}
public Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default(CancellationToken))
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
}
Set(key, value, options);
return Task.CompletedTask;
}
public void Refresh(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
_memCache.TryGetValue(key, out object value);
}
public Task RefreshAsync(string key, CancellationToken token = default(CancellationToken))
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
Refresh(key);
return Task.CompletedTask;
}
public void Remove(string key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
_memCache.Remove(key);
}
public Task RemoveAsync(string key, CancellationToken token = default(CancellationToken))
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}
Remove(key);
return Task.CompletedTask;
}
}
}