1. using Newtonsoft.Json;
  2. using StackExchange.Redis;
  3. using System;
  4. using System.Configuration;
  5. using System.Reflection;
  6. using System.Threading.Tasks;
  7. using System.Text;
  8.  
  9. namespace Lemon.Common
  10. {
  11. public static class RedisUtil
  12. {
  13. //缓存失效时长
  14. private static TimeSpan _expiry = TimeSpan.FromMinutes();
  15. private static object _locker = new Object();
  16. private static ConnectionMultiplexer _instance = null;
  17.  
  18. /// <summary>
  19. /// 使用一个静态属性来返回已连接的实例,如下列中所示。这样,一旦 ConnectionMultiplexer 断开连接,便可以初始化新的连接实例。
  20. /// </summary>
  21. public static ConnectionMultiplexer Instance
  22. {
  23. get
  24. {
  25. if (_instance == null)
  26. {
  27. lock (_locker)
  28. {
  29. if (_instance == null || !_instance.IsConnected)
  30. {
  31. _instance = ConnectionMultiplexer.Connect(EnvironmentCache.ConnectionStrings["RedisConnection"]);
  32. }
  33. }
  34. }
  35. //注册如下事件
  36. _instance.ConnectionFailed += MuxerConnectionFailed;
  37. _instance.ConnectionRestored += MuxerConnectionRestored;
  38. _instance.ErrorMessage += MuxerErrorMessage;
  39. _instance.HashSlotMoved += MuxerHashSlotMoved;
  40. _instance.InternalError += MuxerInternalError;
  41. return _instance;
  42. }
  43. }
  44.  
  45. static RedisUtil()
  46. {
  47. }
  48.  
  49. /// <summary>
  50. ///
  51. /// </summary>
  52. /// <returns></returns>
  53. public static IDatabase GetDatabase(int db)
  54. {
  55. return Instance.GetDatabase(db);
  56. }
  57.  
  58. /// <summary>
  59. /// 异步获取缓存数据
  60. /// </summary>
  61. /// <typeparam name="T"></typeparam>
  62. /// <param name="dbIndex">Redis数据库索引</param>
  63. /// <param name="key">Redis键</param>
  64. /// <param name="fun">从其他地方获取数据源,并缓存到Redis中</param>
  65. /// <returns></returns>
  66. public static async Task<T> GetAsync<T>(int dbIndex, string key, Func<T> fun)
  67. {
  68. var db = GetDatabase(dbIndex);
  69. if (db.KeyExists(key))
  70. {
  71. return JsonConvert.DeserializeObject<T>(db.StringGet(key));
  72. }
  73. T data = default(T);
  74. if (fun != null)
  75. {
  76. data = await Task.Run(() =>
  77. {
  78. return fun();
  79. });
  80. db.Set(key, data);
  81. }
  82. return data;
  83. }
  84.  
  85. /// <summary>
  86. /// 同步获取缓存数据
  87. /// </summary>
  88. /// <typeparam name="T"></typeparam>
  89. /// <param name="dbIndex">Redis数据库索引</param>
  90. /// <param name="key">Redis键</param>
  91. /// <param name="fun">从其他地方获取数据源,并缓存到Redis中</param>
  92. /// <returns></returns>
  93. public static T Get<T>(int dbIndex, string key, Func<T> fun)
  94. {
  95. var db = GetDatabase(dbIndex);
  96. if (db.KeyExists(key))
  97. {
  98. return JsonConvert.DeserializeObject<T>(db.StringGet(key));
  99. }
  100. T data = default(T);
  101. if (fun != null)
  102. {
  103. data = fun();
  104. db.Set(key, data);
  105. }
  106. return data;
  107. }
  108.  
  109. /// <summary>
  110. /// 设置缓存
  111. /// </summary>
  112. /// <param name="key"></param>
  113. /// <param name="value"></param>
  114. public static void Set(this IDatabase db,string key, object value)
  115. {
  116. db.StringSet(key, JsonConvert.SerializeObject(value), _expiry);
  117. }
  118.  
  119. /// <summary>
  120. /// 实现递增
  121. /// </summary>
  122. /// <param name="key"></param>
  123. /// <returns></returns>
  124. //public static long Increment(string key)
  125. //{
  126. // //三种命令模式
  127. // //Sync,同步模式会直接阻塞调用者,但是显然不会阻塞其他线程。
  128. // //Async,异步模式直接走的是Task模型。
  129. // //Fire - and - Forget,就是发送命令,然后完全不关心最终什么时候完成命令操作。
  130. // //即发即弃:通过配置 CommandFlags 来实现即发即弃功能,在该实例中该方法会立即返回,如果是string则返回null 如果是int则返回0.这个操作将会继续在后台运行,一个典型的用法页面计数器的实现:
  131. // return GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget);
  132. //}
  133.  
  134. /// <summary>
  135. /// 实现递减
  136. /// </summary>
  137. /// <param name="key"></param>
  138. /// <param name="value"></param>
  139. /// <returns></returns>
  140. //public static long Decrement(string key, string value)
  141. //{
  142. // return GetDatabase().HashDecrement(key, value, flags: CommandFlags.FireAndForget);
  143. //}
  144.  
  145. /// <summary>
  146. /// 发生错误时
  147. /// </summary>
  148. /// <param name="sender"></param>
  149. /// <param name="e"></param>
  150. private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
  151. {
  152. Logger.Error(e.Message);
  153. }
  154. /// <summary>
  155. /// 重新建立连接之前的错误
  156. /// </summary>
  157. /// <param name="sender"></param>
  158. /// <param name="e"></param>
  159. private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
  160. {
  161. Logger.Error(sender, e.Exception);
  162. }
  163. /// <summary>
  164. /// 连接失败 , 如果重新连接成功你将不会收到这个通知
  165. /// </summary>
  166. /// <param name="sender"></param>
  167. /// <param name="e"></param>
  168. private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
  169. {
  170. // LogHelper.WriteInfoLog("重新连接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType + (e.Exception == null ? "" : (", " + e.Exception.Message)));
  171. }
  172. /// <summary>
  173. /// 更改集群
  174. /// </summary>
  175. /// <param name="sender"></param>
  176. /// <param name="e"></param>
  177. private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
  178. {
  179. // LogHelper.WriteInfoLog("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
  180. }
  181. /// <summary>
  182. /// redis类库错误
  183. /// </summary>
  184. /// <param name="sender"></param>
  185. /// <param name="e"></param>
  186. private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
  187. {
  188. Logger.Error(sender, e.Exception);
  189. }
  190.  
  191. //场景不一样,选择的模式便会不一样,大家可以按照自己系统架构情况合理选择长连接还是Lazy。
  192. //建立连接后,通过调用ConnectionMultiplexer.GetDatabase 方法返回对 Redis Cache 数据库的引用。从 GetDatabase 方法返回的对象是一个轻量级直通对象,不需要进行存储。
  193.  
  194. /// <summary>
  195. /// 使用的是Lazy,在真正需要连接时创建连接。
  196. /// 延迟加载技术
  197. /// 微软azure中的配置 连接模板
  198. /// </summary>
  199. //private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
  200. //{
  201. // //var options = ConfigurationOptions.Parse(constr);
  202. // ////options.ClientName = GetAppName(); // only known at runtime
  203. // //options.AllowAdmin = true;
  204. // //return ConnectionMultiplexer.Connect(options);
  205. // ConnectionMultiplexer muxer = ConnectionMultiplexer.Connect(Coonstr);
  206. // muxer.ConnectionFailed += MuxerConnectionFailed;
  207. // muxer.ConnectionRestored += MuxerConnectionRestored;
  208. // muxer.ErrorMessage += MuxerErrorMessage;
  209. // muxer.ConfigurationChanged += MuxerConfigurationChanged;
  210. // muxer.HashSlotMoved += MuxerHashSlotMoved;
  211. // muxer.InternalError += MuxerInternalError;
  212. // return muxer;
  213. //});
  214.  
  215. #region 当作消息代理中间件使用 一般使用更专业的消息队列来处理这种业务场景
  216. /// <summary>
  217. /// 当作消息代理中间件使用
  218. /// 消息组建中,重要的概念便是生产者,消费者,消息中间件。
  219. /// </summary>
  220. /// <param name="channel"></param>
  221. /// <param name="message"></param>
  222. /// <returns></returns>
  223. public static long Publish(string channel, string message)
  224. {
  225. ISubscriber sub = Instance.GetSubscriber();
  226. //return sub.Publish("messages", "hello");
  227. return sub.Publish(channel, message);
  228. }
  229.  
  230. /// <summary>
  231. /// 在消费者端得到该消息并输出
  232. /// </summary>
  233. /// <param name="channelFrom"></param>
  234. /// <returns></returns>
  235. public static void Subscribe(string channelFrom)
  236. {
  237. ISubscriber sub = Instance.GetSubscriber();
  238. sub.Subscribe(channelFrom, (channel, message) =>
  239. {
  240. Console.WriteLine((string)message);
  241. });
  242. }
  243. #endregion
  244. }}
  1. /// <summary>
  2. ///通过secretkey对应的平台id
  3. /// </summary>
  4. /// <param name="secretKey"></param>
  5. /// <returns></returns>
  6. public int GetChannel(string secretKey, string appKey)
  7. {
  8. string key = string.Format("{0}&{1}",secretKey,appKey);
  9. int channelId = RedisUtil.Get<int>(, key, () =>
  10. {
  11. using (var context = new MediaDBContext())
  12. {
  13. return context.ChannelApps.Where(a => a.AppKey == appKey && a.Channel.SecretKey == secretKey && !a.IsDel)
  14. .Select(c => c.ChannelId)
  15. .FirstOrDefault();
  16. }
  17. });
  18. return channelId;
  19. }
  1. <add name="RedisConnection" connectionString="127.0.0.1,password=Lemon82211852" />

