摘要


  上一篇讲述了安装redis客户端和服务器端,也大体地介绍了一下redis。本篇着重讲解.NET4.0 和 .NET4.5中如何使用redis和C# redis操作哈希表。并且会将封装的一些代码贴一下。在讲解的过程中,我打算结合redis操作命令一起叙述,算是作为对比吧。这样也能让读者清楚了 解,所分装的代码对应的redis的哪一些操作命令。

hash哈希表简介


  这里仅仅是对哈希表作简单概念级介绍(摘自csdn),如果需要,自己去研究。

1、哈希表的概念

  哈希表(Hash Table)也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构。它通过把关键码值映射到哈希表中的一个位置来访问记录,以加快查找的速度。这个映射函数就做散列函数,存放记录的数组叫做散列表。

2、哈希表查找的时间复杂度

  哈希表存储的是键值对,其查找的时间复杂度与元素数量多少无关,哈希表在查找元素时是通过计算哈希码值来定位元素的位置从而直接访问元素的,因此,哈希表查找的时间复杂度为O(1)。

如何在.NET4.0/4.5中安装redis组件?


  在上一篇博文中,安装好的redis服务器端,要记得开启服务。然后再在.NET4.5(.NET4.0同理)项目中添加对redis操作的dll文件的引用。引用的步骤如下:

第一步:右键项目中的引用,选择“管理NuGet程序包”;

第二步:在搜索栏中输入“Redis client for the Redis NoSQL DB”,联机查找;如下图:

  联机搜索结构中的第一个(如上图红色区域的组件,其版本号为4.0.35)就是要安装的组件了。接下来我们就继续点击“安装”按钮,进入下载组件,等下载完成后,继续选择“接受条款”,然后继续安装。安装过程中会出现下图情况:

   这句红色错误的意思是我们安装的ServiceStack.Interfaces 4.0.35版本与当前的.NET4.5框架中组件不兼容。这说明我们需要降低或是提高.NET版本解决此问题。我安装的是.NET4.5,所以我只能降 低版本。降低.NET版本的方法大家应该都知道的。我就在累述一次,希望大家不要嫌烦,毕竟还有新手在。方法:右键项目文件选择“属性”==》“应用程 序”==》“目标框架”,然后选择各个版本去尝试之前的两步操作,直到可以安装为止。

   我试过了,.NET4.0也会遇到同样问题,直到.NET3.5才可以。当然此时安装的ServiceStack.Interfaces 版本是1.0.0.0 ,这样我们再把.NET版本恢复4.5即可使用了。,其实是变相在.NET4.0/4.5下使用redis客户端。不知道各位有没有遇到这样的问题,还是 直接拷贝别人的dll文件。当自己亲自去操作的时候,才会发现,其实就算是安装一个组件都可能会出现各种各样的问题。所以,要想了解全过程的话,我们还是 要身体力行的啊。好了,这样就说明在.NET4.5下安装好了redis client了。

实战:在项目中运用redis代码详解


  这部分主要是讲解怎样连接到redis服务器。其中包含很多配置,我就用代码去说明一切了。配置文件如下代码:

1  <configSections>
2 <section name="RedisConfig" type="RedisDemo.Common.Redis.RedisConfigInfo, RedisDemo"/>
3 </configSections>
4 <RedisConfig WriteServerList="127.0.0.1:6379" ReadServerList="127.0.0.1:6379" MaxWritePoolSize="60"
  MaxReadPoolSize="60" AutoStart="true" LocalCacheTime="180" RecordeLog="false"/>

  在这里对RedisConfig这段配置文件的属性作下说明。

  WriteServerList:可写的Redis链接地址。

  ReadServerList:可读的Redis链接地址。

  MaxWritePoolSize:最大写链接数。

  MaxReadPoolSize:最大读链接数。

  AutoStart:自动重启。

  LocalCacheTime:本地缓存到期时间,单位:秒。

  RecordeLog:是否记录日志,该设置仅用于排查redis运行时出现的问题,如redis工作正常,请关闭该项。

  RedisConfigInfo类是记录redis连接信息,此信息和配置文件中的RedisConfig相呼应。cs代码如下:(这段代码不是我自己写的,但是我觉得应该这样设计。所以,copy了一下别人的代码。)

  1 using System.Configuration;
