【BCVP更新】StackExchange.Redis 的异步开发方式
有哪些習慣
堅持
LESS IS MORE,SIMPLER IS BETTER THAN MORE
你一定會有很大的收獲
各種小問題?
如果你之前用過Redis的話,肯定會使用過StackExchange.Redis,我之前很久就用過,在.netfw的時候,當時并發還比較小,沒有什么問題,后來我就遷移到Blog.Core里了,但是有很多小伙伴,反饋高并發下,使用同步的方法會有問題,比如超時的問題,偶爾還會出現什么內存的問題,一直被很多網友所詬病。
一直說國內有一個組件很不錯,這個大家自己去使用吧,我也不多說什么,但是我想著StackExchange.Redis既然是官方推薦的不會這么菜吧,果然官方給的方案是,用異步的方式寫,會解決超時的問題。
那具體應該怎么寫呢,我還沒有來得及思考,正好這兩天研究微軟的微服務案例eShopOnContainers,我發現他就是用的StackExchange.Redis實現的購物車緩存的子服務邏輯,研究了下,遷移到Blog.Core項目中,當然我這里簡單測試了下,并發下沒有問題,大家還是可以自行測試,當然還是那句話,有問題了我會繼續修改,如果還是不行,那自己就換其他的組件吧。
設計異步方案
這個比較簡單的,設計思路和之前的是一樣的,只不過有一點,連接調制器的注入方式我做了調整(ConnectionMultiplexer),之前用的是雙if夾lock的方式,實現的單例,現在直接使用依賴注入AddSingleton的方式,更專業些,也沒那么幺蛾子:
/// <summary> /// Redis緩存 啟動服務 /// </summary> public static class RedisCacheSetup {public static void AddRedisCacheSetup(this IServiceCollection services){if (services == null) throw new ArgumentNullException(nameof(services));services.AddTransient<IRedisBasketRepository,?RedisBasketRepository>();services.AddSingleton<ConnectionMultiplexer>(sp =>{//獲取連接字符串string redisConfiguration = Appsettings.app(new string[] { "AppSettings", "RedisCachingAOP", "ConnectionString" });var?configuration?=?ConfigurationOptions.Parse(redisConfiguration,?true);configuration.ResolveDns?=?true;return ConnectionMultiplexer.Connect(configuration);});} }這里是Redis依賴注入的擴展方法,需要在Startup里配置上,別忘記了:
services.AddRedisCacheSetup();
然后就是設計接口和實現類了,也很簡單,接口和之前的一樣,只不過都換成了異步:
接口的名稱我為了紀念eShop項目,保持一致了,雖然比較怪,自己酌情修改吧。
然后實現類也很簡單,構造函數直接注入日志和連接調制器實例,不用寫復雜的單例模式了:
public class RedisBasketRepository : IRedisBasketRepository{private readonly ILogger<RedisBasketRepository> _logger;private readonly ConnectionMultiplexer _redis;private readonly IDatabase _database;public RedisBasketRepository(ILogger<RedisBasketRepository> logger, ConnectionMultiplexer redis){_logger = logger;_redis = redis;_database = redis.GetDatabase();}private IServer GetServer(){var endpoint = _redis.GetEndPoints();return _redis.GetServer(endpoint.First());}public async Task Clear(){foreach (var endPoint in _redis.GetEndPoints()){var server = GetServer();foreach (var key in server.Keys()){await _database.KeyDeleteAsync(key);}}}public async Task<bool> Exist(string key){return await _database.KeyExistsAsync(key);}public async Task<string> GetValue(string key){return await _database.StringGetAsync(key);}public async Task Remove(string key){await _database.KeyDeleteAsync(key);}public async Task Set(string key, object value, TimeSpan cacheTime){if (value != null){//序列化,將object值生成RedisValueawait _database.StringSetAsync(key, SerializeHelper.Serialize(value), cacheTime);}}public async Task<TEntity> Get<TEntity>(string key){var value = await _database.StringGetAsync(key);if (value.HasValue){//需要用的反序列化,將Redis存儲的Byte[],進行反序列化return SerializeHelper.Deserialize<TEntity>(value);}else{return default(TEntity);}}}相應的邏輯也很簡單,我詳細基本都能看得懂。
最后就是在BlogRedisCacheAOP.cs中,也要修改下,畢竟改成了異步,還是要注意的:
寫到最后
九月馬上就要到了,新的一年也快結束了,準備好迎接125天的2021年了么!希望新的一年,一起都好起來,大家也要趁著時間好好學學知識,因為我相信到時候肯定會有很多崗位,機會總是會留給有準備的人,相信我,相信你自己。
生活の藝術
總結
以上是生活随笔為你收集整理的【BCVP更新】StackExchange.Redis 的异步开发方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Istio 1.7——进击的追风少年
- 下一篇: 使用 Visual Studio 201