Redis Fun使用的更多相关文章

  1. 使用redis构建可靠分布式锁

    关于分布式锁的概念,具体实现方式,直接参阅下面两个帖子,这里就不多介绍了. 分布式锁的多种实现方式 分布式锁总结 对于分布式锁的几种实现方式的优劣,这里再列举下 1. 数据库实现方式 优点:易理解 缺 ...

  2. Ignite性能测试以及对redis的对比

    测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像.测试方法很简单主要是下面几点: 不作参数优化,默认 ...

  3. mac osx 安装redis扩展

    1 php -v查看php版本 2 brew search php|grep redis 搜索对应的redis   ps:如果没有brew 就根据http://brew.sh安装 3 brew ins ...

  4. Redis/HBase/Tair比较

    KV系统对比表 对比维度 Redis Redis Cluster Medis Hbase Tair 访问模式    支持Value大小 理论上不超过1GB(建议不超过1MB) 理论上可配置(默认配置1 ...

  5. Redis数据库

    Redis是k-v型数据库的典范,设计思想及数据结构实现都值得学习. 1.数据类型 value支持五种数据类型:1.字符串(strings)2.字符串列表(lists)3.字符串集合(sets)4.有 ...

  6. redis 学习笔记(2)

    redis-cluster 简介 redis-cluster是一个分布式.容错的redis实现,redis-cluster通过将各个单独的redis实例通过特定的协议连接到一起实现了分布式.集群化的目 ...

  7. redis 学习笔记(1)

    redis持久化 snapshot数据快照(rdb) 这是一种定时将redis内存中的数据写入磁盘文件的一种方案,这样保留这一时刻redis中的数据镜像,用于意外回滚.redis的snapshot的格 ...

  8. python+uwsgi导致redis无法长链接引起性能下降问题记录

    今天在部署python代码到预生产环境时,web站老是出现redis链接未初始化,无法连接到服务的提示,比对了一下开发环境与测试环境代码,完全一致,然后就是查看各种日志,排查了半天也没有查明是什么原因 ...

  9. nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...

  10. windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)

    本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...