2
3 namespace RedisDemo.Common.Redis
4 {
5 public sealed class RedisConfigInfo : ConfigurationSection
6 {
7 public static RedisConfigInfo GetConfig()
8 {
9 var section = (RedisConfigInfo)ConfigurationManager.GetSection("RedisConfig");
10 return section;
11 }
12 public static RedisConfigInfo GetConfig(string sectionName)
13 {
14 var section = (RedisConfigInfo)ConfigurationManager.GetSection("RedisConfig");
15 if (section == null)
16 {
17 throw new ConfigurationErrorsException("Section " + sectionName + " is not found.");
18 }
19 return section;
20 }
21 /// <summary>
22 /// 可写的Redis链接地址
23 /// </summary>
24 [ConfigurationProperty("WriteServerList", IsRequired = false)]
25 public string WriteServerList
26 {
27 get
28 {
29 return (string)base["WriteServerList"];
30 }
31 set
32 {
33 base["WriteServerList"] = value;
34 }
35 }
36 /// <summary>
37 /// 可读的Redis链接地址
38 /// </summary>
39 [ConfigurationProperty("ReadServerList", IsRequired = false)]
40 public string ReadServerList
41 {
42 get
43 {
44 return (string)base["ReadServerList"];
45 }
46 set
47 {
48 base["ReadServerList"] = value;
49 }
50 }
51 /// <summary>
52 /// 最大写链接数
53 /// </summary>
54 [ConfigurationProperty("MaxWritePoolSize", IsRequired = false, DefaultValue = 5)]
55 public int MaxWritePoolSize
56 {
57 get
58 {
59 var maxWritePoolSize = (int)base["MaxWritePoolSize"];
60 return maxWritePoolSize > 0 ? maxWritePoolSize : 5;
61 }
62 set
63 {
64 base["MaxWritePoolSize"] = value;
65 }
66 }
67 /// <summary>
68 /// 最大读链接数
69 /// </summary>
70 [ConfigurationProperty("MaxReadPoolSize", IsRequired = false, DefaultValue = 5)]
71 public int MaxReadPoolSize
72 {
73 get
74 {
75 var maxReadPoolSize = (int)base["MaxReadPoolSize"];
76 return maxReadPoolSize > 0 ? maxReadPoolSize : 5;
77 }
78 set
79 {
80 base["MaxReadPoolSize"] = value;
81 }
82 }
83 /// <summary>
84 /// 自动重启
85 /// </summary>
86 [ConfigurationProperty("AutoStart", IsRequired = false, DefaultValue = true)]
87 public bool AutoStart
88 {
89 get
90 {
91 return (bool)base["AutoStart"];
92 }
93 set
94 {
95 base["AutoStart"] = value;
96 }
97 }
98 /// <summary>
99 /// 本地缓存到期时间,单位:秒
100 /// </summary>
101 [ConfigurationProperty("LocalCacheTime", IsRequired = false, DefaultValue = 36000)]
102 public int LocalCacheTime
103 {
104 get
105 {
106 return (int)base["LocalCacheTime"];
107 }
108 set
109 {
110 base["LocalCacheTime"] = value;
111 }
112 }
113 /// <summary>
114 /// 是否记录日志,该设置仅用于排查redis运行时出现的问题,如redis工作正常,请关闭该项
115 /// </summary>
116 [ConfigurationProperty("RecordeLog", IsRequired = false, DefaultValue = false)]
117 public bool RecordeLog
118 {
119 get
120 {
121 return (bool)base["RecordeLog"];
122 }
123 set
124 {
125 base["RecordeLog"] = value;
126 }
127 }
128 }
129 }

  RedisManager类主要是创建链接池管理对象的。

 1 using System.Linq;
