一个技术汪的开源梦 —— 公共组件缓存之分布式缓存 Redis 实现篇
Redis 安装 & 配置
本测试环境将在 CentOS 7 x64 上安装最新版本的 Redis。
1. 运行以下命令安装 Redis
$ wget http://download.redis.io/releases/redis-3.2.6.tar.gz $ tar xzf redis-3.2.6.tar.gz $ cd redis-3.2.6 $ make install
如果 CentOS 上提示 wget 命令未找到,则先安装 net-tools。
yum install net-tools
2. Redis 配置文件
1)开启守护程序
修改 daemonize 节点为 yes。
2)运行外部IP访问
配置 bind 节点为 0.0.0.0
本次示例只使用 Redis 的缓存 所以配置暂时只修改这两处即可。
3. 设置 Redis 开机自动启动
1)在 Redis 的源码包中找到 utils 目录
2) 将 redis_init_script 文件复制到 /etc/init.d 目录下并重命名为 redisd
cp redis_init_script /etc/init.d/redisd
3) 打开 redisd 修改部分配置。
1 #!/bin/sh 2 # chkconfig: 2345 90 10 3 # Simple Redis init.d script conceived to work on Linux systems 4 # as it does use of the /proc filesystem. 5 6 REDISPORT=6379 7 EXEC=/usr/local/bin/redis-server 8 CLIEXEC=/usr/local/bin/redis-cli 9 10 PIDFILE=/var/run/redis_${REDISPORT}.pid 11 CONF="/etc/redis/redis_${REDISPORT}.conf"
其中第二行 # chkconfig: 2345 90 10 需要另行添加。
- REDISPORT Redis 运行端口号;
- EXEC Redis 服务器命令文件路径(根据实际情况修改);
- CLIEXEC Redis 客户端命令文件路径(亦根据实际情况修改);
- CONF Redis 配置文件。
4)设置开机启动 & 启动、停止服务
#设置为开机自启动服务器 chkconfig redisd on #打开服务 service redisd start #关闭服务 service redisd stop
主:如果外部机器还访问不到 Redis 服务器,请将 6379 端口号加防火墙例外即可。
代码实现:
Common 包 接口定义 & 分布式缓存实例获取和配置
- IDistributedCache 接口
1 using System; 2 3 namespace Wlitsoft.Framework.Common.Core 4 { 5 /// <summary> 6 /// 分布式缓存接口。 7 /// </summary> 8 public interface IDistributedCache 9 { 10 /// <summary> 11 /// 获取缓存。 12 /// </summary> 13 /// <typeparam name="T">缓存类型。</typeparam> 14 /// <param name="key">缓存键值。</param> 15 /// <returns>获取到的缓存。</returns> 16 T Get<T>(string key); 17 18 /// <summary> 19 /// 设置缓存。 20 /// </summary> 21 /// <typeparam name="T">缓存类型。</typeparam> 22 /// <param name="key">缓存键值。</param> 23 /// <param name="value">要缓存的对象。</param> 24 void Set<T>(string key, T value); 25 26 /// <summary> 27 /// 设置缓存。 28 /// </summary> 29 /// <typeparam name="T">缓存类型。</typeparam> 30 /// <param name="key">缓存键值。</param> 31 /// <param name="value">要缓存的对象。</param> 32 /// <param name="expiredTime">过期时间。</param> 33 void Set<T>(string key, T value, TimeSpan expiredTime); 34 35 /// <summary> 36 /// 判断指定键值的缓存是否存在。 37 /// </summary> 38 /// <param name="key">缓存键值。</param> 39 /// <returns>一个布尔值,表示缓存是否存在。</returns> 40 bool Exists(string key); 41 42 /// <summary> 43 /// 移除指定键值的缓存。 44 /// </summary> 45 /// <param name="key">缓存键值。</param> 46 bool Remove(string key); 47 48 /// <summary> 49 /// 获取 Hash 表中的缓存。 50 /// </summary> 51 /// <typeparam name="T">缓存类型。</typeparam> 52 /// <param name="key">缓存键值。</param> 53 /// <param name="hashField">要获取的 hash 字段。</param> 54 /// <returns>获取到的缓存。</returns> 55 T GetHash<T>(string key, string hashField); 56 57 /// <summary> 58 /// 设置 缓存到 Hash 表。 59 /// </summary> 60 /// <typeparam name="T">缓存类型。</typeparam> 61 /// <param name="key">缓存键值。</param> 62 /// <param name="hashField">要设置的 hash 字段。</param> 63 /// <param name="hashValue">要设置的 hash 值。</param> 64 void SetHash<T>(string key, string hashField, T hashValue); 65 66 /// <summary> 67 /// 判断指定键值的 Hash 缓存是否存在。 68 /// </summary> 69 /// <param name="key">缓存键值。</param> 70 /// <param name="hashField">hash 字段。</param> 71 /// <returns>一个布尔值,表示缓存是否存在。</returns> 72 bool ExistsHash(string key, string hashField); 73 74 /// <summary> 75 /// 删除 hash 表中的指定字段的缓存。 76 /// </summary> 77 /// <param name="key">缓存键值。</param> 78 /// <param name="hashField">hash 字段。</param> 79 /// <returns>一个布尔值,表示缓存是否删除成功。</returns> 80 bool DeleteHash(string key, string hashField); 81 } 82 }
- App 类
1 /// <summary> 2 /// 获取分布式缓存。 3 /// </summary> 4 public static IDistributedCache DistributedCache { get; internal set; }
- AppBuilder 类
1 namespace Wlitsoft.Framework.Common 2 { 3 /// <summary> 4 /// 应用 构造。 5 /// </summary> 6 public class AppBuilder 7 { 8 #region 添加序列化者 9 10 /// <summary> 11 /// 添加序列化者。 12 /// </summary> 13 /// <param name="type">序列化类型。</param> 14 /// <param name="serializer">序列化者接口。</param> 15 public void AddSerializer(SerializeType type, ISerializer serializer) 16 { 17 #region 参数校验 18 19 if (serializer == null) 20 throw new ObjectNullException(nameof(serializer)); 21 22 #endregion 23 24 App.SerializerService.SetSerializer(type, serializer); 25 } 26 27 #endregion 28 29 #region 添加日志记录者 30 31 /// <summary> 32 /// 添加日志记录者。 33 /// </summary> 34 /// <param name="name">日志记录者名称。</param> 35 /// <param name="logger">日志接口。</param> 36 public void AddLogger(string name, ILog logger) 37 { 38 #region 参数校验 39 40 if (string.IsNullOrEmpty(name)) 41 throw new StringNullOrEmptyException(nameof(name)); 42 43 if (logger == null) 44 throw new ObjectNullException(nameof(logger)); 45 46 #endregion 47 48 App.LoggerService.SetLogger(name, logger); 49 } 50 51 #endregion 52 53 #region 设置分布式缓存 54 55 /// <summary> 56 /// 设置分布式缓存。 57 /// </summary> 58 /// <param name="cache">分布式缓存实例。</param> 59 /// <returns></returns> 60 public AppBuilder SetDistributedCache(IDistributedCache cache) 61 { 62 #region 参数校验 63 64 if (cache == null) 65 throw new ObjectNullException(nameof(cache)); 66 67 #endregion 68 69 App.DistributedCache = cache; 70 return this; 71 } 72 73 #endregion 74 } 75 }
分布式缓存 Redis 实现
- RedisCache 类
1 using System; 2 using System.Linq; 3 using System.Threading; 4 using StackExchange.Redis; 5 using Wlitsoft.Framework.Common.Core; 6 using Wlitsoft.Framework.Common.Extension; 7 using Wlitsoft.Framework.Common.Exception; 8 9 namespace Wlitsoft.Framework.Caching.Redis 10 { 11 /// <summary> 12 /// Redis 缓存。 13 /// </summary> 14 public class RedisCache : IDistributedCache 15 { 16 #region 私有属性 17 18 //redis 连接实例。 19 private volatile ConnectionMultiplexer _connection; 20 21 //redis 缓存数据库实例。 22 private IDatabase _database; 23 24 //连接实例锁。 25 private readonly SemaphoreSlim _connectionLock = new SemaphoreSlim(1, 1); 26 27 //Redis 配置。 28 internal static RedisCacheConfiguration RedisCacheConfiguration; 29 30 #endregion 31 32 #region IDistributedCache 成员 33 34 /// <summary> 35 /// 获取缓存。 36 /// </summary> 37 /// <typeparam name="T">缓存类型。</typeparam> 38 /// <param name="key">缓存键值。</param> 39 /// <returns>获取到的缓存。</returns> 40 public T Get<T>(string key) 41 { 42 #region 参数校验 43 44 if (string.IsNullOrEmpty(key)) 45 throw new StringNullOrEmptyException(nameof(key)); 46 47 #endregion 48 49 this.Connect(); 50 string result = this._database.StringGet(key); 51 if (string.IsNullOrEmpty(result)) 52 return default(T); 53 return result.ToJsonObject<T>(); 54 } 55 56 /// <summary> 57 /// 设置缓存。 58 /// </summary> 59 /// <typeparam name="T">缓存类型。</typeparam> 60 /// <param name="key">缓存键值。</param> 61 /// <param name="value">要缓存的对象。</param> 62 public void Set<T>(string key, T value) 63 { 64 #region 参数校验 65 66 if (string.IsNullOrEmpty(key)) 67 throw new StringNullOrEmptyException(nameof(key)); 68 69 if (value == null) 70 throw new ObjectNullException(nameof(value)); 71 72 #endregion 73 74 this.Connect(); 75 this._database.StringSet(key, value.ToJsonString()); 76 } 77 78 /// <summary> 79 /// 设置缓存。 80 /// </summary> 81 /// <typeparam name="T">缓存类型。</typeparam> 82 /// <param name="key">缓存键值。</param> 83 /// <param name="value">要缓存的对象。</param> 84 /// <param name="expiredTime">过期时间。</param> 85 public void Set<T>(string key, T value, TimeSpan expiredTime) 86 { 87 #region 参数校验 88 89 if (string.IsNullOrEmpty(key)) 90 throw new StringNullOrEmptyException(nameof(key)); 91 92 if (value == null) 93 throw new ObjectNullException(nameof(value)); 94 95 #endregion 96 97 this.Connect(); 98 this._database.StringSet(key, value.ToJsonString(), expiredTime); 99 } 100 101 /// <summary> 102 /// 判断指定键值的缓存是否存在。 103 /// </summary> 104 /// <param name="key">缓存键值。</param> 105 /// <returns>一个布尔值,表示缓存是否存在。</returns> 106 public bool Exists(string key) 107 { 108 #region 参数校验 109 110 if (string.IsNullOrEmpty(key)) 111 throw new StringNullOrEmptyException(nameof(key)); 112 113 #endregion 114 115 this.Connect(); 116 return this._database.KeyExists(key); 117 } 118 119 /// <summary> 120 /// 移除指定键值的缓存。 121 /// </summary> 122 /// <param name="key">缓存键值。</param> 123 public bool Remove(string key) 124 { 125 #region 参数校验 126 127 if (string.IsNullOrEmpty(key)) 128 throw new StringNullOrEmptyException(nameof(key)); 129 130 #endregion 131 132 this.Connect(); 133 return this._database.KeyDelete(key); 134 } 135 136 /// <summary> 137 /// 获取 Hash 表中的缓存。 138 /// </summary> 139 /// <typeparam name="T">缓存类型。</typeparam> 140 /// <param name="key">缓存键值。</param> 141 /// <param name="hashField">要获取的 hash 字段。</param> 142 /// <returns>获取到的缓存。</returns> 143 public T GetHash<T>(string key, string hashField) 144 { 145 #region 参数校验 146 147 if (string.IsNullOrEmpty(key)) 148 throw new StringNullOrEmptyException(nameof(key)); 149 150 if (string.IsNullOrEmpty(hashField)) 151 throw new StringNullOrEmptyException(nameof(hashField)); 152 153 #endregion 154 155 this.Connect(); 156 string value = this._database.HashGet(key, hashField); 157 if (string.IsNullOrEmpty(value)) 158 return default(T); 159 return value.ToJsonObject<T>(); 160 } 161 162 /// <summary> 163 /// 设置 缓存到 Hash 表。 164 /// </summary> 165 /// <typeparam name="T">缓存类型。</typeparam> 166 /// <param name="key">缓存键值。</param> 167 /// <param name="hashField">要设置的 hash 字段。</param> 168 /// <param name="hashValue">要设置的 hash 值。</param> 169 public void SetHash<T>(string key, string hashField, T hashValue) 170 { 171 #region 参数校验 172 173 if (string.IsNullOrEmpty(key)) 174 throw new StringNullOrEmptyException(nameof(key)); 175 176 if (string.IsNullOrEmpty(hashField)) 177 throw new StringNullOrEmptyException(nameof(hashField)); 178 179 if (hashValue == null) 180 throw new ObjectNullException(nameof(hashValue)); 181 182 #endregion 183 184 this.Connect(); 185 this._database.HashSet(key, hashField, hashValue.ToJsonString()); 186 } 187 188 /// <summary> 189 /// 判断指定键值的 Hash 缓存是否存在。 190 /// </summary> 191 /// <param name="key">缓存键值。</param> 192 /// <param name="hashField">hash 字段。</param> 193 /// <returns>一个布尔值,表示缓存是否存在。</returns> 194 public bool ExistsHash(string key, string hashField) 195 { 196 #region 参数校验 197 198 if (string.IsNullOrEmpty(key)) 199 throw new StringNullOrEmptyException(nameof(key)); 200 201 if (string.IsNullOrEmpty(hashField)) 202 throw new StringNullOrEmptyException(nameof(hashField)); 203 204 #endregion 205 206 this.Connect(); 207 return this._database.HashExists(key, hashField); 208 } 209 210 /// <summary> 211 /// 删除 hash 表中的指定字段的缓存。 212 /// </summary> 213 /// <param name="key">缓存键值。</param> 214 /// <param name="hashField">hash 字段。</param> 215 /// <returns>一个布尔值,表示缓存是否删除成功。</returns> 216 public bool DeleteHash(string key, string hashField) 217 { 218 #region 参数校验 219 220 if (string.IsNullOrEmpty(key)) 221 throw new StringNullOrEmptyException(nameof(key)); 222 223 if (string.IsNullOrEmpty(hashField)) 224 throw new StringNullOrEmptyException(nameof(hashField)); 225 226 #endregion 227 228 this.Connect(); 229 return this._database.HashDelete(key, hashField); 230 } 231 232 #endregion 233 234 #region 私有方法 235 236 /// <summary> 237 /// 连接。 238 /// </summary> 239 private void Connect() 240 { 241 if (this._connection != null) 242 return; 243 244 this._connectionLock.Wait(); 245 try 246 { 247 if (this._connection == null) 248 { 249 this._connection = ConnectionMultiplexer.Connect(this.GetConfigurationOptions()); 250 this._database = this._connection.GetDatabase(); 251 } 252 } 253 finally 254 { 255 this._connectionLock.Release(); 256 } 257 } 258 259 private ConfigurationOptions GetConfigurationOptions() 260 { 261 #region 校验 262 263 if (RedisCacheConfiguration == null) 264 throw new ObjectNullException(nameof(RedisCacheConfiguration)); 265 266 if (!RedisCacheConfiguration.HostAndPoints.Any()) 267 throw new Exception("RedisCahce 的 HostAndPoints 不能为空"); 268 269 #endregion 270 271 ConfigurationOptions options = new ConfigurationOptions(); 272 273 foreach (string item in RedisCacheConfiguration.HostAndPoints) 274 options.EndPoints.Add(item); 275 276 options.ConnectRetry = RedisCacheConfiguration.ConnectRetry; 277 options.ConnectTimeout = RedisCacheConfiguration.ConnectTimeout; 278 279 return options; 280 } 281 282 #endregion 283 284 #region 析构函数 285 286 /// <summary> 287 /// 析构 <see cref="RedisCache"/> 类型的对象。 288 /// </summary> 289 ~RedisCache() 290 { 291 _connection?.Close(); 292 } 293 294 #endregion 295 } 296 }
转载于:https://www.cnblogs.com/wlitsoft/p/6242765.html
一个技术汪的开源梦 —— 公共组件缓存之分布式缓存 Redis 实现篇相关推荐
- java 公共组件_【JAVA语言程序设计基础篇】--Swing GUI组件的公共特性
package chapter12; import java.awt.Color; import java.awt.FlowLayout; import java.awt.Font; import j ...
- 【分布式缓存】分布式缓存-缓存技术
目录 从数据的使用说起 本地缓存 远程缓存 缓存策略 缓存常见问题 总结回顾与作业实践 1. 从数据的使用说起 我们把数据的使用频率和方式分个类 静态数据:一般不变,类似于字典表 准静态数据:变化频率 ...
- 电商技术架构演进过程——具体到每一个技术
我想,不管你是一个开发人员,或者正在走向开发路上的人,都和我一样,都想了解那些电商平台,究竟是如何一步一步从孤舟称为航空母舰的!他们都经历的哪些技术革新.我们正在做的,在哪一个节点上. 以下是我的几个 ...
- 大厂都咋用平台、分布式缓存?起码你要懂技术,高级还得懂业务
所有程序猿都对那缓存并不陌生,好似那风一样的女子只为你独自而舞.只见那回眸一笑百媚生,让你甚是吝惜,惹人怜爱. 但随着项目规模不断增大变强,光是单个缓存就难以招架,优而显得力不从心. 这时伴随着多级缓 ...
- java 项目做多级缓存_【开源项目系列】如何基于 Spring Cache 实现多级缓存(同时整合本地缓存 Ehcache 和分布式缓存 Redis)...
一.缓存 当系统的并发量上来了,如果我们频繁地去访问数据库,那么会使数据库的压力不断增大,在高峰时甚至可以出现数据库崩溃的现象.所以一般我们会使用缓存来解决这个数据库并发访问问题,用户访问进来,会先从 ...
- 通用社区登陆组件技术分享(开源)下篇:OAuth 源码下载及原理解说
原文http://www.cnblogs.com/cyq1162/archive/2012/11/07/2756848.html 上节内容: 1:通用社区登陆组件技术分享(开源)上篇:OAuth 授权 ...
- 路由到另外一个页面_如何在多个页面中,引入一个公共组件
应用场景 在前端开发的过程中,时常有这样的一个需求,需要将某个组件,展示在不同的页面中.常见的有,头部菜单栏.底部版权,如下图中的菜单,就需要在不同页面中进行显示. 解决方法 假设有这样一个需求,希望 ...
- 第十一篇: 使用ElementUi 卡片封装一个季度选择器公共组件,可直接使用
本篇主要内容:ElementUi 只提供了时间.日历等选择器,没有提供季度选择器,但在开发中报表的时候用到了季度选择器.需要换切换多种类型(年报.月报.季报), 于是封装一个季度公共组件,大家可按需修 ...
- 重磅!GitHub 开源负载均衡组件 GLB Director
8 日,GitHub 发布了开源负载均衡组件 GitHub Load Balancer Director(GLB) Director,GLB 是 GitHub 针对裸机数据中心的可扩展负载均衡解决方案 ...
- .NET 开源免费图表组件库,Winform,WPF 通用
大家好, 我是等天黑, 今天给大家介绍一个功能完善, 性能强悍的图表组件库 ScottPlot, 当我第一次在 github 上看到这个库, 我看不懂,但我大受震撼, 这么好的项目当然要分享出来了. ...
最新文章
- Codeforces Beta Round #95 (Div. 2) 部分解题报告 (dp,组合数,)
- POJ 3046 Ant Counting(递推,和号优化)
- ArcMap导出属性表为Excel文件
- mysql中的get_lock锁机制解析
- 如何让apache支持.htaccess 解决Internal Server Error The server …错误
- leetcode98. 验证二叉搜索树
- 动态代理原理源码分析
- ERROR: Could not install packages due to an EnvironmentError: [Errno 13] 权限不够的解决办法
- Unity3D之Json序列化
- SAS安装时出现的问题:Diagram Control
- UI中经常出现的下拉框下拉自动筛选效果的实现
- React-pdf:pdf预览插件实践
- U盘插入电脑提示未能成功安装设备驱动程序,这个要怎么处理呢
- K8s中Secrets
- This may be due to a lack of SYSV IPC support
- 1.静态方法只能访问静态成员(包括变量和方法不能直接访问实例成员,除非使用对象调用2.实例方法既可以访问静态成员,也可以访问实例成员
- proc*c/c++简介
- hdu 4607 Park Visit(树上最长链)
- iOS 火星坐标相关整理及解决方案汇总
- 百度地图离线开发demo(热力图)