Redis Fun使用
using Newtonsoft.Json; using StackExchange.Redis; using System; using System.Configuration; using System.Reflection; using System.Threading.Tasks; using System.Text; namespace Lemon.Common { public static class RedisUtil { //缓存失效时长 private static TimeSpan _expiry = TimeSpan.FromMinutes(30); private static object _locker = new Object(); private static ConnectionMultiplexer _instance = null; /// <summary> /// 使用一个静态属性来返回已连接的实例,如下列中所示。这样,一旦 ConnectionMultiplexer 断开连接,便可以初始化新的连接实例。 /// </summary> public static ConnectionMultiplexer Instance { get { if (_instance == null) { lock (_locker) { if (_instance == null || !_instance.IsConnected) { _instance = ConnectionMultiplexer.Connect(EnvironmentCache.ConnectionStrings["RedisConnection"]); } } } //注册如下事件 _instance.ConnectionFailed += MuxerConnectionFailed; _instance.ConnectionRestored += MuxerConnectionRestored; _instance.ErrorMessage += MuxerErrorMessage; _instance.HashSlotMoved += MuxerHashSlotMoved; _instance.InternalError += MuxerInternalError; return _instance; } } static RedisUtil() { } /// <summary> /// /// </summary> /// <returns></returns> public static IDatabase GetDatabase(int db) { return Instance.GetDatabase(db); } /// <summary> /// 异步获取缓存数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dbIndex">Redis数据库索引</param> /// <param name="key">Redis键</param> /// <param name="fun">从其他地方获取数据源,并缓存到Redis中</param> /// <returns></returns> public static async Task<T> GetAsync<T>(int dbIndex, string key, Func<T> fun) { var db = GetDatabase(dbIndex); if (db.KeyExists(key)) { return JsonConvert.DeserializeObject<T>(db.StringGet(key)); } T data = default(T); if (fun != null) { data = await Task.Run(() => { return fun(); }); db.Set(key, data); } return data; } /// <summary> /// 同步获取缓存数据 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dbIndex">Redis数据库索引</param> /// <param name="key">Redis键</param> /// <param name="fun">从其他地方获取数据源,并缓存到Redis中</param> /// <returns></returns> public static T Get<T>(int dbIndex, string key, Func<T> fun) { var db = GetDatabase(dbIndex); if (db.KeyExists(key)) { return JsonConvert.DeserializeObject<T>(db.StringGet(key)); } T data = default(T); if (fun != null) { data = fun(); db.Set(key, data); } return data; } /// <summary> /// 设置缓存 /// </summary> /// <param name="key"></param> /// <param name="value"></param> public static void Set(this IDatabase db,string key, object value) { db.StringSet(key, JsonConvert.SerializeObject(value), _expiry); } /// <summary> /// 实现递增 /// </summary> /// <param name="key"></param> /// <returns></returns> //public static long Increment(string key) //{ // //三种命令模式 // //Sync,同步模式会直接阻塞调用者,但是显然不会阻塞其他线程。 // //Async,异步模式直接走的是Task模型。 // //Fire - and - Forget,就是发送命令,然后完全不关心最终什么时候完成命令操作。 // //即发即弃:通过配置 CommandFlags 来实现即发即弃功能,在该实例中该方法会立即返回,如果是string则返回null 如果是int则返回0.这个操作将会继续在后台运行,一个典型的用法页面计数器的实现: // return GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget); //} /// <summary> /// 实现递减 /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> //public static long Decrement(string key, string value) //{ // return GetDatabase().HashDecrement(key, value, flags: CommandFlags.FireAndForget); //} /// <summary> /// 发生错误时 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e) { Logger.Error(e.Message); } /// <summary> /// 重新建立连接之前的错误 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e) { Logger.Error(sender, e.Exception); } /// <summary> /// 连接失败 , 如果重新连接成功你将不会收到这个通知 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e) { // LogHelper.WriteInfoLog("重新连接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType + (e.Exception == null ? "" : (", " + e.Exception.Message))); } /// <summary> /// 更改集群 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e) { // LogHelper.WriteInfoLog("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint); } /// <summary> /// redis类库错误 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private static void MuxerInternalError(object sender, InternalErrorEventArgs e) { Logger.Error(sender, e.Exception); } //场景不一样,选择的模式便会不一样,大家可以按照自己系统架构情况合理选择长连接还是Lazy。 //建立连接后,通过调用ConnectionMultiplexer.GetDatabase 方法返回对 Redis Cache 数据库的引用。从 GetDatabase 方法返回的对象是一个轻量级直通对象,不需要进行存储。 /// <summary> /// 使用的是Lazy,在真正需要连接时创建连接。 /// 延迟加载技术 /// 微软azure中的配置 连接模板 /// </summary> //private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => //{ // //var options = ConfigurationOptions.Parse(constr); // ////options.ClientName = GetAppName(); // only known at runtime // //options.AllowAdmin = true; // //return ConnectionMultiplexer.Connect(options); // ConnectionMultiplexer muxer = ConnectionMultiplexer.Connect(Coonstr); // muxer.ConnectionFailed += MuxerConnectionFailed; // muxer.ConnectionRestored += MuxerConnectionRestored; // muxer.ErrorMessage += MuxerErrorMessage; // muxer.ConfigurationChanged += MuxerConfigurationChanged; // muxer.HashSlotMoved += MuxerHashSlotMoved; // muxer.InternalError += MuxerInternalError; // return muxer; //}); #region 当作消息代理中间件使用 一般使用更专业的消息队列来处理这种业务场景 /// <summary> /// 当作消息代理中间件使用 /// 消息组建中,重要的概念便是生产者,消费者,消息中间件。 /// </summary> /// <param name="channel"></param> /// <param name="message"></param> /// <returns></returns> public static long Publish(string channel, string message) { ISubscriber sub = Instance.GetSubscriber(); //return sub.Publish("messages", "hello"); return sub.Publish(channel, message); } /// <summary> /// 在消费者端得到该消息并输出 /// </summary> /// <param name="channelFrom"></param> /// <returns></returns> public static void Subscribe(string channelFrom) { ISubscriber sub = Instance.GetSubscriber(); sub.Subscribe(channelFrom, (channel, message) => { Console.WriteLine((string)message); }); } #endregion }}
/// <summary> ///通过secretkey对应的平台id /// </summary> /// <param name="secretKey"></param> /// <returns></returns> public int GetChannel(string secretKey, string appKey) { string key = string.Format("{0}&{1}",secretKey,appKey); int channelId = RedisUtil.Get<int>(0, key, () => { using (var context = new MediaDBContext()) { return context.ChannelApps.Where(a => a.AppKey == appKey && a.Channel.SecretKey == secretKey && !a.IsDel) .Select(c => c.ChannelId) .FirstOrDefault(); } }); return channelId; }
<add name="RedisConnection" connectionString="127.0.0.1,password=Lemon82211852" />