.Net Core3.0 WebApi 目錄
Redis介紹
之前的隨筆中,也有關於Redis的介紹。這里就簡單介紹一下。
簡單來說 redis 就是一個數據庫,不過與傳統數據庫不同的是 redis 的數據是存在內存中的,所以讀寫速度非常快,因此 redis 被廣泛應用於緩存方向。另外,redis 也經常用來做分布式鎖。redis 提供了多種數據類型來支持不同的業務場景。除此之外,redis 支持事務 、持久化、LUA腳本、LRU驅動事件、多種集群方案。
為什么要用 redis?/為什么要用緩存?
主要從“高性能”和“高並發”這兩點來看待這個問題。
高性能:
假如用戶第一次訪問數據庫中的某些數據。這個過程會比較慢,因為是從硬盤上讀取的。將該用戶訪問的數據存在緩存中,這樣下一次再訪問這些數據的時候就可以直接從緩存中獲取了。操作緩存就是直接操作內存,所以速度相當快。如果數據庫中的對應數據改變的之后,同步改變緩存中相應的數據即可!
高並發:
直接操作緩存能夠承受的請求是遠遠大於直接訪問數據庫的,所以我們可以考慮把數據庫中的部分數據轉移到緩存中去,這樣用戶的一部分請求會直接到緩存這里而不用經過數據庫。
什么數據需要存Redis
歡迎補充:
1.任何可丟失數據
2.不經常變動的數據
Redis安裝配置
安裝:www.baidu.com,網上一大堆。這里主要配置一下redis連接字符串,在appsetting.json添加Redis配置。
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"ConnectionString": "Data Source=127.0.0.1;Initial Catalog=db;User ID=uid;Password=123456;Pooling=True;Max Pool Size=512;Connect Timeout=500;",
"JwtSetting": {
"Issuer": "jwtIssuer", //頒發者
"Audience": "jwtAudience", //可以給哪些客戶端使用
"SecretKey": "chuangqianmingyueguang" //加密的Key
},
"RedisCaching": { "Enabled": true, "ConnectionString": "127.0.0.1:6379" }
}
}
自定義序列化幫助類
Infrastructure的Helpers文件夾中,添加SerializeHelper.cs 對象序列化操作
namespace WebApi.Core.Infrastructure.Helpers { public class SerializeHelper { /// <summary> /// 序列化 /// </summary> /// <param name="item"></param> /// <returns></returns> public static byte[] Serialize(object item) { var jsonString = JsonConvert.SerializeObject(item); return Encoding.UTF8.GetBytes(jsonString); } /// <summary> /// 反序列化 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="value"></param> /// <returns></returns> public static TEntity Deserialize<TEntity>(byte[] value) { if (value == null) { return default(TEntity); } var jsonString = Encoding.UTF8.GetString(value); return JsonConvert.DeserializeObject<TEntity>(jsonString); } } }
定義Redis接口和實現類
Infrastructure類庫中,新建Redis文件夾,新建IRedisCacheManager接口和RedisCacheManager類,並引用Nuget包StackExchange.Redis
namespace WebApi.Core.Infrastructure.Redis { public class RedisCacheManager : IRedisCacheManager { private readonly string redisConnenctionString; public volatile ConnectionMultiplexer redisConnection; private readonly object redisConnectionLock = new object(); public RedisCacheManager() { string redisConfiguration = ConfigHelper.GetSectionValue("ConnectionStrings:RedisCaching:ConnectionString");//獲取連接字符串 if (string.IsNullOrWhiteSpace(redisConfiguration)) { throw new ArgumentException("redis config is empty", nameof(redisConfiguration)); } this.redisConnenctionString = redisConfiguration; this.redisConnection = GetRedisConnection(); } /// <summary> /// 核心代碼,獲取連接實例 /// 通過雙if 夾lock的方式,實現單例模式 /// </summary> /// <returns></returns> private ConnectionMultiplexer GetRedisConnection() { //如果已經連接實例,直接返回 if (this.redisConnection != null && this.redisConnection.IsConnected) { return this.redisConnection; } //加鎖,防止異步編程中,出現單例無效的問題 lock (redisConnectionLock) { if (this.redisConnection != null) { //釋放redis連接 this.redisConnection.Dispose(); } try { this.redisConnection = ConnectionMultiplexer.Connect(redisConnenctionString); } catch (Exception) { throw new Exception("Redis服務未啟用,請開啟該服務"); } } return this.redisConnection; } public void Clear() { foreach (var endPoint in this.GetRedisConnection().GetEndPoints()) { var server = this.GetRedisConnection().GetServer(endPoint); foreach (var key in server.Keys()) { redisConnection.GetDatabase().KeyDelete(key); } } } public bool Get(string key) { return redisConnection.GetDatabase().KeyExists(key); } public string GetValue(string key) { return redisConnection.GetDatabase().StringGet(key); } public TEntity Get<TEntity>(string key) { var value = redisConnection.GetDatabase().StringGet(key); if (value.HasValue) { //需要用的反序列化,將Redis存儲的Byte[],進行反序列化 return SerializeHelper.Deserialize<TEntity>(value); } else { return default(TEntity); } } public void Remove(string key) { redisConnection.GetDatabase().KeyDelete(key); } public void Set(string key, object value, TimeSpan cacheTime) { if (value != null) { //序列化,將object值生成RedisValue redisConnection.GetDatabase().StringSet(key, SerializeHelper.Serialize(value), cacheTime); } } public bool SetValue(string key, byte[] value) { return redisConnection.GetDatabase().StringSet(key, value, TimeSpan.FromSeconds(120)); } } }
將Redis服務注入到容器中
將redis接口和類 在ConfigureServices中 進行注入:
//注冊Redis services.AddSingleton<IRedisCacheManager, RedisCacheManager>();
控制器中調用
通過構造函數把IRedisCacheManager和UserRepository注入進去,然后新加一個接口。
/// <summary> /// 測試Redis /// </summary> /// <returns></returns> [HttpGet] public async Task<IActionResult> Redis(int id) { var key = $"Redis{id}"; UserNew user = new UserNew(); if (_redisCacheManager.Get<object>(key) != null) { user = _redisCacheManager.Get<UserNew>(key); } else { user = new UserNew { UserId = id, UserName = "bingle", Age = 18 }; _redisCacheManager.Set(key, user, TimeSpan.FromHours(2));//緩存2小時 } return Ok(user); }
運行項目,測試接口。測試接口之前,需要先把Redis服務器開啟。
Redis緩存NoSQL 詳細的介紹了Redis,docker下安裝Redis 以及docker下安裝Redis
第一次執行,這個key下是沒有值的,所以,會走下面的代碼,進行緩存。
得到這樣的響應結果。我們再來調試一次,看看。
這次會從緩存中取值。得到的結果,和上面的結果一樣。