2 using ServiceStack.Redis;
3 using System.Collections.Generic;
4
5 namespace RedisDemo.Common.Redis
6 {
7 public class RedisManager
8 {
9 /// <summary>
10 /// redis配置文件信息
11 /// </summary>
12 private static readonly RedisConfigInfo RedisConfigInfo = RedisConfigInfo.GetConfig();
13
14 private static PooledRedisClientManager _prcm;
15
16 /// <summary>
17 /// 静态构造方法,初始化链接池管理对象
18 /// </summary>
19 static RedisManager()
20 {
21 CreateManager();
22 }
23
24 /// <summary>
25 /// 创建链接池管理对象
26 /// </summary>
27 private static void CreateManager()
28 {
29 var writeServerList = SplitString(RedisConfigInfo.WriteServerList, ",");
30 var readServerList = SplitString(RedisConfigInfo.ReadServerList, ",");
31
32 _prcm = new PooledRedisClientManager(writeServerList,readServerList,
33 new RedisClientManagerConfig
34 {
35 MaxWritePoolSize = RedisConfigInfo.MaxWritePoolSize,
36 MaxReadPoolSize = RedisConfigInfo.MaxReadPoolSize,
37 AutoStart = RedisConfigInfo.AutoStart,
38 });
39 }
40
41 private static IEnumerable<string> SplitString(string strSource, string split)
42 {
43 return strSource.Split(split.ToArray());
44 }
45
46 /// <summary>
47 /// 客户端缓存操作对象
48 /// </summary>
49 public static IRedisClient GetClient()
50 {
51 if (_prcm == null)
52 {
53 CreateManager();
54 }
55 return _prcm.GetClient();
56 }
57
58 }
59 }

实战:封装redis对哈希表操作的代码


  实战中,我们操作redis最好还是要封装提炼一下的。提炼的目的是为了以后代码的重用。代码封装重用的好处我就不多说了,这个不是本次主要讨论的。下面是我所用项目中分装的代码,其中有的部分我修改过了,贴出来让大家看下。个人感觉不错:^_^

  RedisOperatorBase类,是redis操作的基类,继承自IDisposable接口,主要用于释放内存。

 1 using System;
2 using ServiceStack.Redis;
3
4 namespace RedisDemo.Common.Redis.RedisOperator
5 {
6 public abstract class RedisOperatorBase : IDisposable
7 {
8 protected IRedisClient Redis { get; private set; }
9 private bool _disposed = false;
10 protected RedisOperatorBase()
11 {
12 Redis = RedisManager.GetClient();
13 }
14 protected virtual void Dispose(bool disposing)
15 {
16 if (!this._disposed)
17 {
18 if (disposing)
19 {
20 Redis.Dispose();
21 Redis = null;
22 }
23 }
24 this._disposed = true;
25 }
26 public void Dispose()
27 {
28 Dispose(true);
29 GC.SuppressFinalize(this);
30 }
31 /// <summary>
32 /// 保存数据DB文件到硬盘
33 /// </summary>
34 public void Save()
35 {
36 Redis.Save();
37 }
38 /// <summary>
39 /// 异步保存数据DB文件到硬盘
40 /// </summary>
41 public void SaveAsync()
42 {
43 Redis.SaveAsync();
44 }
45 }
46 }

   HashOperator类,是操作哈希表类。继承自RedisOperatorBase类,代码中有详细注释,理解起来一目了然。

 1 using System;
