一、KVStore的简单介绍
阿里云KVStore兼容Redis。因为KVStore就相当于Redis的服务器端,我们代码只是当作客户端,链接上服务器端就行了,阿里云的KVStore详情文档见,https://docs.aliyun.com/#/pub/kvstore/key-value-store/kvstore-introduction。
二、C#客户端链接OCS
1.阿里云文档上介绍的是用ServiceStack去链接KVStore。那我们项目中就用nuget去下载ServiceStack包。nuget搜索ServiceStack,搜索到的结果如下图,安装图中标识的就可以了。这个应该是最新的V4版本,当提醒你需要用商业版的时候,可以去还原之前的V3版本,具体还原方法见,https://github.com/ServiceStackV3/ServiceStackV3。
nuget搜索结果如下:
2.安装好以后,写链接和调用kvstore的代码。其中_setting.AccessId, _setting.AccessKey, _setting.HostAddress,分别是KVStore的实例ID,链接密码和链接地址。
1 using ServiceStack.Redis; 2 //using ServiceStack.Text; 3 using ServiceStack.Common; 4 using System; 5 using System.Collections.Generic; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Web.Script.Serialization; 10 using Zupo.Core.Caching; 11 using System.Text.RegularExpressions; 12 13 14 namespace KVStore 15 { 16 public class KVStoreService 17 { 18 19 IKVStoreSetting _setting; 20 private IRedisClient redisClient; 21 private bool linkServer = true; 22 23 public KVStoreService(IKVStoreSetting setting) 24 { 25 try 26 { 27 this._setting = setting; 28 //连接池模式 29 //string[] testReadWriteHosts = new[] { 30 //string.Format("redis://:{0}:{1}@{2}:6379",_setting.AccessId,_setting.AccessKey,_setting.HostAddress)/*redis://:实例id:密码@访问地址:端口*/ 31 //}; 32 //RedisClientManagerConfig RedisConfig = new RedisClientManagerConfig(); 33 //RedisConfig.AutoStart = true; 34 //RedisConfig.MaxReadPoolSize = 60; 35 //RedisConfig.MaxWritePoolSize = 60; 36 ////RedisConfig.VerifyMasterConnections = false;//需要设置 37 ////PooledRedisClientManager redisPoolManager = new PooledRedisClientManager(10/*连接池个数*/, 10/*连接池超时时间*/, testReadWriteHosts); 38 //PooledRedisClientManager redisPoolManager = new PooledRedisClientManager(10/*连接池个数*/, 10/*连接池超时时间*/, testReadWriteHosts); 39 //redisClient = redisPoolManager.GetClient();//获取连接 40 ////RedisNativeClient redisNativeClient = (RedisNativeClient)redisClient; 41 ////redisNativeClient.Client = null;//KVStore不支持client setname所以这里需要显示的把client对象置为null 42 //var dbSize = redisClient.DbSize; 43 44 //单链接模式 45 //string host = _setting.HostAddress;/*访问host地址*/ 46 //string password = string.Format("{0}:{1}", _setting.AccessId, _setting.AccessKey);/*实例id:密码*/ 47 //redisClient = new RedisClient(host, 6379, password); 48 //var dbSize = redisClient.DbSize; 49 50 RedisClientManagerConfig RedisConfig = new RedisClientManagerConfig(); 51 RedisConfig.AutoStart = true; 52 RedisConfig.MaxReadPoolSize = 60; 53 RedisConfig.MaxWritePoolSize = 60; 54 RedisConfig.DefaultDb = 1; //默认第一个db 55 56 PooledRedisClientManager prcm = new PooledRedisClientManager(new List<string>() { string.Format("{0}:{1}@{2}:6379", _setting.AccessId, _setting.AccessKey, _setting.HostAddress) }, 57 new List<string>() { string.Format("{0}:{1}@{2}:6379", _setting.AccessId, _setting.AccessKey, _setting.HostAddress) }, RedisConfig); 58 redisClient = prcm.GetClient(); 59 } 60 catch (Exception) 61 { 62 linkServer = false; 63 } 64 } 65 66 /// <summary> 67 /// 是否处于链接状态 68 /// </summary> 69 protected bool LinkServer 70 { 71 get 72 { 73 return linkServer; 74 } 75 } 76 77 /// <summary> 78 /// 根据传入的key-value添加一条记录,当key已存在返回false 79 /// </summary> 80 /// <typeparam name="T"></typeparam> 81 /// <param name="key"></param> 82 /// <param name="value"></param> 83 /// <returns></returns> 84 protected bool Add<T>(string key, T value) 85 { 86 return redisClient.Add<T>(key, value); 87 } 88 89 /// <summary> 90 /// 根据传入的key-value添加一条记录,当key已存在返回false 91 /// </summary> 92 /// <typeparam name="T"></typeparam> 93 /// <param name="key"></param> 94 /// <param name="value"></param> 95 /// <param name="expiresIn">TimeSpan</param> 96 /// <returns></returns> 97 protected bool AddExpires<T>(string key, T value, TimeSpan expiresIn) 98 { 99 return redisClient.Add<T>(key, value, expiresIn);100 }101 102 /// <summary>103 /// 获取104 /// </summary>105 /// <typeparam name="T"></typeparam>106 /// <param name="key"></param>107 /// <returns></returns>108 protected T Get<T>(string key)109 {110 try111 {112 return redisClient.Get<T>(key);113 }114 catch(Exception ex)115 {116 throw ex;117 }118 }119 120 protected List<T> GetList<T>(string key)121 {122 return redisClient.Get<List<T>>(key);123 }124 125 /// <summary>126 /// 根据传入的多个key获取多条记录的值127 /// </summary>128 /// <typeparam name="T"></typeparam>129 /// <param name="keys"></param>130 /// <returns></returns>131 protected IDictionary<string, T> GetAll<T>(IEnumerable<string> keys)132 {133 return redisClient.GetAll<T>(keys);134 }135 136 /// <summary>137 /// 根据传入的key移除一条记录138 /// </summary>139 /// <param name="key"></param>140 /// <returns></returns>141 public void Remove(string key)142 {143 redisClient.Remove(key);144 }145 146 /// <summary>147 /// 根据传入的多个key移除多条记录148 /// </summary>149 /// <param name="keys"></param>150 protected void RemoveAll(IEnumerable<string> keys)151 {152 redisClient.RemoveAll(keys);153 }154 155 /// <summary>156 /// Removes items by pattern157 /// </summary>158 /// <param name="pattern">pattern</param>159 public void RemoveByPattern(string pattern)160 {161 var regex = new Regex(pattern, RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase);162 var keysToRemove = new List<String>();163 164 var allkeys = redisClient.GetAllKeys();165 foreach (var key in allkeys)166 if (regex.IsMatch(key))167 keysToRemove.Add(key);168 169 foreach (string key in keysToRemove)170 {171 Remove(key);172 }173 }174 175 176 /// <summary>177 /// 清空kv-store缓存178 /// </summary>179 /// <returns></returns>180 public void Clear()181 {182 var allkeys = redisClient.GetAllKeys();183 redisClient.RemoveAll(allkeys);184 }185 186 /// <summary>187 /// 根据传入的key覆盖一条记录的值,当key不存在不会添加188 /// </summary>189 /// <typeparam name="T"></typeparam>190 /// <param name="key"></param>191 /// <param name="value"></param>192 /// <returns></returns>193 protected bool Replace<T>(string key, T value)194 {195 return redisClient.Replace<T>(key, value);196 }197 198 /// <summary>199 /// 根据传入的key修改一条记录的值,当key不存在则添加 200 /// </summary>201 /// <typeparam name="T"></typeparam>202 /// <param name="key"></param>203 /// <param name="value"></param>204 /// <returns></returns>205 protected bool Set<T>(string key, T value)206 {207 try208 {209 return redisClient.Set<T>(key, value);210 }211 catch(Exception ex)212 {213 throw ex;214 }215 }216 217 protected bool Set<T>(string key, List<T> value)218 {219 try220 {221 JavaScriptSerializer jsonSerializer = new JavaScriptSerializer();222 //执行序列化223 string objectStr = jsonSerializer.Serialize(value);224 225 return redisClient.Set(key, value);226 }227 catch (Exception ex)228 {229 throw ex;230 }231 }232 233 /// <summary>234 /// 根据传入的key修改一条记录的值,当key不存在则添加235 /// </summary>236 /// <typeparam name="T"></typeparam>237 /// <param name="key"></param>238 /// <param name="value"></param>239 /// <param name="expiresIn">TimeSpan</param>240 /// <returns></returns>241 protected bool SetExpires<T>(string key, T value, TimeSpan expiresIn)242 {243 return redisClient.Set<T>(key, value, expiresIn);244 }245 246 /// <summary>247 /// 根据传入的多个key覆盖多条记录248 /// </summary>249 /// <typeparam name="T"></typeparam>250 /// <param name="values"></param>251 protected void SetAll<T>(IDictionary<string, T> values)252 {253 redisClient.SetAll<T>(values);254 }255 256 /// <summary>257 /// 判断Key在本数据库内是否已被使用(包括各种类型、内置集合等等)258 /// </summary>259 /// <param name="key"></param>260 /// <returns></returns>261 public bool Contains(string key)262 {263 return redisClient.ContainsKey(key);264 }265 266 /// <summary>267 /// 获取所有的Keys集合268 /// </summary>269 /// <returns></returns>270 protected List<string> GetAllKeys()271 {272 return redisClient.GetAllKeys();273 }274 275 /// <summary>276 /// 重命名一个Key,值不变277 /// </summary>278 /// <param name="fromName"></param>279 /// <param name="toName"></param>280 protected void RenameKey(string fromName, string toName)281 {282 redisClient.RenameKey(fromName, toName);283 }284 285 /// <summary>286 /// 清除本数据库的所有数据287 /// </summary>288 protected void FlushDb()289 {290 redisClient.FlushAll();291 }292 293 /// <summary>294 /// 根据Key获取当前存储的值是什么类型:295 /// </summary>296 /// <param name="key">None = 0 String = 1 List = 2 Set = 3 SortedSet = 4 Hash = 5</param>297 /// <returns></returns>298 protected RedisKeyType GetEntryType(string key)299 {300 return redisClient.GetEntryType(key);301 }302 303 /// <summary>304 /// 添加一个项到内部的List<T>305 /// </summary>306 /// <param name="listId"></param>307 /// <param name="value"></param>308 protected void AddItemToList(string listId, string value)309 {310 redisClient.AddItemToList(listId, value);311 }312 313 /// <summary>314 /// 添加一个项到内部的HashSet<T> 315 /// </summary>316 /// <param name="setId"></param>317 /// <param name="item"></param>318 protected void AddItemToSet(string setId, string item)319 {320 redisClient.AddItemToSet(setId, item);321 }322 323 /// <summary>324 /// 一次过将参数中的List<T>中的多个值添加入内部的List<T>325 /// </summary>326 /// <param name="listId"></param>327 /// <param name="values"></param>328 protected void AddRangeToList(string listId, List<string> values)329 {330 redisClient.AddRangeToList(listId, values);331 }332 333 /// <summary>334 /// 一次过将参数中的HashSet<T>中的多个值添加入内部的HashSet<T>335 /// </summary>336 /// <param name="setId"></param>337 /// <param name="items"></param>338 protected void AddRangeToSet(string setId, List<string> items)339 {340 redisClient.AddRangeToSet(setId, items);341 }342 343 /// <summary>344 /// 获取指定ListId的内部List<T>的所有值345 /// </summary>346 /// <param name="listId"></param>347 /// <returns></returns>348 protected List<string> GetAllItemsFromList(string listId)349 {350 return redisClient.GetAllItemsFromList(listId);351 }352 353 /// <summary>354 /// 获取指定SetId的内部HashSet<T>的所有值 355 /// </summary>356 /// <param name="setId"></param>357 /// <returns></returns>358 protected HashSet<string> GetAllItemsFromSet(string setId)359 {360 return redisClient.GetAllItemsFromSet(setId);361 }362 363 /// <summary>364 /// 根据ListId和下标获取一项365 /// </summary>366 /// <param name="listId"></param>367 /// <param name="listIndex"></param>368 /// <returns></returns>369 protected string GetItemFromList(string listId, int listIndex)370 {371 return redisClient.GetItemFromList(listId, listIndex);372 }373 }374 }
View Code
三、使用注意点
这个可以直接上传list和set等类型的数据,它也支持泛型方法,但因为网络传输肯定是要先序列化的,跟OCS一样的问题,所以我项目用的是EF,所以得先去忽略不需要序列化的字段和属性等,加上[IgnoreDataMember],不然有死循环就会造成内存溢出。
原标题:C#链接阿里云KVStore
关键词:C#