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。設置緩存過期。