研究了下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 DictionaryConcache = new Dictionary (); /// /// 单例模式获取redis连接实例 /// public static ConnectionMultiplexer Instance { get { if (instance == null) { lock (locker) { if (instance == null) instance = GetManager(); } } return instance; } } ////// 从缓存中获取 /// /// ///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事件 /// /// 内部异常 /// /// /// private static void MuxerInternalError(object sender, InternalErrorEventArgs e) { Units.Log("内部异常:" + e.Exception.Message); } ////// 集群更改 /// /// /// private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e) { Units.Log("新集群:" + e.NewEndPoint + "旧集群:" + e.OldEndPoint); } ////// 配置更改事件 /// /// /// private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e) { Units.Log("配置更改:" + e.EndPoint); } ////// 错误事件 /// /// /// private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e) { Units.Log("异常信息:" + e.Message); } ////// 重连错误事件 /// /// /// private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e) { Units.Log("重连错误" + e.EndPoint); } ////// 连接失败事件 /// /// /// 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 辅助方法 ////// 添加名称 /// /// ///public string AddKey(string old) { var fixkey = key ?? RedisConfig.Key(); return fixkey + old; } /// /// 执行保存 /// ////// /// public T DoSave (Func func) { return func(db.GetDatabase(DbNumber)); } public string ConvertJson (T val) { return val is string ? val.ToString() : JsonConvert.SerializeObject(val); } public T ConvertObj (RedisValue val) { return JsonConvert.DeserializeObject (val); } public List ConvertList (RedisValue[] val) { List result = new List (); foreach (var item in val) { var model = ConvertObj (item); result.Add(model); } return result; } public RedisKey[] ConvertRedisKeys(List 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 { ////// 表示string的操作 /// public class DoRedisStringCache : IRedisCaching { private RedisBase redis = null; public DoRedisStringCache() { redis = new RedisBase(); } #region 同步执行 ////// 单个保存 /// /// /// 值 /// 过期时间 ///public bool StringSet(string key, string val, TimeSpan? exp = default(TimeSpan?)) { key = redis.AddKey(key); return redis.DoSave(db => db.StringSet(key, val, exp)); } /// /// 保存多个key value /// /// 键值对 ///public bool StringSet(List > KeyVal) { List > newkey = KeyVal.Select(k => new KeyValuePair (redis.AddKey(k.Key), k.Value)).ToList(); return redis.DoSave(db => db.StringSet(newkey.ToArray())); } /// /// 保存一个对象 /// ////// /// /// /// public bool StringSet (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)); } /// /// 获取单个 /// /// ///public string StringGet(string key) { key = redis.AddKey(key); return redis.DoSave(db => db.StringGet(key)); } /// /// 获取单个对象 /// ////// /// public T StringGet (string key) { key = redis.AddKey(key); var val = redis.DoSave(db => db.StringGet(key)); return redis.ConvertObj (val); } /// /// 为数字增长val /// /// /// 可以为负数 ///增长后的值 public double StringIncrement(string key, double val = 1) { key = redis.AddKey(key); return redis.DoSave(db => db.StringIncrement(key, val)); } ////// 为数字减少val /// /// /// 可以为负数 ///增长后的值 public double StringDecrement(string key, double val = 1) { key = redis.AddKey(key); return redis.DoSave(db => db.StringDecrement(key, val)); } #endregion #region 异步执行 ////// 异步保存单个 /// /// /// /// ///public async Task StringSetAsync(string key, string val, TimeSpan? exp = default(TimeSpan?)) { key = redis.AddKey(key); return await redis.DoSave(db => db.StringSetAsync(key, val, exp)); } /// /// 异步保存多个key value /// /// 键值对 ///public async Task StringSetAsync(List > KeyVal) { List > newkey = KeyVal.Select(k => new KeyValuePair (redis.AddKey(k.Key), k.Value)).ToList(); return await redis.DoSave(db => db.StringSetAsync(newkey.ToArray())); } /// /// 异步保存一个对象 /// ////// /// /// /// public async Task StringSetAsync (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)); } /// /// 异步获取单个 /// /// ///public async Task StringGetAsync(string key) { key = redis.AddKey(key); return await redis.DoSave(db => db.StringGetAsync(key)); } /// /// 异步获取单个 /// /// ///public async Task StringGetAsync (string key) { key = redis.AddKey(key); var val = await redis.DoSave(db => db.StringGetAsync(key)); return redis.ConvertObj (val); } /// /// 异步为数字增长val /// /// /// 可以为负数 ///增长后的值 public async TaskStringIncrementAsync(string key, double val = 1) { key = redis.AddKey(key); return await redis.DoSave(db => db.StringIncrementAsync(key, val)); } /// /// 为数字减少val /// /// /// 可以为负数 ///增长后的值 public async TaskStringDecrementAsync(string key, double val = 1) { key = redis.AddKey(key); return await redis.DoSave(db => db.StringDecrementAsync(key, val)); } #endregion } }
StackExchange.Redis本身提供了一套异步的方法这个我比较喜欢。至于其他的和string的同理,我这里就不放出封装方法,需要的留言。
最后是测试:
这是我的redis然后是我的数据库
这里是我登录的测试代码: