目录html
缓存是分布式系统中的重要组件,主要解决高并发,大数据场景下,热点数据访问的性能问题。提供高性能的数据快速访问。git
CDN
:存放HTML、CSS、JS等静态资源;反向代理
:动静分离,只缓存用户请求的静态资源;分布式缓存
:缓存数据库中的热点数据;本地缓存
:缓存应用字典等经常使用数据。必定不存在的key,采用布隆过滤器,创建一个大的Bitmap中,查询时经过该bitmap过滤。github
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它其实是一个很长的二进制向量和一系列随机映射函数。布隆过滤器能够用于检索一> 个元素是否在一个集合中。它的优势是空间效率和查询时间都远远超过通常的算法,缺点是有必定的误识别率和删除困难
若是想要判断一个元素是否是在一个集合里,通常想到的是将全部元素保存起来,而后经过比较肯定。链表,树等等数据结构都是这种思路. > 可是随着集合中元素的增长,咱们须要的存储空间愈来愈大,检索速度也愈来愈慢(O(n),O(logn))。不过世界上还有一种叫做散列表(又叫哈> 希表,Hash table)的数据结构。它能够经过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,咱们只要看看这个点是否是1就能够知道集合中有没有它了。这就是布隆过滤器的基本思想。redis
数据不一致的几种状况:算法
目前比较经常使用的数据缓存策略的是Cache Aside Pattern,更新缓存是先把数据存到数据库中,成功后,再让缓存失效。
这种策略下不一致产生的缘由只有更新数据库成功,可是删除缓存失败。
解决方案:shell
ASP.NET Core 支持多种不一样的缓存。包括内存缓存,分布式缓存(Redis 和 SQL Server)。Github 开源地址 Libraries for in-memory caching and distributed caching.数据库
IMemoryCache是把数据存储在Web服务器的内存中。api
在 ConfigureServices 中调用 AddMemoryCache 经过依赖关系注入引用服务。缓存
public void ConfigureServices(IServiceCollection services) { services.AddMemoryCache(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
在控制器类中用构造器注入的方式建立 IMemoryCache 的对象。服务器
using Microsoft.Extensions.Caching.Memory; public class ValuesController : ControllerBase { private IMemoryCache _cache; public ValuesController(IMemoryCache cache) { _cache = cache; } }
建立缓存
Set()
DateTime cacheEntry1 = DateTime.Now; var cacheEntryOptions = new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromSeconds(3)); _cache.Set("cache1", cacheEntry1, cacheEntryOptions);
GetOrCreate()
GetOrCreateAsync
var cacheEntry = _cache.GetOrCreate("cache1", entry => { entry.SetAbsoluteExpiration(TimeSpan.FromSeconds(3)); return DateTime.Now; });
获取缓存
Get()
var cacheEntry = this._cache.Get<DateTime?>("cache1");
TryGetValue()
DateTime cacheEntry; if (!_cache.TryGetValue("cache1", out cacheEntry)) { // Key not in cache, so get data. cacheEntry = DateTime.Now; var cacheEntryOptions = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromSeconds(3)); _cache.Set("cache1", cacheEntry, cacheEntryOptions); }
删除缓存
Remove()
_cache.Remove("cache1");
其余知识点
ICacheEntry成员:Key
缓存keyValue
缓存值AbsoluteExpiration
绝对过时时间,为null则条件无效AbsoluteExpirationRelativeToNow
相对当前时间的绝对过时时间(使用TimeSpan),为null条件无效SlidingExpiration
滑动过时时间ExpirationTokens
提供用来自定义缓存过时PostEvictionCallbacks
缓存失效回调Priority
缓存项优先级(在缓存满载的时候绝对清除的顺序)Size
表明缓存数据的大小,在内存缓存中通常为nullConfigureServices 方法里面添加服务 AddDistributedRedisCache
public void ConfigureServices(IServiceCollection services) { services.AddDistributedRedisCache(options => { options.Configuration = "localhost"; options.InstanceName = "Instance1"; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
Get
,GetAsync
采用字符串键并以byte[]形式检索缓存项(若是在缓存中找到)Set
,SetAsync
使用字符串键向缓存添加项byte[]形式Refresh
,RefreshAsync
根据键刷新缓存中的项,并重置其可调过时超时值(若是有)Remove
,RemoveAsync
根据键删除缓存项var now = DateTime.Now; var cacheValue = System.Text.Encoding.UTF8.GetBytes(now.ToString()); var options = new DistributedCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromSeconds(3)); _cache.Set("cache1", cacheValue, options); _cache.Refresh("cache1"); var value = _cache.Get("cache1"); var nowString = System.Text.Encoding.UTF8.GetString(value); _cache.Remove("cache1");
因为自带的 RedisCache 继承 IDistributedCache 接口并无提供 Redis的一些高级特性好比Hash, List, Set等。
基于Stackexchange.Redis封装一个简单RedisHelper类:
RedisHelper 类
public class RedisHelper { private readonly RedisOptions _options; private readonly Lazy<ConnectionMultiplexer> _connectionMultiplexer; public RedisHelper(IOptions<RedisOptions> optionsAccessor) { if (optionsAccessor == null) { throw new ArgumentNullException(nameof(optionsAccessor)); } _options = optionsAccessor.Value; _connectionMultiplexer = new Lazy<ConnectionMultiplexer>(CreateConnectionMultiplexer); } public IDatabase GetDatabase() { return _connectionMultiplexer.Value.GetDatabase(); } private ConnectionMultiplexer CreateConnectionMultiplexer() { if (_options.ConfigurationOptions != null) { return ConnectionMultiplexer.Connect(_options.ConfigurationOptions); } else { return ConnectionMultiplexer.Connect(_options.Configuration); } } }
RedisOptions 配置类
public class RedisOptions : IOptions<RedisOptions> { /// <summary> /// The configuration used to connect to Redis. /// </summary> public string Configuration { get; set; } /// <summary> /// The configuration used to connect to Redis. /// This is preferred over Configuration. /// </summary> public ConfigurationOptions ConfigurationOptions { get; set; } /// <summary> /// The Redis instance name. /// </summary> public string InstanceName { get; set; } RedisOptions IOptions<RedisOptions>.Value { get { return this; } } }
RedisHelperServiceCollectionExtensions 扩展类
public static class RedisHelperServiceCollectionExtensions { public static IServiceCollection AddRedisHelper(this IServiceCollection services, Action<RedisOptions> setupAction) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (setupAction == null) { throw new ArgumentNullException(nameof(setupAction)); } services.AddOptions(); services.Configure(setupAction); services.AddSingleton<RedisHelper>(); return services; } }
在 ConfigureServices 里面添加服务引用
public void ConfigureServices(IServiceCollection services) { var redisOptions = Configuration.GetSection("RedisOptions").Get<RedisOptions>(); services.AddRedisHelper(options => { options.Configuration = redisOptions.Configuration; options.InstanceName = redisOptions.InstanceName; }); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); }
在 Controller 里面使用
public class ValuesController : ControllerBase { private readonly RedisHelper _redisHelper; public ValuesController(RedisHelper redisHelper) { _redisHelper = redisHelper; } // GET api/values [HttpGet] public ActionResult<IEnumerable<string>> Get() { _redisHelper.GetDatabase().StringSet("test_key_2", "test_value_2", TimeSpan.FromSeconds(60)); return new string[] { "value1", "value2" }; } }
网上一些开源的Redis扩展: