zoukankan      html  css  js  c++  java
  • 在.Net下使用redis基于StackExchange.Redis

    研究了下redis在.net下的使用,因为以前在java上用redis用的是jedis操作,在.net不是很熟悉,在网站上也看了一部分的.net下redis的使用,大部分都是ServiceStack.Redis听说ServiceStack.Redis4.0版本都是收费的,这个我不是很清楚,但是我确实有项目再用ServiceStack.Redis。

    这里就不讨论ServiceStack.Redis的使用今天带来的是StackExchange.Redis的封装版。

    代码参考

    DDD领域驱动之干货(三)完结篇!

    下面是干货

    RedisCaching里面放着的是Redis的基本5个方法分别如下图所示:

    RedisCommon里面放着的是redis的帮助类和初始化类如下图所示:

    现在举了例子就以DoRedisStringCache为例:

    实现了接口IRedisCaching,当然这里这个接口是标识接口意思就是用来约束的。

    StackExchange.Redis是初始化是单列模式,内部有一套自己的方法,这里我就放一下代码

     

    这里面还有6个事件如下图:

    代码贴出来:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using StackExchange.Redis;
    using KuRuMi.Mio.DoMain.Infrastructure.Logger;
    
    namespace KuRuMi.Mio.DoMain.RedisCache.RedisCommon
    {
        public class RedisManager
        {
            private static string Constring = RedisConfig.Config();
            private static readonly object locker = new object();
            private static ConnectionMultiplexer instance;
            private static readonly Dictionary<string, ConnectionMultiplexer> Concache = new Dictionary<string, ConnectionMultiplexer>();
    
            /// <summary>
            /// 单例模式获取redis连接实例
            /// </summary>
            public static ConnectionMultiplexer Instance
            {
                get
                {
                    if (instance == null)
                    {
                        lock (locker)
                        {
                            if (instance == null)
                                instance = GetManager();
                        }
                    }
                    return instance;
                }
            }
    
            /// <summary>
            /// 从缓存中获取
            /// </summary>
            /// <param name="constr"></param>
            /// <returns></returns>
            public static ConnectionMultiplexer GetConForMap(string constr) {
                if (!Concache.ContainsKey(constr))
                    Concache[constr] = GetManager(constr);
                return Concache[constr];
            }
    
            private static ConnectionMultiplexer GetManager(string constr = null)
            {
                constr = constr ?? Constring;
                var connect = ConnectionMultiplexer.Connect(constr);
    
                #region 注册事件
                connect.ConnectionFailed += MuxerConnectionFailed;
                connect.ConnectionRestored += MuxerConnectionRestored;
                connect.ErrorMessage += MuxerErrorMessage;
                connect.ConfigurationChanged += MuxerConfigurationChanged;
                connect.HashSlotMoved += MuxerHashSlotMoved;
                connect.InternalError += MuxerInternalError;
                #endregion
    
                return connect;
            }
            #region Redis事件
            /// <summary>
            /// 内部异常
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
            {
                Units.Log("内部异常:" + e.Exception.Message);
            }
    
            /// <summary>
            /// 集群更改
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
            {
                Units.Log("新集群:" + e.NewEndPoint + "旧集群:" + e.OldEndPoint);
            }
    
            /// <summary>
            /// 配置更改事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
            {
                Units.Log("配置更改:" + e.EndPoint);
            }
    
            /// <summary>
            /// 错误事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
            {
                Units.Log("异常信息:" + e.Message);
            }
    
            /// <summary>
            /// 重连错误事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
            {
                Units.Log("重连错误" + e.EndPoint);
            }
    
            /// <summary>
            /// 连接失败事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
            {
                Units.Log("连接异常" + e.EndPoint + ",类型为" + e.FailureType + (e.Exception == null ? "" : (",异常信息是" + e.Exception.Message)));
            }
            #endregion
        }
    }

    下面是redis的config:

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace KuRuMi.Mio.DoMain.RedisCache.RedisCommon
    {
        public sealed class RedisConfig
        {
            public static readonly string config = ConfigurationManager.AppSettings["RedisConfig"];
            public static readonly string redisKey = ConfigurationManager.AppSettings["RedisKey"] ?? "";
            public static string Config() {
                return config;
            }
            public static string Key() {
                return redisKey;
            }
        }
    }

    下面是redis的helper:

    using Newtonsoft.Json;
    using StackExchange.Redis;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace KuRuMi.Mio.DoMain.RedisCache.RedisCommon
    {
        public class RedisBase
        {
            private static ConnectionMultiplexer db = null;
            private static string key = string.Empty;
    
            private int DbNumber { get; }
            public RedisBase(int dbnum = 0) : this(dbnum, null)
            {
    
            }
    
            public RedisBase(int dbnum, string connectionString)
            {
                DbNumber = dbnum;
                db = string.IsNullOrWhiteSpace(connectionString) ? RedisManager.Instance : RedisManager.GetConForMap(connectionString);
            }
    
            #region 辅助方法
            /// <summary>
            /// 添加名称
            /// </summary>
            /// <param name="old"></param>
            /// <returns></returns>
            public string AddKey(string old)
            {
                var fixkey = key ?? RedisConfig.Key();
                return fixkey + old;
            }
    
            /// <summary>
            /// 执行保存
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="func"></param>
            /// <returns></returns>
            public T DoSave<T>(Func<IDatabase, T> func)
            {
                return func(db.GetDatabase(DbNumber));
            }
            public string ConvertJson<T>(T val)
            {
                return val is string ? val.ToString() : JsonConvert.SerializeObject(val);
            }
    
            public T ConvertObj<T>(RedisValue val)
            {
                return JsonConvert.DeserializeObject<T>(val);
            }
    
            public List<T> ConvertList<T>(RedisValue[] val)
            {
                List<T> result = new List<T>();
                foreach (var item in val)
                {
                    var model = ConvertObj<T>(item);
                    result.Add(model);
                }
                return result;
            }
    
            public RedisKey[] ConvertRedisKeys(List<string> val)
            {
                return val.Select(k => (RedisKey)k).ToArray();
            }
            #endregion
        }
    }

    下面是我的string封装方法:

    using KuRuMi.Mio.DoMain.RedisCache.RedisCommon;
    using StackExchange.Redis;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace KuRuMi.Mio.DoMain.RedisCache.RedisCaching
    {
        /// <summary>
        /// 表示string的操作
        /// </summary>
        public class DoRedisStringCache : IRedisCaching
        {
            private RedisBase redis = null;
            public DoRedisStringCache()
            {
                redis = new RedisBase();
            }
    
            #region 同步执行
            /// <summary>
            /// 单个保存
            /// </summary>
            /// <param name="key"></param>
            /// <param name="val"></param>
            /// <param name="exp">过期时间</param>
            /// <returns></returns>
            public bool StringSet(string key, string val, TimeSpan? exp = default(TimeSpan?))
            {
                key = redis.AddKey(key);
                return redis.DoSave(db => db.StringSet(key, val, exp));
            }
    
            /// <summary>
            /// 保存多个key value
            /// </summary>
            /// <param name="keyValues">键值对</param>
            /// <returns></returns>
            public bool StringSet(List<KeyValuePair<RedisKey, RedisValue>> KeyVal)
            {
                List<KeyValuePair<RedisKey, RedisValue>> newkey = KeyVal.Select(k => new KeyValuePair<RedisKey, RedisValue>(redis.AddKey(k.Key), k.Value)).ToList();
                return redis.DoSave(db => db.StringSet(newkey.ToArray()));
            }
    
            /// <summary>
            /// 保存一个对象
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <param name="obj"></param>
            /// <param name="exp"></param>
            /// <returns></returns>
            public bool StringSet<T>(string key, T obj, TimeSpan? exp = default(TimeSpan?))
            {
                key = redis.AddKey(key);
                string json = redis.ConvertJson(obj);
                return redis.DoSave(db => db.StringSet(key, json, exp));
            }
    
            /// <summary>
            /// 获取单个
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public string StringGet(string key)
            {
               key = redis.AddKey(key);
                return redis.DoSave(db => db.StringGet(key));
            }
            /// <summary>
            /// 获取单个对象
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <returns></returns>
            public T StringGet<T>(string key) {
                key = redis.AddKey(key);
                var val = redis.DoSave(db => db.StringGet(key));
                return redis.ConvertObj<T>(val);
            }
    
            /// <summary>
            /// 为数字增长val
            /// </summary>
            /// <param name="key"></param>
            /// <param name="val">可以为负数</param>
            /// <returns>增长后的值</returns>
            public double StringIncrement(string key, double val = 1)
            {
               key = redis.AddKey(key);
                return redis.DoSave(db => db.StringIncrement(key, val));
            }
            /// <summary>
            /// 为数字减少val
            /// </summary>
            /// <param name="key"></param>
            /// <param name="val">可以为负数</param>
            /// <returns>增长后的值</returns>
            public double StringDecrement(string key, double val = 1)
            {
               key = redis.AddKey(key);
                return redis.DoSave(db => db.StringDecrement(key, val));
            }
            #endregion
    
            #region 异步执行
            /// <summary>
            /// 异步保存单个
            /// </summary>
            /// <param name="key"></param>
            /// <param name="val"></param>
            /// <param name="exp"></param>
            /// <returns></returns>
            public async Task<bool> StringSetAsync(string key, string val, TimeSpan? exp = default(TimeSpan?))
            {
                key = redis.AddKey(key);
                return await redis.DoSave(db => db.StringSetAsync(key, val, exp));
            }
            /// <summary>
            /// 异步保存多个key value
            /// </summary>
            /// <param name="keyValues">键值对</param>
            /// <returns></returns>
            public async Task<bool> StringSetAsync(List<KeyValuePair<RedisKey, RedisValue>> KeyVal)
            {
                List<KeyValuePair<RedisKey, RedisValue>> newkey = KeyVal.Select(k => new KeyValuePair<RedisKey, RedisValue>(redis.AddKey(k.Key), k.Value)).ToList();
                return await redis.DoSave(db => db.StringSetAsync(newkey.ToArray()));
            }
    
            /// <summary>
            /// 异步保存一个对象
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <param name="obj"></param>
            /// <param name="exp"></param>
            /// <returns></returns>
            public async Task<bool> StringSetAsync<T>(string key, T obj, TimeSpan? exp = default(TimeSpan?))
            {
                key = redis.AddKey(key);
                string json = redis.ConvertJson(obj);
                return await redis.DoSave(db => db.StringSetAsync(key, json, exp));
            }
    
            /// <summary>
            /// 异步获取单个
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public async Task<string> StringGetAsync(string key)
            {
               key = redis.AddKey(key);
                return await redis.DoSave(db => db.StringGetAsync(key));
            }
    
            /// <summary>
            /// 异步获取单个
            /// </summary>
            /// <param name="key"></param>
            /// <returns></returns>
            public async Task<T> StringGetAsync<T>(string key)
            {
                key = redis.AddKey(key);
                var val = await redis.DoSave(db => db.StringGetAsync(key));
                return redis.ConvertObj<T>(val);
            }
    
            /// <summary>
            /// 异步为数字增长val
            /// </summary>
            /// <param name="key"></param>
            /// <param name="val">可以为负数</param>
            /// <returns>增长后的值</returns>
            public async Task<double> StringIncrementAsync(string key, double val = 1)
            {
               key = redis.AddKey(key);
                return await redis.DoSave(db => db.StringIncrementAsync(key, val));
            }
            /// <summary>
            /// 为数字减少val
            /// </summary>
            /// <param name="key"></param>
            /// <param name="val">可以为负数</param>
            /// <returns>增长后的值</returns>
            public async Task<double> StringDecrementAsync(string key, double val = 1)
            {
               key = redis.AddKey(key);
                return await redis.DoSave(db => db.StringDecrementAsync(key, val));
            }
            #endregion
        }
    }

    StackExchange.Redis本身提供了一套异步的方法这个我比较喜欢。至于其他的和string的同理,我这里就不放出封装方法,需要的留言。

    最后是测试:

    这是我的redis然后是我的数据库

    这里是我登录的测试代码:

  • 相关阅读:
    tcp单线程实现并发
    文件处理
    异常处理、深浅拷贝、基本的文件操作
    列表、元组、字典、集合类型的内置方法
    python进阶之数字类型内置方法和字符串类型内置方法
    九九乘法表和金字塔
    python基础总结
    0801学习整理
    0731学习内容整理
    0730学习内容整理
  • 原文地址:https://www.cnblogs.com/edna-lzh/p/6932948.html
Copyright © 2011-2022 走看看