C# 使用 redis 作為緩存服務(wù)器

源代碼:https://git.oschina.net/zhaord/CacheDemo.git(dev_redis 分支)
前提:已安裝并運(yùn)行redis服務(wù)器


redis 緩存

通過 《C# 緩存》 可以了解到,緩存其實(shí),就是一系列的 key-value,而 redis 是典型的key-value數(shù)據(jù)庫(kù)之一,那么,我們是不是可以借助 redis來(lái)實(shí)現(xiàn)緩存呢?答案是肯定的!


實(shí)現(xiàn)

代碼是在 《C# 緩存》基礎(chǔ)上修改的,代碼分支為:dev_redis。
《C# 緩存》中,是用C#自帶的類庫(kù)實(shí)現(xiàn)的緩存,那么,我們只要繼承自 cachebase,并重寫相關(guān)方法,就可以實(shí)現(xiàn)使用redis作為緩存服務(wù)器,在實(shí)現(xiàn)之前,我們先約定key值為 “n:name,c:key”來(lái)作為redis的key值,啟用name為自定義的,因?yàn)榭赡懿煌姆謱訒?huì)使用不同的name名稱,key就是需要保存的緩存項(xiàng)的key,代碼如下


        protected virtual string GetLocalizedKey(string key)
        {
            return "n:" + "RandomRedis" + ",c:" + key;
        }

redis中保存的value值,格式是 "類名,程序集名 | 序列化后的值" 作為value的保存格式,具體實(shí)現(xiàn)代碼如下


        protected virtual string Serialize(object value, Type type)
        {
            var serialized = JsonConvert.SerializeObject(value);
            
            return string.Format(
                "{0}{1}{2}",
                type.AssemblyQualifiedName,
                TypeSeperator,
                serialized
                );

        }
        

既然,我們針對(duì)保存的值進(jìn)行了格式約定,那么久需要解析約定,解析代碼如下


        protected virtual object Deserialize(RedisValue objbyte)
        {
            var serializedObj = objbyte.ToString();

            var typeSeperatorIndex = serializedObj.IndexOf(TypeSeperator);
            var type = Type.GetType(serializedObj.Substring(0, typeSeperatorIndex));
            var serialized = serializedObj.Substring(typeSeperatorIndex + 1);
            
            return JsonConvert.DeserializeObject(serialized, type);
        }

通過以上兩個(gè)函數(shù),我們可以顯示取值和設(shè)置值得函數(shù),如下


        public override object GetOrDefault(string key)
        {

            var objbyte = this._database.StringGet(this.GetLocalizedKey(key));
            return objbyte.HasValue ? this.Deserialize(objbyte) : null;

        }

        public override void Set(string key, object value, TimeSpan? slidingExpireTime = null, TimeSpan? absoluteExpireTime = null)
        {
            if (value == null)
            {
                throw new Exception("不可以插入null到緩存!");
            }

            var type = value.GetType();
            
            // 以string類型保存緩存值
            this._database.StringSet(
                this.GetLocalizedKey(key),
                this.Serialize(value, type),
                absoluteExpireTime ?? slidingExpireTime ?? TimeSpan.FromSeconds(60)
                );
            
        }

那么整個(gè)緩存實(shí)現(xiàn)的代碼如下

    public class RedisCache
        :CacheBase
    {
        private readonly IDatabase _database;

        private ConnectionMultiplexer redisClient = ConnectionMultiplexer.Connect("localhost");

        private const char TypeSeperator = '|';


        public RedisCache()
        {
            this._database = this.redisClient.GetDatabase();

        }
        
        public override object GetOrDefault(string key)
        {

            var objbyte = this._database.StringGet(this.GetLocalizedKey(key));
            return objbyte.HasValue ? this.Deserialize(objbyte) : null;

        }

        public override void Set(string key, object value, TimeSpan? slidingExpireTime = null, TimeSpan? absoluteExpireTime = null)
        {
            if (value == null)
            {
                throw new Exception("不可以插入null到緩存!");
            }

            var type = value.GetType();
            
            // 以string類型保存緩存值
            this._database.StringSet(
                this.GetLocalizedKey(key),
                this.Serialize(value, type),
                absoluteExpireTime ?? slidingExpireTime ?? TimeSpan.FromSeconds(60)
                );
            
        }

        public override void Remove(string key)
        {
            this._database.KeyDelete(this.GetLocalizedKey(key));

        }

        public override void Clear()
        {
            this._database.KeyDeleteWithPrefix(this.GetLocalizedKey("*"));

        }

        protected virtual object Deserialize(RedisValue objbyte)
        {
            var serializedObj = objbyte.ToString();

            var typeSeperatorIndex = serializedObj.IndexOf(TypeSeperator);
            var type = Type.GetType(serializedObj.Substring(0, typeSeperatorIndex));
            var serialized = serializedObj.Substring(typeSeperatorIndex + 1);
            
            return JsonConvert.DeserializeObject(serialized, type);
        }


        protected virtual string Serialize(object value, Type type)
        {
            var serialized = JsonConvert.SerializeObject(value);
            
            return string.Format(
                "{0}{1}{2}",
                type.AssemblyQualifiedName,
                TypeSeperator,
                serialized
                );

        }
        
        protected virtual string GetLocalizedKey(string key)
        {
            return "n:" + "RandomRedis" + ",c:" + key;
        }

    }

代碼大部分實(shí)現(xiàn),是和democache類想通,只不過,democache通過封裝memory實(shí)現(xiàn)緩存保存,而 類 RedisCache 封裝 redis客戶端,作為緩存 容器!


使用緩存

《C# 緩存》 已經(jīng)寫好了測(cè)試過程,我們只需要將代碼ICache cache = new DemoCache(); 替換為 ICache cache = new RedisCache();即可使用新的緩存實(shí)現(xiàn)方式。


運(yùn)行結(jié)果

具體的運(yùn)行結(jié)果如下

圖片.png

《C# 緩存》 中運(yùn)行期望一直,說(shuō)明我們已經(jīng)成功使用redis來(lái)作為緩存容器了!


總結(jié)

通過上述描述,我們就可以借助redis來(lái)實(shí)現(xiàn)緩存容器了。
本片文章和《C# 緩存》中使用了大量ABP的代碼。


qq:1260825783
轉(zhuǎn)載備注:http://www.itdecent.cn/p/f5f2a5e7ec1c

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容