在.Net下使用redis基於StackExchange.Redis
阿新 • • 發佈:2017-06-02
sof sel setting null pep inf syn url 討論
研究了下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(); privatestatic 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然後是我的數據庫
這裏是我登錄的測試代碼:
在.Net下使用redis基於StackExchange.Redis