你的位置:首页 > ASP.net教程

[ASP.net教程]C#链接阿里云KVStore


一、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],不然有死循环就会造成内存溢出。