C#中使用Redis學習二 在.NET4.5中使用redis hash操作
摘要
上一篇講述了安裝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
伺服器。其中包含很多配置,我就用程式碼去說明一切了。配置檔案如下程式碼:
<configSections>
<section name="RedisConfig" type="RedisDemo.Common.Redis.RedisConfigInfo, RedisDemo"/>
</configSections>
<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了一下別人的程式碼。)
using System.Configuration;
namespace RedisDemo.Common.Redis
{
public sealed class RedisConfigInfo : ConfigurationSection
{
public static RedisConfigInfo GetConfig()
{
var section = (RedisConfigInfo)ConfigurationManager.GetSection("RedisConfig");
return section;
}
public static RedisConfigInfo GetConfig(string sectionName)
{
var section = (RedisConfigInfo)ConfigurationManager.GetSection("RedisConfig");
if (section == null)
{
throw new ConfigurationErrorsException("Section " + sectionName + " is not found.");
}
return section;
}
/// <summary>
/// 可寫的Redis連結地址
/// </summary>
[ConfigurationProperty("WriteServerList", IsRequired = false)]
public string WriteServerList
{
get
{
return (string)base["WriteServerList"];
}
set
{
base["WriteServerList"] = value;
}
}
/// <summary>
/// 可讀的Redis連結地址
/// </summary>
[ConfigurationProperty("ReadServerList", IsRequired = false)]
public string ReadServerList
{
get
{
return (string)base["ReadServerList"];
}
set
{
base["ReadServerList"] = value;
}
}
/// <summary>
/// 最大寫連結數
/// </summary>
[ConfigurationProperty("MaxWritePoolSize", IsRequired = false, DefaultValue = 5)]
public int MaxWritePoolSize
{
get
{
var maxWritePoolSize = (int)base["MaxWritePoolSize"];
return maxWritePoolSize > 0 ? maxWritePoolSize : 5;
}
set
{
base["MaxWritePoolSize"] = value;
}
}
/// <summary>
/// 最大讀連結數
/// </summary>
[ConfigurationProperty("MaxReadPoolSize", IsRequired = false, DefaultValue = 5)]
public int MaxReadPoolSize
{
get
{
var maxReadPoolSize = (int)base["MaxReadPoolSize"];
return maxReadPoolSize > 0 ? maxReadPoolSize : 5;
}
set
{
base["MaxReadPoolSize"] = value;
}
}
/// <summary>
/// 自動重啟
/// </summary>
[ConfigurationProperty("AutoStart", IsRequired = false, DefaultValue = true)]
public bool AutoStart
{
get
{
return (bool)base["AutoStart"];
}
set
{
base["AutoStart"] = value;
}
}
/// <summary>
/// 本地快取到期時間,單位:秒
/// </summary>
[ConfigurationProperty("LocalCacheTime", IsRequired = false, DefaultValue = 36000)]
public int LocalCacheTime
{
get
{
return (int)base["LocalCacheTime"];
}
set
{
base["LocalCacheTime"] = value;
}
}
/// <summary>
/// 是否記錄日誌,該設定僅用於排查redis執行時出現的問題,如redis工作正常,請關閉該項
/// </summary>
[ConfigurationProperty("RecordeLog", IsRequired = false, DefaultValue = false)]
public bool RecordeLog
{
get
{
return (bool)base["RecordeLog"];
}
set
{
base["RecordeLog"] = value;
}
}
}
}
RedisManager
類主要是建立連結池管理物件的。
using System.Linq;
using ServiceStack.Redis;
using System.Collections.Generic;
namespace RedisDemo.Common.Redis
{
public class RedisManager
{
/// <summary>
/// redis配置檔案資訊
/// </summary>
private static readonly RedisConfigInfo RedisConfigInfo = RedisConfigInfo.GetConfig();
private static PooledRedisClientManager _prcm;
/// <summary>
/// 靜態構造方法,初始化連結池管理物件
/// </summary>
static RedisManager()
{
CreateManager();
}
/// <summary>
/// 建立連結池管理物件
/// </summary>
private static void CreateManager()
{
var writeServerList = SplitString(RedisConfigInfo.WriteServerList, ",");
var readServerList = SplitString(RedisConfigInfo.ReadServerList, ",");
_prcm = new PooledRedisClientManager(writeServerList,readServerList,
new RedisClientManagerConfig
{
MaxWritePoolSize = RedisConfigInfo.MaxWritePoolSize,
MaxReadPoolSize = RedisConfigInfo.MaxReadPoolSize,
AutoStart = RedisConfigInfo.AutoStart,
});
}
private static IEnumerable<string> SplitString(string strSource, string split)
{
return strSource.Split(split.ToArray());
}
/// <summary>
/// 客戶端快取操作物件
/// </summary>
public static IRedisClient GetClient()
{
if (_prcm == null)
{
CreateManager();
}
return _prcm.GetClient();
}
}
}
實戰:封裝redis對雜湊表操作的程式碼
實戰中,我們操作redis
最好還是要封裝提煉一下的。提煉的目的是為了以後程式碼的重用。程式碼封裝重用的好處我就不多說了,這個不是本次主要討論的。下面是我所用專案中分裝的程式碼,其中有的部分我修改過了,貼出來讓大家看下。個人感覺不錯:^_^
RedisOperatorBase
類,是redis
操作的基類,繼承自IDisposable
介面,主要用於釋放記憶體。
using System;
using ServiceStack.Redis;
namespace RedisDemo.Common.Redis.RedisOperator
{
public abstract class RedisOperatorBase : IDisposable
{
protected IRedisClient Redis { get; private set; }
private bool _disposed = false;
protected RedisOperatorBase()
{
Redis = RedisManager.GetClient();
}
protected virtual void Dispose(bool disposing)
{
if (!this._disposed)
{
if (disposing)
{
Redis.Dispose();
Redis = null;
}
}
this._disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 儲存資料DB檔案到硬碟
/// </summary>
public void Save()
{
Redis.Save();
}
/// <summary>
/// 非同步儲存資料DB檔案到硬碟
/// </summary>
public void SaveAsync()
{
Redis.SaveAsync();
}
}
}
HashOperator
類,是操作雜湊表類。繼承自RedisOperatorBase
類,程式碼中有詳細註釋,理解起來一目瞭然。
using System;
using System.Collections.Generic;
using ServiceStack.Text;
namespace RedisDemo.Common.Redis.RedisOperator
{
public class HashOperator : RedisOperatorBase
{
public HashOperator() : base() { }
/// <summary>
/// 判斷某個資料是否已經被快取
/// </summary>
public bool Exist<T>(string hashId, string key)
{
return Redis.HashContainsEntry(hashId, key);
}
/// <summary>
/// 儲存資料到hash表
/// </summary>
public bool Set<T>(string hashId, string key, T t)
{
var value = JsonSerializer.SerializeToString<T>(t);
return Redis.SetEntryInHash(hashId, key, value);
}
/// <summary>
/// 移除hash中的某值
/// </summary>
public bool Remove(string hashId, string key)
{
return Redis.RemoveEntryFromHash(hashId, key);
}
/// <summary>
/// 移除整個hash
/// </summary>
public bool Remove(string key)
{
return Redis.Remove(key);
}
/// <summary>
/// 從hash表獲取資料
/// </summary>
public T Get<T>(string hashId, string key)
{
string value = Redis.GetValueFromHash(hashId, key);
return JsonSerializer.DeserializeFromString<T>(value);
}
/// <summary>
/// 獲取整個hash的資料
/// </summary>
public List<T> GetAll<T>(string hashId)
{
var result = new List<T>();
var list = Redis.GetHashValues(hashId);
if (list != null && list.Count > 0)
{
list.ForEach(x =>
{
var value = JsonSerializer.DeserializeFromString<T>(x);
result.Add(value);
});
}
return result;
}
/// <summary>
/// 設定快取過期
/// </summary>
public void SetExpire(string key, DateTime datetime)
{
Redis.ExpireEntryAt(key, datetime);
}
}
}
實戰: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
客戶端操作去找,這樣效率會更高一點。而且當操作命令熟練的時候,你會發現,客戶端操作比除錯操作快很多很多。所以,建議大家多多使用客戶端操 作。剛開始會感覺很多需要記,熟能生巧,多操作,自然會很好。
相關文章
- redis學習筆記4: 在Java中操作RedisRedis筆記Java
- Redis在.net中的使用(2).net專案中的Redis使用Redis
- Redis在.net中的使用(5)Redis持久化Redis持久化
- redis redis中的hash結構【八】Redis
- Redis在.net中的使用(6)Redis併發鎖Redis
- Redis在遊戲業務中的使用Redis遊戲
- Redis 中的原子操作(3)-使用Redis實現分散式鎖Redis分散式
- Redis在.net中的使用(1)下載安裝RedisRedis
- [Redis 系列]redis 學習二Redis
- 【Redis 系列】redis 學習二Redis
- Redis在.net中的使用(7)redis部署為Windows服務RedisWindows
- redis操作中hash結構可以存多少key合適Redis
- Redis學習記錄(二)--使用Jedis連線Redis
- redis的安裝並在java中初步使用(spring配置redis)RedisJavaSpring
- Redis 哨兵使用以及在 Laravel 中的配置RedisLaravel
- Redis的安裝及在Java中的使用RedisJava
- redis在排行榜中的使用總結Redis
- spring boot中redis使用Spring BootRedis
- 深入學習Redis(二)Redis
- redis使用中存在的問題及如何避免(二)Redis
- Redis的使用(二)Redis
- Redis pipeline 在連續一萬次插入操作測試中的使用Redis
- Redis 中的原子操作(1)-Redis 中命令的原子性Redis
- Redis之hash型別及操作Redis型別
- Redis中的原子操作(2)-redis中使用Lua指令碼保證命令原子性Redis指令碼
- redis原始碼分析(五)、redis命令學習總結—雜湊HashRedis原始碼
- Redis在專案中合理使用經驗總結Redis
- redis(二)redis概述與jedis的使用Redis
- Redis 中 BitMap 的使用場景Redis
- 使用redis中setnx防止併發二次寫入Redis
- Redis中PipeLine使用(二)---批量get與批量setRedis
- 使用Docker安裝Redis - 學習三DockerRedis
- 【Redis】Redis 學習Redis
- 在centos7中安裝redis,並通過node.js操作redisCentOSRedisNode.js
- 如何設定redis中hash的field的expire ?Redis
- 使用java程式碼操作redisJavaRedis
- java操作redis。jedis使用apiJavaRedisAPI
- 在 Java 中使用 redisJavaRedis