zoukankan      html  css  js  c++  java
  • C#中使用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 }
    RedisConfigInfo 类
    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 private static PooledRedisClientManager _prcm;
    14 /// <summary>
    15 /// 静态构造方法,初始化链接池管理对象
    16 /// </summary>
    17 static RedisManager()
    18 {
    19 CreateManager();
    20 }
    21 /// <summary>
    22 /// 创建链接池管理对象
    23 /// </summary>
    24 private static void CreateManager()
    25 {
    26 var writeServerList = SplitString(RedisConfigInfo.WriteServerList, ",");
    27 var readServerList = SplitString(RedisConfigInfo.ReadServerList, ",");
    28
    29 _prcm = new PooledRedisClientManager(readServerList, writeServerList,
    30 new RedisClientManagerConfig
    31 {
    32 MaxWritePoolSize = RedisConfigInfo.MaxWritePoolSize,
    33 MaxReadPoolSize = RedisConfigInfo.MaxReadPoolSize,
    34 AutoStart = RedisConfigInfo.AutoStart,
    35 });
    36 }
    37 private static IEnumerable<string> SplitString(string strSource, string split)
    38 {
    39 return strSource.Split(split.ToArray());
    40 }
    41 /// <summary>
    42 /// 客户端缓存操作对象
    43 /// </summary>
    44 public static IRedisClient GetClient()
    45 {
    46 if (_prcm == null)
    47 {
    48 CreateManager();
    49 }
    50 return _prcm.GetClient();
    51 }
    52 }
    53 }
    RedisManager 类
    实战:封装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 }
    RedisOperatorBase 类
    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 }
    HashOperator 类
    实战: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。设置缓存过期。

  • 相关阅读:
    DropDownList判断值是否存在下拉列表中
    postgre教程
    Cookie seesion 赋值
    Winform定时启动
    ASP.NET数据绑定控件
    ASP.NET常用数据绑定控件优劣总结
    Cards and Joy (dp好题)
    River Hopscotch (二分)
    剪花布条(KMP入门)
    GCD (区间数的质因子打表+容斥原理)
  • 原文地址:https://www.cnblogs.com/ft-Pavilion/p/6045942.html
Copyright © 2011-2022 走看看