.Net Core3.0 WebApi 八:使用Redis做數據緩存


.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下是沒有值的,所以,會走下面的代碼,進行緩存。

 

 得到這樣的響應結果。我們再來調試一次,看看。

 

 這次會從緩存中取值。得到的結果,和上面的結果一樣。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM