一、引言
今天开始有关Redis学习的第九篇文章了,以后肯定会大量系统使用Redis作为缓存介质,为了更好的更好的Redis,自己写了两个工具类,但是这两个工具类,没有提供一致的接口,是为了使用的独立性。测试已经完毕,可以正常访问Windows和Linux版本上的Redis服务,各种操作也没问题。今天就把主要代码贴出来,因为有一部分是需要配置文件的,我自己独立写了一套配置系统,这套配置系统就不贴出来,大家可以根据自己的理解来写这个部分的内容,好了,开始我们今天的写作吧。
二、简介
我写了两个工具类,第一个是以【StackExchange.Redis】为实现技术的Redis的客户端工具类,另一个是以【ServiceStack.Redis】为实现技术的Redis客户端工具类。【ServiceStack.Redis】的官网主页:https://servicestack.net/redis,【ServiceStack.Redis】在github上的主页:https://github.com/ServiceStack/ServiceStack.Redis,【ServiceStack.Redis】和Visual Studio 2015整个也很方便,微软在这块做的的很不过,我们可以通过命令直接安装:@H_502_17@Install-Package ServiceStack.Redis,当然我们也可以通过NuGet来安装,安装完成,在您项目的【引用】里面会生成四个dll,分别是:ServiceStack.Common,ServiceStack.Interfaces,ServiceStack.Redis,ServiceStack.Client 四个程序集,然后在项目中使用Using引入就可以正常使用了。【ServiceStack.Redis】是Redis官方推荐的C#客户端,性能非常优越,使用也很方便,但是从v4版本已经逐渐商业化了,目的可以想而知,嗨,都是钱惹的祸。
上面我说道了,【ServiceStack.Redis】后来就商业化了,我想了想光靠他也是不行了,还要在写一个版本的工具类,所以就选择了【StackExchange.Redis】,【StackExchange.Redis】也是开源的,到目前,一直都是开源的,它的地址是:https://github.com/StackExchange/StackExchange.Redis,我使用的是.net 4.5,工具采用 vs2015, StackExchange.Redis版本是1.0.488。工具类还会在持续的使用过程中,我还会更新和修改的。
三、实例代码
这是Redis客户端的配置文件的格式,格式很简单,可以分开配置,也可以合在一起配置。代码中标红的是和我的配置系统有关的代码,大家请注意。
<configuration> <configSections> <section name="Framework" type=Enterprise.Framework.Configuration.ConfigurationFrameworkSectionHandler,Enterprise.Framework.Configuration" /> </configSections> <Framework type=Enterprise.Framework.Configuration.ConfigurationFrameworkManager,1)">"> <Enterprise.Framework.Nosql> <RedisClients> <RedisClient name=ServiceStack" technology=ServiceStack.Redis"> <readWriteHosts>192.168.3.11:6379,6380</readWriteHosts> <!--<readOnlyHosts>可以省略该项</readOnlyHosts>--> <!--<maxWritePoolSize>可以省略该项</maxWritePoolSize>--> <!--<maxReadPoolSize>可以省略该项</maxReadPoolSize>--> <!--<password>可以省略该项</password>--> <!--<autoStart>可以省略该项</autoStart>--> </RedisClient> <RedisClient name=StackExchangeStackExchange.Redis"> <host>131.1:6379</host> <!--<password>可以省略该项</password>--> </RedisClient> </RedisClients> </Enterprise.Framework.Nosql> </Framework> </configuration>
1、这是以【ServiceStack.Redis】为实现技术的工具类,对外界的访问接口提供了2个,第一个是以配置文件中自定义的名称参数的,红色代码是和我独立的配置系统相关联的,另一个访问接口是以配置实体类参数的,代码很简单,不多说了。
工具类:ServiceStackRedisClientProvider.cs
1 /// <summary> 2 /// 通过ServiceStack.Redis实现的Redis的客户端操作类型 3 </summary> 4 public sealed class ServiceStackRedisClientProvider 5 { 6 #region 私有变量 7 8 //线程同步变量 9 private static readonly object lockObject = new object(); 10 11 redis链接池管理对象 12 volatile PooledRedisClientManager _instance = null; 13 14 配置文件里面的ServiceStack详细配置设置 15 static ServiceStackDetails _serviceStackDetails; 16 17 可以自行配置ServiceStack的配置对象 18 ServiceStackConfigEntry _serviceStackConfigEntry; 19 20 #endregion 21 22 #region 私有构造函数 23 24 25 私有构造函数,禁止外部通过new关键字来创建该对象实例 26 27 private ServiceStackRedisClientProvider() { } 28 29 30 31 #region 获取PooledRedisClientManager实例的方法 32 33 34 获取redis链接池管理对象实例 35 实例发生变化的集中情况: 36 1.实例为空 37 2.配置文件发生变化 38 39 <param name="startByConfigFile">这是一个布尔值,true表示根据配置文件的配置启动,false表示是根据配置对象启动</param> 40 <returns>返回PooledRedisClientManager类型的对象实例</returns> 41 static PooledRedisClientManager GetInstance(bool startByConfigFile) 42 { 43 if (_instance == ) 44 { 45 lock (lockObject) 46 { 47 48 { 49 string[] readWriteServerList= 50 string[] readOnlyServerList= 51 RedisClientManagerConfig managerConfig= 52 53 根据我们配置文件中数据来设置启动信息(app.config或者web.config) 54 if (startByConfigFile && (_serviceStackDetails != )) 55 { 56 managerConfig = new RedisClientManagerConfig() 57 { 58 AutoStart = _serviceStackDetails.AutoStart, 59 MaxReadPoolSize = _serviceStackDetails.MaxReadPoolSize,1)"> 60 MaxWritePoolSize = _serviceStackDetails.MaxWritePoolSize,1)"> 61 }; 62 63 readWriteServerList = GetRedisHosts(_serviceStackDetails.ReadWriteHosts); 64 readOnlyServerList = GetRedisHosts(_serviceStackDetails.ReadOnlyHosts); 65 } 66 else if (!startByConfigFile && (_serviceStackConfigEntry != null))根据配置对象来设置启动信息(ServiceStackConfigEntry) 67 68 managerConfig = 69 70 AutoStart = _serviceStackConfigEntry.AutoStart,1)"> 71 MaxReadPoolSize = _serviceStackConfigEntry.MaxReadPoolSize,1)"> 72 MaxWritePoolSize = _serviceStackConfigEntry.MaxWritePoolSize,1)"> 73 74 75 readWriteServerList = GetRedisHosts(_serviceStackConfigEntry.ReadWriteHosts); 76 readOnlyServerList = GetRedisHosts(_serviceStackConfigEntry.ReadOnlyHosts); 77 78 else 79 80 throw new InvalidOperationException(Redis客户端初始化配置失败!"); 81 82 83 if ((readWriteServerList != null && readWriteServerList.Length > 0)&&(readOnlyServerList != null && readOnlyServerList.Length <= 0 84 85 _instance = PooledRedisClientManager(readWriteServerList); 86 87 88 0) && (readOnlyServerList != null && readOnlyServerList.Length > 89 90 _instance = PooledRedisClientManager(readWriteServerList,readOnlyServerList,managerConfig); 91 92 } 93 } 94 } 95 return _instance; 96 } 97 98 99 解析Redis服务器列表,该列表格式IP[:Port] 100 101 <param name="redisHosts">包含一个或者多个Redis服务器地址的字符串列表,以逗号做为分隔符102 返回Redis服务器地址列表103 string[] GetRedisHosts(string redisHosts) 104 105 if (string.IsNullOrWhiteSpace(redisHosts) || .IsNullOrEmpty(redisHosts)) 106 107 return [] { }; 108 109 var hosts=redisHosts.Split(','110 foreach (var host in hosts) 111 112 if (!Regex.IsMatch(host,1)">@"^(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9]):\d{3,4}$113 114 Redis服务器地址格式不正确!115 116 117 hosts; 118 119 120 121 122 #region 提供对外访问接口 123 124 125 获取Redis客户端对象实例 126 127 <param name="redisClientName">在配置文件中,Redis客户端的名称128 <param name="databaseIndex">redis逻辑分为16个数据库,排序为:0-15,我们默认使用的是0号数据库,数据库当前的索引值129 返回IRedisClient对象实例130 static IRedisClient GetRedisClient(string redisClientName,int databaseIndex = 131 132 获取配置数据 133 ParameterValidityChecker.requiredParameterStringNotNullOrWhiteSpace(redisClientName,1)">Redis客户端的名称不能为空!134 var _configurationManager = (ConfigurationFrameworkManager)ConfigurationManager.GetSection("Framework"); 135 if (_configurationManager != 136 137 _serviceStackDetails = _configurationManager.RedisClientConfiguration.GetServiceStackDetails(redisClientName); 138 if (_serviceStackDetails == 139 140 以ServiceStack.Redis为实现技术的Redis客户端的配置有误!141 142 143 144 145 146 147 148 实例化Redis客户端实例对象 149 var pooledRedisClientManager = GetInstance(true150 var redisClient = pooledRedisClientManager.GetClient(); 151 if (!.IsNullOrEmpty(_serviceStackDetails.Password)) 152 153 redisClient.Password = _serviceStackDetails.Password; 154 155 redisClient.Db = databaseIndex; 156 redisClient; 157 158 159 160 161 162 <param name="serviceStackConfigEntry">163 164 165 static IRedisClient GetRedisClient(ServiceStackConfigEntry serviceStackConfigEntry,1)">166 167 168 if (serviceStackConfigEntry == 169 170 new ArgumentNullException(以ServiceStack.Redis为实现技术的Redis客户端的配置对象不能为空!171 172 173 174 _serviceStackConfigEntry = serviceStackConfigEntry; 175 176 177 string.IsNullOrEmpty(_serviceStackConfigEntry.ReadWriteHosts) || .IsNullOrWhiteSpace(_serviceStackConfigEntry.ReadWriteHosts)) 178 179 【ReadWriteHosts】必须设置其值!180 181 182 183 false184 185 string.IsNullOrEmpty(_serviceStackConfigEntry.Password)&&!.IsNullOrWhiteSpace(_serviceStackConfigEntry.Password)) 186 187 redisClient.Password = _serviceStackConfigEntry.Password; 188 189 redisClient.Db =190 191 192 193 194 }
配置实体类 ServiceStackConfigEntry.cs的代码:
1 2 配置文件中,以ServiceStack.Redis为实现技术的配置Redis的详情 3 4 ServiceStackConfigEntry 5 6 #region 构造函数 7 8 9 给配置参数初始化默认值 10 11 public ServiceStackConfigEntry() 12 13 ReadWriteHosts = 127.0.0.1:637914 ReadOnlyHosts = .Empty; 15 MaxWritePoolSize = 20016 MaxReadPoolSize = 17 Password = 18 AutoStart = 19 20 21 22 23 #region 配置属性 24 25 26 可读可写的Redis服务器地址,多个地址以逗号分隔,例如:192.168.127.11:6379,192.168.127.128:6380 27 28 string ReadWriteHosts { get; set; } 29 30 31 只能读的Redis服务器地址,多个地址以逗号分隔,例如:192.168.127.11:6379,1)">32 33 string ReadOnlyHosts { 34 35 36 最大写链接数 37 38 int MaxWritePoolSize { 39 40 41 最大读链接数 42 43 int MaxReadPoolSize { 44 45 46 登陆Redis服务器的密码 47 48 string Password { 49 50 51 是否自动启动 52 53 bool AutoStart { 54 55 56 }
获取配置文件详情的类型:ServiceStackDetails.cs
<summary> 配置文件中,以ServiceStack.Redis为实现技术的配置Redis的详情 </summary> ServiceStackDetails { #region 构造函数 <summary> 给配置参数初始化默认值 </summary> ServiceStackDetails() { ReadWriteHosts = ; ReadOnlyHosts = .Empty; MaxWritePoolSize = ; MaxReadPoolSize = ; Password = .Empty; AutoStart = ; } #endregion #region 配置属性 internal ; } 最大写链接数 最大读链接数 登陆Redis服务器的密码 是否自动启动 ; } #endregion }
2、这是以【StackExchange.Redis】为实现技术的工具类,对外界的访问接口提供了2个,第一个是以配置文件中自定义的名称参数的,红色代码是和我独立的配置系统相关联的,另一个访问接口是以配置实体类参数的,代码很简单,不多说了。
工具类: StackExchangeRedisClientProvider.cs
通过StackExchange.Redis实现的Redis的客户端操作类型 StackExchangeRedisClientProvider #region 私有字段 8 9 线程同步变量 10 12 13 14 redis链接池管理对象 15 16 volatile ConnectionMultiplexer _instance; 17 18 19 日志记录器 20 21 readonly ILog _log = LogManager.GetLogger(typeof(StackExchangeRedisClientProvider)); 22 23 StackExchangeDetails _stackExchangeDetails; 24 25 StackExchangeConfigEntry _stackExchangeConfigEntry; 26 31 32 私有构造函数,禁止不允许通过new 来实例化该对象 34 StackExchangeRedisClientProvider() { } 35 36 37 38 #region 获取Redis客户端实例 39 41 使用一个静态属性来返回已连接的实例 42 实例发生变化的几种情况: 43 44 2.连接关闭 45 3.文件发生变化时 46 47 48 返回ConnectionMultiplexer类型的对象实例 49 static ConnectionMultiplexer GetInstance( 50 51 if (startByConfigFile) 52 53 GetRedisHosts(_stackExchangeDetails.Hosts); 54 55 56 GetRedisHosts(_stackExchangeConfigEntry.Hosts); 58 59 60 null || !_instance.IsConnected) 62 63 64 68 _instance = ConnectionMultiplexer.Connect(_stackExchangeDetails.Hosts); 70 71 72 _instance = ConnectionMultiplexer.Connect(_stackExchangeConfigEntry.Hosts); 74 75 76 77 _instance.ErrorMessage += MuxerErrorMessage; 78 _instance.HashSlotMoved += MuxerHashSlotMoved; 79 _instance.InternalError += MuxerInternalError; 80 _instance.ConnectionFailed += MuxerConnectionFailed; 81 _instance.ConnectionRestored += MuxerConnectionRestored; 82 _instance.ConfigurationChanged += MuxerConfigurationChanged; 83 85 86 87 解析Redis服务器列表,该列表格式IP:Port 88 89 90 void GetRedisHosts( 92 94 95 96 var hosts = redisHosts.Split( 97 98 99 100 101 102 103 105 106 107 108 109 110 111 <returns></returns> 112 static IDatabase GetRedisClient(int databaseIndex =114 115 ParameterValidityChecker.requiredParameterStringNotNullOrWhiteSpace(redisClientName,1)">116 119 _stackExchangeDetails = _configurationManager.RedisClientConfiguration.GetStackExchangeDetails(redisClientName); 120 if (_stackExchangeDetails == 121 122 以StackExchange.Redis为实现技术的Redis客户端的配置有误!123 124 125 126 127 128 129 130 131 var instance = GetInstance( instance.GetDatabase(databaseIndex); 133 134 135 136 137 138 <param name="stackExchangeConfigEntry">StackExchange配置对象139 140 141 static IDatabase GetRedisClient(StackExchangeConfigEntry stackExchangeConfigEntry,1)">144 if (stackExchangeConfigEntry == 145 146 以StackExchange.Redis为实现技术的Redis客户端的配置对象不能为空!147 149 150 _stackExchangeConfigEntry = stackExchangeConfigEntry; 151 152 153 string.IsNullOrEmpty(_stackExchangeConfigEntry.Hosts) || .IsNullOrWhiteSpace(_stackExchangeConfigEntry.Hosts)) 155 【Hosts】必须设置其值!156 157 158 159 160 161 162 163 164 }
配置实体类:StackExchangeConfigEntry.cs
配置文件中,以StackExchange.Redis为实现技术的配置Redis的详情 StackExchangeConfigEntry StackExchangeConfigEntry() 13 Hosts = 14 Password = 15 16 17 18 19 21 22 Redis服务器地址,多个地址以逗号分隔,例如:192.168.127.11:6379,1)">23 24 string Hosts { 25 28 29 30 31 32 }
根据配置信息获取数据的类型:StackExchangeDetails.cs
StackExchangeDetails StackExchangeDetails() Redis服务器的主机地址,如果多个地址则以逗号分隔,格式:127.0.0.1:6379,127.0.0.1:6380 string Hosts{ 32 }
四、结束
好了,今天就写到这里了,先说明一下,这两个类暂时没有提供统一的接口,看以后的需要吧,如果有需要,我在重构。StackExchangeDetails 和 ServiceStackDetails 这两个类在这个 Enterprise.Framework.Configuration 命名空间,配置的系统暂时就不贴代码了,代码很多,其他的类型都在 Enterprise.Framework.Nosql.RedisClient 这个命名空间下边。