C#利用ServiceStack.Redis访问Redis    

Redis【REmote DIctionary Server】作为当前比较流行的NoSql数据库,以其高性能,高可用的的特点,应用越来越广泛,深得各大企业和开发人员的青睐。 本文主要以一个简单的小例子,简述ServiceStack.Redis动态库在Redis方面的相关应用,仅供学习分享使用,如有不足之处,还请指正。

概述

Redis【REmote DIctionary Server】作为当前比较流行的NoSql数据库,以其高性能,高可用的的特点,应用越来越广泛,深得各大企业和开发人员的青睐。 本文主要以一个简单的小例子,简述ServiceStack.Redis动态库在Redis方面的相关应用,仅供学习分享使用,如有不足之处,还请指正。

开发环境

相关开发环境,如下所示:

  • Microsoft Visual Studio Community 2019
  • ServiceStack.Redis 动态库
  • Redis 6.0.9 服务器端环境搭建

ServiceStack.Redis的安装

在C#开发中,主要通过NuGet包管理器,来安装ServiceStack.Redis动态库,目前版本为5.10.4,如下所示:

C#利用ServiceStack.Redis访问Redis_C#

 

示例截图

关于C#调用Redis相关示例截图,如下所示:

C#利用ServiceStack.Redis访问Redis_Redis_02

核心代码

关于Redis操作的核心代码,主要分两部分:Redis客户端管理类,Redis客户端操作类。

Redis客户端管理类,主要通过Redis客户端连接池【PooledRedisClientManager】创建客户端对象【IRedisClient】,如下所示:

C#利用ServiceStack.Redis访问Redis_C#_03C#利用ServiceStack.Redis访问Redis_C#_04

 1 using ServiceStack.Redis; 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Threading.Tasks; 7  8 namespace DemoRedis 9 {10     /// 11     /// Redis客户端管理类12     /// 13     public static class RedisManager14     {15         private static PooledRedisClientManager clientManager;16 17         /// 18         /// 初始化信息19         /// 20         private static void initInfo()21         {22             string ipaddr = System.Configuration.ConfigurationManager.AppSettings["ipaddr"];23             string port = System.Configuration.ConfigurationManager.AppSettings["port"];24             string host = string.Format("{0}:{1}", ipaddr, port);25             initInfo(new string[] { host }, new string[] { host });26         }27 28         /// 29         /// 初始化Redis客户端管理30         /// 31         /// 32         /// 33         private static void initInfo(string[] readWriteHosts, string[] readOnlyHosts)34         {35             clientManager = new PooledRedisClientManager(readWriteHosts, readOnlyHosts, new RedisClientManagerConfig36             {37                 MaxWritePoolSize = 5, // “写”链接池链接数 38                 MaxReadPoolSize = 5, // “读”链接池链接数 39                 AutoStart = true,40             });41         }42 43         public static IRedisClient getRedisClient()44         {45             if (clientManager == null)46             {47                 initInfo();48             }49             return clientManager.GetClient();50         }51 52     }53 54 55 }

View Code

Redis客户端操作类,主要包括字符串(String),列表(List),哈希结构(Hash),集合(Set),有序集合(Sorted Set)等相关操作功能的封装,如下所示:

C#利用ServiceStack.Redis访问Redis_C#_03C#利用ServiceStack.Redis访问Redis_C#_04

  1 using ServiceStack.Redis;  2 using System;  3 using System.Collections.Generic;  4 using System.Linq;  5 using System.Text;  6 using System.Threading.Tasks;  7   8 namespace DemoRedis  9 { 10     public class RedisHelper:IDisposable 11     { 12         private IRedisClient client; 13  14         public RedisHelper() 15         { 16  17         } 18  19         public RedisHelper(IRedisClient client ) { 20             this.client = client; 21         } 22  23         #region 字符串 24  25         public List<string> getAllKeys() 26         { 27             return this.client.GetAllKeys(); 28         } 29  30         ///  31         /// 设置值 32         ///  33         ///  34         ///  35         public void setString(string key,string value) 36         { 37             this.client.Set(key, value); 38         } 39  40         ///  41         /// 设置值,带过期时间 42         ///  43         ///  44         ///  45         ///  46         public void setString(string key, string value,TimeSpan expiresIn) 47         { 48             this.client.Set(key, value, expiresIn); 49         } 50  51         ///  52         /// 是否存在 53         ///  54         ///  55         ///  56         public bool containsKey(string key) 57         { 58             return this.client.ContainsKey(key); 59         } 60  61         ///  62         /// 设置字典 63         ///  64         ///  65         public void setAll(Dictionary<string,string> dic) 66         { 67             this.client.SetAll(dic); 68         } 69  70         ///  71         /// 返回旧值,设置新值 72         ///  73         ///  74         ///  75         ///  76         public string getAndSetValue(string key,string value) { 77            return this.client.GetAndSetValue(key, value); 78         } 79  80         ///  81         /// 获取对应的值 82         ///  83         ///  84         ///  85         public string getValue(string key) { 86             return this.client.GetValue(key); 87         } 88  89         public string getRandomKey() 90         { 91             return this.client.GetRandomKey(); 92         } 93  94         ///  95         /// 追加值到现有key中 96         ///  97         ///  98         ///  99         public void appendToValue(string key, string value) {100             this.client.AppendToValue(key, value);101         }102 103         #endregion104 105         #region List106 107         /// 108         /// (队列操作)增加一个值到列表109         /// 110         /// 111         /// 112         public void enqueueItemOnList(string listId ,string value)113         {114             this.client.EnqueueItemOnList(listId, value);115         }116 117         /// 118         /// 从队列中出一个119         /// 120         /// 121         /// 122         public string dequeueItemFromList(string listId)123         {124             return this.client.DequeueItemFromList(listId);125         }126 127         /// 128         /// 栈,增加一个值到列表129         /// 130         /// 131         /// 132         public void pushItemToList(string listId, string value) {133             this.client.PushItemToList(listId, value);134         }135 136         /// 137         /// 栈,从当前列表中出一个值,并返回138         /// 139         /// 140         /// 141         public string popItemFromList(string listId)142         {143             return this.client.PopItemFromList(listId);144         }145 146 147         /// 148         /// 获取某一个位置的值149         /// 150         /// 151         /// 152         /// 153         public string getItemFromList(string listId, int index)154         {155             return this.client.GetItemFromList(listId, index);156         }157 158         /// 159         /// 设置并修改指定位置的值160         /// 161         /// 162         /// 163         /// 164         public void setItemInList(string listId, int index,string value)165         {166             this.client.SetItemInList(listId, index, value);167         }168 169 170         /// 171         /// 获取列表所有的值172         /// 173         /// 174         /// 175         public List<string> getAllItemsFromList(string listId) {176             return this.client.GetAllItemsFromList(listId);177         }178 179         /// 180         /// 删除所有内容181         /// 182         /// 183         public void removeAllFromList(string listId) {184             this.client.RemoveAllFromList(listId);185         }186 187         /// 188         /// 删除列表指定元素189         /// 190         /// 191         /// 192         public void removeItemFromList(string listId, string value) {193             this.client.RemoveItemFromList(listId, value);194         }195 196         /// 197         /// 获取指定列表的长度198         /// 199         /// 200         /// 201         public long getListCount(string listId) {202             return this.client.GetListCount(listId);203         }204 205         #endregion206 207         #region Hash208 209         /// 210         /// 设置Hash的值211         /// 212         /// 213         /// 214         /// 215         /// 216         public bool setEntryInHash(string hashId, string key, string value)217         {218             return this.client.SetEntryInHash(hashId, key, value);219         }220 221         /// 222         /// 获取Hash中的值223         /// 224         /// 225         /// 226         /// 227         public string getValueFromHash(string hashId, string key)228         {229             return this.client.GetValueFromHash(hashId, key);230         }231 232         /// 233         /// 获取Hash列表中的所有内容234         /// 235         /// 236         public Dictionary<string,string> getAllEntriesFromHash(string hashId)237         {238             return this.client.GetAllEntriesFromHash(hashId);239         }240 241         /// 242         /// 判断Hash是否存在指定的键243         /// 244         /// 245         /// 246         /// 247         public bool hashContainsEntry(string hashId, string key)248         {249             return this.client.HashContainsEntry(hashId, key);250         }251 252         /// 253         /// 设置多个值到Hash254         /// 255         /// 256         /// 257         public void setRangeInHash(string hashId,Dictionary<string,string> keyValuePairs) {258             this.client.SetRangeInHash(hashId, keyValuePairs);259         }260 261         /// 262         /// 获取Hash列表的长度263         /// 264         /// 265         /// 266         public long getHashCount(string hashId) {267             return this.client.GetHashCount(hashId);268         }269 270         /// 271         /// 删除某一个值272         /// 273         /// 274         /// 275         /// 276         public bool removeEntryFromHash(string hashId,string key) {277             return this.client.RemoveEntryFromHash(hashId, key);278         }279       280         #endregion281 282         #region Set283 284         /// 285         /// 从Set中获取随机值286         /// 287         /// 288         /// 289         public string getRandomItemFromSet(string setId)290         {291             return this.client.GetRandomItemFromSet(setId);292         }293 294         /// 295         /// 获取所有的值296         /// 297         /// 298         /// 299         public HashSet<string> getAllItemsFromSet(string setId)300         {301            return this.client.GetAllItemsFromSet(setId);302         }303 304         /// 305         /// 获取set的长度306         /// 307         /// 308         /// 309         public long getSetCount(string setId)310         {311             return this.client.GetSetCount(setId);312         }313 314         /// 315         /// 删除某一项316         /// 317         /// 318         /// 319         public void removeItemFromSet(string setId,string item) {320             this.client.RemoveItemFromSet(setId, item);321         }322 323         /// 324         /// 新增内容325         /// 326         /// 327         /// 328         public void addItemToSet(string setId, string item) {329             this.client.AddItemToSet(setId, item);330         }331 332         /// 333         /// 增加列表到Set334         /// 335         /// 336         /// 337         public void addRangeToSet(string setId,List<string> items) {338             this.client.AddRangeToSet(setId, items);339         }340 341         #endregion342 343         #region zset344 345         /// 346         /// 添加元素到排序集合347         /// 348         /// 349         /// 350         /// 351         public bool addItemToSortedSet(string setId,string value) {352             return this.client.AddItemToSortedSet(setId, value);353         }354 355         /// 356         /// 添加元素到排序集合357         /// 358         /// 359         /// 360         /// 361         /// 362         public bool addItemToSortedSet(string setId, string value,double score)363         {364             return this.client.AddItemToSortedSet(setId, value,score);365         }366 367         /// 368         /// 增加列表到排序集合369         /// 370         /// 371         /// 372         /// 373         /// 374         public bool addRangeToSortedSet(string setId,List<string> values, double score) {375            return  this.client.AddRangeToSortedSet(setId, values, score);376         }377 378         /// 379         /// 增加列表到排序集合380         /// 381         /// 382         /// 383         /// 384         /// 385         public bool addRangeToSortedSet(string setId, List<string> values, long score)386         {387             return this.client.AddRangeToSortedSet(setId, values, score);388         }389 390         /// 391         /// 获取所有的集合内容392         /// 393         /// 394         /// 395         public List<string> getAllItemsFromSortedSet(string setId) {396             return this.client.GetAllItemsFromSortedSet(setId);397         }398 399         /// 400         /// 倒序获取所有的内容401         /// 402         /// 403         /// 404         public List<string> getAllItemsFromSortedSetDesc(string setId) {405             return this.client.GetAllItemsFromSortedSetDesc(setId);406         }407 408         /// 409         /// 带分数一起取出410         /// 411         /// 412         /// 413         public IDictionary<string, double> getAllWithScoresFromSortedSet(string setId)414         {415             return this.client.GetAllWithScoresFromSortedSet(setId);416         }417 418         /// 419         /// 获取对应值的位置420         /// 421         /// 422         /// 423         /// 424         public long getItemIndexInSortedSet(string setId,string value)425         {426             return this.client.GetItemIndexInSortedSet(setId, value);427         }428 429         /// 430         /// 倒序的位置431         /// 432         /// 433         /// 434         /// 435         public long getItemIndexInSortedSetDesc(string setId, string value) {436            return this.client.GetItemIndexInSortedSetDesc(setId, value);437         }438 439         /// 440         /// 获取对应元素的分数441         /// 442         /// 443         /// 444         /// 445         public double getItemScoreInSortedSet(string setId, string value) {446             return this.client.GetItemScoreInSortedSet(setId, value);447         }448 449         /// 450         /// 451         /// 452         /// 453         /// 454         /// 455         /// 456         public List<string> getRangeFromSortedSet(string setId, int fromRank, int toRank) {457            return  this.client.GetRangeFromSortedSet(setId, fromRank, toRank);458         }459 460         public IDictionary<string, double> getRangeWithScoresFromSortedSet(string setId, int fromRank, int toRank) {461             return this.client.GetRangeWithScoresFromSortedSet(setId, fromRank, toRank);462         }463 464         public void Dispose()465         {466             if(this.client != null)467             {468                 this.client.Dispose();469             }470         }471         #endregion472     }473 }

View Code

关于前端调用功能,主要是各个按钮对应的事件,如下所示:

C#利用ServiceStack.Redis访问Redis_C#_03C#利用ServiceStack.Redis访问Redis_C#_04

  1 using System;  2 using System.Collections.Generic;  3 using System.ComponentModel;  4 using System.Data;  5 using System.Drawing;  6 using System.Linq;  7 using System.Text;  8 using System.Threading.Tasks;  9 using System.Windows.Forms; 10  11 namespace DemoRedis 12 { 13     public partial class FrmMain : Form 14     { 15  16         private RedisHelper redisHelper; 17  18         public FrmMain() 19         { 20             InitializeComponent(); 21         } 22  23         ///  24         /// 加载 25         ///  26         ///  27         ///  28         private void FrmMain_Load(object sender, EventArgs e) 29         { 30             this.redisHelper = new RedisHelper(RedisManager.getRedisClient()); 31         } 32  33         ///  34         /// 获取所有的Key 35         ///  36         ///  37         ///  38         private void btnAllKey_Click(object sender, EventArgs e) 39         { 40             List<string> keys = this.redisHelper.getAllKeys(); 41             this.combKeys.Items.AddRange(keys.ToArray()); 42             this.combKeys.SelectedIndex = 0; 43         } 44  45         private void btnSetString_Click(object sender, EventArgs e) 46         { 47             string key = this.txtKey1.Text; 48             string value = this.txtValue1.Text; 49             if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) 50             { 51                 return; 52             } 53             this.redisHelper.setString(key, value); 54             MessageBox.Show("设置成功"); 55         } 56  57         private void btnGetString_Click(object sender, EventArgs e) 58         { 59             string key = this.txtKey2.Text; 60             if (string.IsNullOrEmpty(key)) 61             { 62                 return; 63             } 64             string value = this.redisHelper.getValue(key); 65             if (string.IsNullOrEmpty(value)) { 66                 MessageBox.Show("读取失败,值为空"); 67             } 68             else 69             { 70                 this.txtValue2.Text = value; 71             } 72         } 73  74         private void btnAppend_Click(object sender, EventArgs e) 75         { 76             string key = this.txtKey3.Text; 77             string value = this.txtValue3.Text; 78             if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value)) { 79                 return; 80             } 81             this.redisHelper.appendToValue(key, value); 82             MessageBox.Show("追加成功"); 83         } 84  85         private void btnAddItemToHash_Click(object sender, EventArgs e) 86         { 87             string hashId = this.txtHashId1.Text; 88             string attr = this.txtHashAttr1.Text; 89             string value = this.txtHashVal1.Text; 90             if (string.IsNullOrEmpty(hashId) || string.IsNullOrEmpty(attr) || string.IsNullOrEmpty(value)) 91             { 92                 return; 93             } 94             if (this.redisHelper.setEntryInHash(hashId, attr, value)) 95             { 96                 MessageBox.Show("设置成功"); 97             } 98             else { 99                 MessageBox.Show("设置失败");100             }101         }102 103         private void btnGetItemFromHash_Click(object sender, EventArgs e)104         {105             string hashId = this.txtHashId2.Text;106             string attr = this.txtHashAttr2.Text;107             if (string.IsNullOrEmpty(hashId) || string.IsNullOrEmpty(attr) )108             {109                 return;110             }111             string value = this.redisHelper.getValueFromHash(hashId, attr);112             if (string.IsNullOrEmpty(value))113             {114                 MessageBox.Show("获取失败");115             }116             else117             {118                 this.txtHashVal2.Text = value;119             }120         }121 122         private void btnGetHashCount_Click(object sender, EventArgs e)123         {124             string hashId = this.txtHashId3.Text;125             if (string.IsNullOrEmpty(hashId))126             {127                 return;128             }129             long count = this.redisHelper.getHashCount(hashId);130             if (count > 0)131             {132                 MessageBox.Show("长度为:" + count);133             }134             else {135                 MessageBox.Show("获取失败");136             }137         }138 139         private void btnHashContainsEntry_Click(object sender, EventArgs e)140         {141             string hashId = this.txtHashId3.Text;142             string attr = this.txtHashAttr3.Text;143             if (string.IsNullOrEmpty(hashId) || string.IsNullOrEmpty(attr))144             {145                 return;146             }147             bool flag =  this.redisHelper.hashContainsEntry(hashId, attr);148             if (flag) {149                 MessageBox.Show("存在");150             }151             else152             {153                 MessageBox.Show("不存在");154             }155         }156 157         private void btnRemoveEntryFromHash_Click(object sender, EventArgs e)158         {159             string hashId = this.txtHashId3.Text;160             string attr = this.txtHashAttr3.Text;161             if (string.IsNullOrEmpty(hashId) || string.IsNullOrEmpty(attr))162             {163                 return;164             }165             bool flag = this.redisHelper.removeEntryFromHash(hashId, attr);166             if (flag)167             {168                 MessageBox.Show("删除成功");169             }170             else171             {172                 MessageBox.Show("删除失败");173             }174         }175 176         private void btnEnqueueItemToList_Click(object sender, EventArgs e)177         {178             string listId = this.txtListId1.Text;179             string item = this.txtListItem1.Text;180             if (string.IsNullOrEmpty(listId) || string.IsNullOrEmpty(item))181             {182                 return;183             }184             this.redisHelper.enqueueItemOnList(listId, item);185             MessageBox.Show("入队成功");186         }187 188         private void btnPushItemToList_Click(object sender, EventArgs e)189         {190             string listId = this.txtListId2.Text;191             string item = this.txtListItem2.Text;192             if (string.IsNullOrEmpty(listId) || string.IsNullOrEmpty(item))193             {194                 return;195             }196             this.redisHelper.pushItemToList(listId, item);197             MessageBox.Show("入栈成功");198         }199 200         private void btnGetItemFromList_Click(object sender, EventArgs e)201         {202             string listId = this.txtListId3.Text;203             string index =  this.txtListIndex3.Text;204             if (string.IsNullOrEmpty(listId) || string.IsNullOrEmpty(index))205             {206                 return;207             }208             string value = this.redisHelper.getItemFromList(listId, int.Parse(index));209             if (string.IsNullOrEmpty(value))210             {211                 MessageBox.Show("值为:" + value);212             }213             else214             {215                 MessageBox.Show("获取失败");216             }217         }218 219         private void btnRemoveItemFromList_Click(object sender, EventArgs e)220         {221             string listId = this.txtListId4.Text;222             string item = this.txtListItem4.Text;223             if (string.IsNullOrEmpty(listId) || string.IsNullOrEmpty(item))224             {225                 return;226             }227             this.redisHelper.removeItemFromList(listId, item);228             MessageBox.Show("删除成功");229         }230 231         private void btnAddItemToSet_Click(object sender, EventArgs e)232         {233             string setId = this.txtSetId1.Text;234             string item = this.txtSetItem1.Text;235             if (string.IsNullOrEmpty(setId) || string.IsNullOrEmpty(item))236             {237                 return;238             }239             this.redisHelper.addItemToSet(setId, item);240             MessageBox.Show("添加成功");241         }242 243         private void btnGetSetCount_Click(object sender, EventArgs e)244         {245             string setId = this.txtSetId1.Text;246             if (string.IsNullOrEmpty(setId))247             {248                 return;249             }250             long count = this.redisHelper.getSetCount(setId);251             if (count > 0)252             {253                 MessageBox.Show("长度为:" + count);254             }255             else256             {257                 MessageBox.Show("获取失败");258             }259         }260 261         private void btnAddItemToSortSet_Click(object sender, EventArgs e)262         {263             string setId = this.txtZsetId1.Text;264             string item = this.txtZsetItem1.Text;265             if (string.IsNullOrEmpty(setId) || string.IsNullOrEmpty(item))266             {267                 return;268             }269             bool flag = this.redisHelper.addItemToSortedSet(setId, item);270             if (flag)271             {272                 MessageBox.Show("添加成功");273             }274             else275             {276                 MessageBox.Show("添加失败");277             }278         }279 280         private void btnGetScoreByValue_Click(object sender, EventArgs e)281         {282             string setId = this.txtZsetId2.Text;283             string item = this.txtZsetItem2.Text;284             if (string.IsNullOrEmpty(setId) || string.IsNullOrEmpty(item))285             {286                 return;287             }288             double score = this.redisHelper.getItemScoreInSortedSet(setId, item);289             MessageBox.Show("分数为:" + score);290         }291 292         private void btnAddItemWithScoreToZset_Click(object sender, EventArgs e)293         {294             string setId = this.txtZsetId2.Text;295             string item = this.txtZsetItem2.Text;296             string score = this.txtZsetScore2.Text;297             if (string.IsNullOrEmpty(setId) || string.IsNullOrEmpty(item) || string.IsNullOrEmpty(score))298             {299                 return;300             }301             bool flag = this.redisHelper.addItemToSortedSet(setId, item,double.Parse(score));302             if (flag)303             {304                 MessageBox.Show("添加成功");305             }306             else307             {308                 MessageBox.Show("添加失败");309             }310         }311     }312 }

View Code

 

注意事项

如果在Redis服务端和客户端不在同一个电脑上,可能会出现无法访问的情况,前端报连接超时错误。则可能是服务端防火墙限制。需要执行如下命令即可:

1 [root@localhost bin]# /sbin/iptables -I INPUT -p tcp --dport 6379 -j ACCEPT

另外Redis.conf配置文件中,关于bind配置,默认bind为127.0.0.1只允许本机访问,需要修改,如下所示:

1 # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~2 bind 127.0.0.1 192.168.127.131

其中:192.168.127.131 为服务器IP地址。