2 using System.Collections.Generic;
3 using ServiceStack.Text;
4
5 namespace RedisDemo.Common.Redis.RedisOperator
6 {
7 public class HashOperator : RedisOperatorBase
8 {
9 public HashOperator() : base() { }
10 /// <summary>
11 /// 判断某个数据是否已经被缓存
12 /// </summary>
13 public bool Exist<T>(string hashId, string key)
14 {
15 return Redis.HashContainsEntry(hashId, key);
16 }
17 /// <summary>
18 /// 存储数据到hash表
19 /// </summary>
20 public bool Set<T>(string hashId, string key, T t)
21 {
22 var value = JsonSerializer.SerializeToString<T>(t);
23 return Redis.SetEntryInHash(hashId, key, value);
24 }
25 /// <summary>
26 /// 移除hash中的某值
27 /// </summary>
28 public bool Remove(string hashId, string key)
29 {
30 return Redis.RemoveEntryFromHash(hashId, key);
31 }
32 /// <summary>
33 /// 移除整个hash
34 /// </summary>
35 public bool Remove(string key)
36 {
37 return Redis.Remove(key);
38 }
39 /// <summary>
40 /// 从hash表获取数据
41 /// </summary>
42 public T Get<T>(string hashId, string key)
43 {
44 string value = Redis.GetValueFromHash(hashId, key);
45 return JsonSerializer.DeserializeFromString<T>(value);
46 }
47 /// <summary>
48 /// 获取整个hash的数据
49 /// </summary>
50 public List<T> GetAll<T>(string hashId)
51 {
52 var result = new List<T>();
53 var list = Redis.GetHashValues(hashId);
54 if (list != null && list.Count > 0)
55 {
56 list.ForEach(x =>
57 {
58 var value = JsonSerializer.DeserializeFromString<T>(x);
59 result.Add(value);
60 });
61 }
62 return result;
63 }
64 /// <summary>
65 /// 设置缓存过期
66 /// </summary>
67 public void SetExpire(string key, DateTime datetime)
68 {
69 Redis.ExpireEntryAt(key, datetime);
70 }
71 }
72 }

实战:redis操作hash哈希表的增删改查


  本来打算这部分把我demo中的操作代码贴出来的,想想,全是代码,看着都烦,还不如讲解一下这部分的操作对应于redis客户端操作命令呢。还有一个原因 就是,上面都已经对hash操作进行了分装,其实如果贴代码也就是调用封装的代码罢了。感觉没啥意思,相信大家都会调用。没啥好讲的。那么接下来我就说 下,上面封装的代码与客户端操作的对应关系。

  Exist<T>方法:对应于redis操作的hexists。返回字段是否是 key 指定的哈希集中存在的字段。true:存在  false:不存在

  Set<T>方法:对应于redis操作的hget。设置 key 指定的哈希集中指定字段的值。如果 key 指定的哈希集不存在,会创建一个新的哈希集并与 key 关联。如果字段在哈希集中存在,它将被重写。

   Remove(string hashId, string key)方法:对应于redis操作的hdel。从 key 指定的哈希集中移除指定的域。在哈希集中不存在的域将被忽略。如果 key 指定的哈希集不存在,它将被认为是一个空的哈希集,该命令将返回false。

  Remove(string key)方法:对应于redis操作的del。直接删除key。

  Get<T>方法:对应于redis操作的hget。返回该字段所关联的值。

  GetAll<T>方法:对应于redis操作的hvals。获取哈希集中的值的列表,当 key 指定的哈希集不存在时返回空列表。

  SetExpire方法:对应于redis操作的expire。设置缓存过期。

总结


   redis操作很多很多,其实说是封装,也只是封装其中的一些常用操作。有兴趣的朋友可以用反编译工具去看下源码,就可以知道所有操作对应于redis 操作命令了。其实我个人觉得,使用C#操作redis只是语言需要,我们还是要学习它的客户端操作的。开发中,很多时候调试很慢的,我们可以直接通过 redis客户端操作去找,这样效率会更高一点。而且当操作命令熟练的时候,你会发现,客户端操作比调试操作快很多很多。所以,建议大家多多使用客户端操 作。刚开始会感觉很多需要记,熟能生巧,多操作,自然会很好。

【转】C#中使用Redis学习二 在.NET4.5中使用redis hash操作的更多相关文章

  1. C#中使用Redis学习二 在.NET4.5中使用redis hash操作

    上一篇>> 摘要 上一篇讲述了安装redis客户端和服务器端,也大体地介绍了一下redis.本篇着重讲解.NET4.0 和 .NET4.5中如何使用redis和C# redis操作哈希表. ...

  2. Redis 学习(二) —— 数据类型及操作

    Redis支持string.list.set.zset.hash等数据类型,这一篇学习redis的数据类型.命令及某些使用场景. 一.String,字符串 字符串是 Redis 最基本的数据类型.一个 ...

  3. Redis学习二:Redis高并发之主从模式

    申明 本文章首发自本人公众号:壹枝花算不算浪漫,如若转载请标明来源! 感兴趣的小伙伴可关注个人公众号:壹枝花算不算浪漫 22.jpg 前言 前面已经学习了Redis的持久化方式,接下来开始学习Redi ...

  4. Redis学习二(数据操作).

    key 操作 删除 key:del key 批量删除key:redis-cli -a(密码)keys "QXJ_*"| xargs redis-cli -a(密码)del 查看所有 ...

  5. php+redis 学习 二 悲观锁

    <?php header('content-type:text/html;chaeset=utf-8'); /** * redis实战 * * 实现悲观锁机制 * */ $timeout = 5 ...

  6. Redis学习系列六ZSet(有序列表)及Redis数据结构的过期

    一.简介 ZSet可以说是Redis中最有趣的数据结构了,因为他兼具了Hash集合和Set的双重特性,也是用的最多的,保证了value值的唯一性的同时,,同时又保证了高性能,最主要的是还可以给每个Va ...

  7. Redis学习之路(四)之Redis集群

    [toc] #Redis集群 1.Redis Cluster简介 Redis Cluster为Redis官方提供的一种分布式集群解决方案.它支持在线节点增加和减少. 集群中的节点角色可能是主,也可能是 ...

  8. Redis学习之路(三)之Redis主从和哨兵模式

    目录 一.Redis主从配置 1.环境说明 2.修改主从的redis配置文件 3.启动主从redis 3.数据同步验证 二.Redis哨兵模式 1.Redis sentinel介绍 2.Redis S ...

  9. Redis学习(一):CentOS下redis安装和部署

    1.基础知识  redis是用C语言开发的一个开源的高性能键值对(key-value)数据库.它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止redis支持的键值数据类型如下字符串.列表 ...

随机推荐

  1. javascript好文 --- 深入理解可视区尺寸client

    可视区大小 可视区大小client又称为可见大小或客户区大小,指的是元素内容及其内边距所占据的空间大小 clientHeight clientHeight属性返回元素节点的可见高度 clientHei ...

  2. Direct2D教程(三)简单几何图形

    从本章开始,我们介绍D2D几何图形. D2D图形分类 Direct2D支持多种类型的几何图形,包括Simple Geometry(简单几何图形) 矩形 圆角矩形 椭圆 Path Geometry(路径 ...

  3. Zen of Python(Python的19条哲学)

    The Zen of Python Beautiful is better than ugly. Explicit is better than implicit. Simple is better ...

  4. tomcat启动文件

    home目录下创建run.bat文件,文件内容如下: @echo off set JAVA_OPTS=-server -Xms1024m -Xmx1024m ^-XX:+UseG1GC ^-XX:Ma ...

  5. C++ ADO 连接 mysql

    1.安装mysql-5.0.22-win32,mysql-connector-odbc-5.1.12-win32.msi    然后:开始菜单->设置->控制面板->管理工具-> ...

  6. Nginx(一):安装

    nginx 的安装 下载地址: http://nginx.org/download/nginx-1.4.2.tar.gz 安装准备: nginx依赖于pcre库,要先安装pcre(正则的库) yum ...

  7. 不能hadoop-daemon.sh start datanode, 显示 错误: 找不到或无法加载主类 ”-Djava.library.path=.home.hadoop.apps.hadoop-2.6.4.lib”

    这两行代码是用来解决一个Hadoop,32位和64位不兼容的警告的,(这个警告可以忽略) 这两行加到mini2~min4后, export HADOOP_COMMON_LIB_NATIVE_DIR=$ ...

  8. IDEA搭建Android wear开发环境,Android wear,I&#39;m comming!

    随着google公布了android wear这个东西.然后又有了三星的gear,LG的G watch以及moto 360,苹果由公布了apple watch.未来可能在智能手表行业又有一场战争. 当 ...

  9. 自己定义ActionBar标题与菜单中的文字样式

    自己定义标题文字样式 标题样式是ActionBar样式的一部分,所以要先定义ActionBar的样式 <style name="AppTheme" parent=" ...

  10. ios 常见错误整理 持续更新

    本文转载至 http://blog.csdn.net/yesjava/article/details/8086185  1. mutating method sent to immutable obj ...