随机推荐

  1. 课后选做题:MyOD

    目录 OD命令了解 MyOD实现 OD命令了解 作用:od命令用于输出文件的八进制.十六进制或其它格式编码的字节,通常用于显示或查看文件中不能直接显示在终端的字符.常见的文件为文本文件和二进制文件.此 ...

  2. [模板]ETT

    解:splay维护括号序列,就是进子树一次出子树一次.树上每个点直接记录这两个点的编号. 建树的时候按照分配的编号建树. #include <bits/stdc++.h> typedef ...

  3. bs4抓取糗事百科

    抓取糗事百科内容及评论,不包含图片信息.user-agent填入浏览器的即可.user-agent对应的value,360极速浏览器的话,可以在地址栏输入about:version,回车,用户代理后面 ...

  4. struts2 数据转换器

    四.数据类型的转换(明白原理,实际开发中几乎不用) 1.开发中的情况: 实际开发中用户通过浏览器输入的数据都是String或者String[]. String/String[]————填充模型(set ...

  5. typedef typename的用法

    我自己最后在这篇文章里理解:[C++]typedef typename什么意思? typedef typename A::a_type b_type; 其中typename是告诉编译器A::a_typ ...

  6. okhttp 内网可以有,但外网访问数据返不回来,代码一样

    :1.问题点在于 下图红框里写成 text/html了,需要改成application/json,造成的问题有:unexpected end of stream  这个是406错误:加上日志之后okh ...

  7. 解决access 导出 excel 字段截断错误的问题

    解决方法:这个问题通过从EXCEL中导入外部数据,也就是ACCESS数据可以解决. 1.选择导入数据 2.点击选择数据源 选择需要导入的access数据源

  8. 过滤富文本编辑器中的html元素和其他元素

    https://blog.csdn.net/fjssharpsword/article/details/53467079 1.应用场景:从一份html文件中或从String(是html内容)中提取纯文 ...

  9. (BFS) leetcode 690. Employee Importance

    690. Employee Importance Easy 377369FavoriteShare You are given a data structure of employee informa ...

  10. MySQL会发生死锁吗?

    SHOW ENGINE INNODB STATUS;来查看死锁日志: SHOW PROCESSLIST;查看进程 MySQL的InnoDB引擎事务有4种隔离级别,主要是为了保证数据的一致性. Inno ...