這幾天沒有按照計劃分享技術博文,主要是去醫院了,這裡一想到在醫院經歷的種種,我真的有話要說;醫院里的醫務人員曾經被吹捧為美麗+和藹+可親的天使,在經受5天左右相互接觸後不得不讓感慨;遇見的有些人員在掛號隊伍猶如長龍的時候坐在收費視窗玩手機,理由是自己是換班的差幾分鐘才上班呢;遇見態度極其惡劣的主任醫 ...
這幾天沒有按照計劃分享技術博文,主要是去醫院了,這裡一想到在醫院經歷的種種,我真的有話要說;醫院里的醫務人員曾經被吹捧為美麗+和藹+可親的天使,在經受5天左右相互接觸後不得不讓感慨;遇見的有些人員在掛號隊伍猶如長龍的時候坐在收費視窗玩手機,理由是自己是換班的差幾分鐘才上班呢;遇見態度極其惡劣的主任醫師,做咨詢幾個問題聲音馬上提高並言語中攜帶諷刺話語;還有其他幾個遇見哈哈這裡就不多說了,可能是某些醫務人員覺得多您個不少,我有的是客源,所以個別是這種態度吧,還是市醫院真不知道怎麼混進去的。
以上是個人的看法,下麵來正式分享今天的文章吧:
。搭建Redis服務端,並用客戶端連接
。封裝緩存父類,定義Get,Set等常用方法
。定義RedisCache緩存類,執行Redis的Get,Set方法
。構造出緩存工廠調用方法
下麵一步一個腳印的來分享:
。搭建Redis服務端,並用客戶端連接
首先,咋們去這個地址下載安裝文件https://github.com/dmajkic/redis/downloads,我這裡的版本是:redis-2.4.5-win32-win64裡面有32位和64位的執行文件,我這裡伺服器是64位的下麵給出截圖和用到部分程式的說明:
現在,咋們直接可以用滑鼠雙擊redis-server.exe這個應用程式,這樣就打開了redis服務窗體(您也可以下載一個windows服務承載器,把redis服務運行在windows的服務中,就不用擔心每次關閉redis服務黑色窗體後無法訪問redis了),運行起來是這樣:
有紅色框的信息就表示成功了,這裡redis服務監聽的埠預設是6379,要修改埠或者更多的配置信息請找到redis.conf配置文件,具體配置信息介紹可以來這裡http://www.shouce.ren/api/view/a/6231
再來,打開客戶端連接服務端,咋們退到64bit文件夾的目錄中,滑鼠移到64bit文件夾上並且安裝Shift鍵,同時點擊滑鼠的右鍵,選中"在此處打開命令視窗"這樣快速進入到了該文件夾的cmd命令視窗中(當然不同的操作系統不同,這裡演示的是windows的操作;還有其他進入的方式這裡不做介紹,因為個人感覺這是最快的);然後,在命令視窗中錄入redis-cli.exe -h localhost -p 6379回車來訪問服務端,效果圖:
再來看下服務端窗體截圖:
沒錯這樣客戶端就連接上服務端了,可以簡單在客戶端執行下set,get命令:
如果是客戶端要訪問遠程的redis服務端,只需要把localhost換成可訪問的ip就行瞭如果還需要密碼等更多配置請去上面的那個地址鏈接;
。封裝緩存父類,定義Get,Set等常用方法
先來,上父類的代碼:
1 public class BaseCache : IDisposable 2 { 3 protected string def_ip = string.Empty; 4 protected int def_port = 0; 5 protected string def_password = string.Empty; 6 7 public BaseCache() 8 { 9 10 } 11 12 public virtual void InitCache(string ip = "", int port = 0, string password = "") 13 { 14 15 } 16 17 public virtual bool SetCache<T>(string key, T t, int timeOutMinute = 10) where T : class,new() 18 { 19 20 return false; 21 } 22 23 public virtual T GetCache<T>(string key) where T : class,new() 24 { 25 26 return default(T); 27 } 28 29 public virtual bool Remove(string key) 30 { 31 32 return false; 33 } 34 35 public virtual bool FlushAll() 36 { 37 38 return false; 39 } 40 41 public virtual bool Any(string key) 42 { 43 44 return false; 45 } 46 47 public virtual void Dispose(bool isfalse) 48 { 49 50 if (isfalse) 51 { 52 53 54 } 55 } 56 57 //手動釋放 58 public void Dispose() 59 { 60 61 this.Dispose(true); 62 //不自動釋放 63 GC.SuppressFinalize(this); 64 } 65 }View Code
這裡定義的方法沒有太多的註釋,更多的意思我想看方法名稱就明白了,這個父類主要實現了IDisposable,實現的Dispose()中主要用來釋放資源並且自定義了一個 public virtual void Dispose(bool isfalse)方法,這裡面有一句是GC.SuppressFinalize(this);按照官網介紹的意思是阻塞自動釋放資源,其他的沒有什麼了,繼續看下麵的
。定義RedisCache緩存類,執行Redis的Get,Set方法
首先,咋們分別定義類RedisCache,MemcachedCache(這裡暫未實現對memcache緩存的操作),並且繼承BaseCache,重寫Set,Get方法如下代碼:
1 /// <summary> 2 /// Redis緩存 3 /// </summary> 4 public class RedisCache : BaseCache 5 { 6 public RedisClient redis = null; 7 8 public RedisCache() 9 { 10 11 //這裡去讀取預設配置文件數據 12 def_ip = "172.0.0.1"; 13 def_port = 6379; 14 def_password = ""; 15 } 16 17 #region Redis緩存 18 19 public override void InitCache(string ip = "", int port = 0, string password = "") 20 { 21 22 if (redis == null) 23 { 24 ip = string.IsNullOrEmpty(ip) ? def_ip : ip; 25 port = port == 0 ? def_port : port; 26 password = string.IsNullOrEmpty(password) ? def_password : password; 27 28 redis = new RedisClient(ip, port, password); 29 } 30 } 31 32 public override bool SetCache<T>(string key, T t, int timeOutMinute = 10) 33 { 34 35 var isfalse = false; 36 37 try 38 { 39 if (string.IsNullOrEmpty(key)) { return isfalse; } 40 41 InitCache(); 42 isfalse = redis.Set<T>(key, t, TimeSpan.FromMinutes(timeOutMinute)); 43 } 44 catch (Exception ex) 45 { 46 } 47 finally { this.Dispose(); } 48 return isfalse; 49 } 50 51 public override T GetCache<T>(string key) 52 { 53 var t = default(T); 54 try 55 { 56 if (string.IsNullOrEmpty(key)) { return t; } 57 58 InitCache(); 59 t = redis.Get<T>(key); 60 } 61 catch (Exception ex) 62 { 63 } 64 finally { this.Dispose(); } 65 return t; 66 } 67 68 public override bool Remove(string key) 69 { 70 var isfalse = false; 71 try 72 { 73 if (string.IsNullOrEmpty(key)) { return isfalse; } 74 75 InitCache(); 76 isfalse = redis.Remove(key); 77 } 78 catch (Exception ex) 79 { 80 } 81 finally { this.Dispose(); } 82 return isfalse; 83 } 84 85 public override void Dispose(bool isfalse) 86 { 87 88 if (isfalse && redis != null) 89 { 90 91 redis.Dispose(); 92 redis = null; 93 } 94 } 95 96 #endregion 97 } 98 99 100 /// <summary> 101 /// Memcached緩存 102 /// </summary> 103 public class MemcachedCache : BaseCache 104 { 105 106 107 }View Code
這裡,用到的RedisClient類是來自nuget包引用的,這裡nuget包是:
然後,來看下重寫的InitCache方法,這裡面有一些ip,port(埠),password(密碼)參數,這裡直接寫入在cs文件中沒有從配置文件讀取,大家可以擴展下;這些參數通過RedisClient構造函數傳遞給底層Socket訪問需要的信息,下麵簡單展示下RedisClient幾個的構造函數:
1 public RedisClient(); 2 public RedisClient(RedisEndpoint config); 3 public RedisClient(string host); 4 public RedisClient(Uri uri); 5 public RedisClient(string host, int port); 6 public RedisClient(string host, int port, string password = null, long db = 0);
至於Get,Set方法最終都是使用RedisClient對象訪問的,個人覺得需要註意的是Set方法裡面的過期時間參數,目前還沒有試驗這種情況的效果:
?通過這幾種方法設置過期時間後,快到過期時間的時候如果此時有使用這個緩存key那麼過期時間是否會往後自動增加過期時間有效期,這裡暫時沒有試驗(這裡是由於前面項目中的.net core框架中的memecache緩存都有這種設置,想來redis應該也有吧)
這裡,需要重寫下public override void Dispose(bool isfalse)方法,因為調用完RedisClient後需要釋放,我們通過Dispose統一來手動釋放,而不是直接在調用的時候使用using()
。構造出緩存工廠調用方法
接下來,咋們需要定義一個緩存工廠,因為上面剛纔定義了一個RedisCache和MemcachedCache明顯這裡會有多個不同緩存的方法調用,所用咋們來定義個工廠模式來調用對應的緩存;這裡的工廠模式沒有使用直接顯示創建new RedisCache(),new MemcachedCache()對象的方法,而是使用了反射的原理,創建對應的緩存對象;
先來,定義個枚舉,枚舉裡面的聲明的名字要和咋們緩存類的名稱相同,代碼如下:
1 public enum CacheType 2 { 3 RedisCache, 4 5 MemcachedCache 6 }
再來,定義個工廠來CacheRepository(緩存工廠),並且定義方法Current如下代碼:
1 public static BaseCache Current(CacheType cacheType = CacheType.RedisCache) 2 { 3 var nspace = typeof(BaseCache); 4 var fullName = nspace.FullName; 5 var nowspace = fullName.Substring(0, fullName.LastIndexOf('.') + 1); 6 7 return Assembly.GetExecutingAssembly().CreateInstance(nowspace + cacheType.ToString(), true) as BaseCache; 8 }
*:通過傳遞枚舉參數,來確定反射CreateInstance()方法需要用到的typeName參數,從而來定義需要訪問的那個緩存對象,這裡要註意的是加上了一個命名空間nowspace,因為緩存類可能和工廠類不是同一個命名空間,但是通常會和緩存基類是同命名空間所以在方法最開始的時候截取獲取了緩存類需要的命名空間(這裡看自身項目來定吧);
*:Assembly.GetExecutingAssembly()這個是用來獲取當前應用程式集的路徑,這裡就避免了咋們使用Assembly.Load()方法還需要傳遞程式集的路徑地址了
好了滿上上面要求後,咋們可以在測試頁面調用代碼如:CacheRepository.Current(CacheType.RedisCache).SetCache<MoFlightSearchResponse>(keyData, value);就如此簡單,咋們使用redis-cli.exe客戶端來看下緩存起來的數據:
怎麼樣,您們的是什麼效果呢,下麵給出整體代碼:
1 public enum CacheType 2 { 3 RedisCache, 4 5 MemcachedCache 6 } 7 8 public class CacheRepository 9 { 10 11 public static BaseCache Current(CacheType cacheType = CacheType.RedisCache) 12 { 13 var nspace = typeof(BaseCache); 14 var fullName = nspace.FullName; 15 var nowspace = fullName.Substring(0, fullName.LastIndexOf('.') + 1); 16 17 return Assembly.GetExecutingAssembly().CreateInstance(nowspace + cacheType.ToString(), true) as BaseCache; 18 } 19 } 20 21 public class BaseCache : IDisposable 22 { 23 protected string def_ip = string.Empty; 24 protected int def_port = 0; 25 protected string def_password = string.Empty; 26 27 public BaseCache() 28 { 29 30 } 31 32 public virtual void InitCache(string ip = "", int port = 0, string password = "") 33 { 34 35 } 36 37 public virtual bool SetCache<T>(string key, T t, int timeOutMinute = 10) where T : class,new() 38 { 39 40 return false; 41 } 42 43 public virtual T GetCache<T>(string key) where T : class,new() 44 { 45 46 return default(T); 47 } 48 49 public virtual bool Remove(string key) 50 { 51 52 return false; 53 } 54 55 public virtual bool FlushAll() 56 { 57 58 return false; 59 } 60 61 public virtual bool Any(string key) 62 { 63 64 return false; 65 } 66 67 public virtual void Dispose(bool isfalse) 68 { 69 70 if (isfalse) 71 { 72 73 74 } 75 } 76 77 //手動釋放 78 public void Dispose() 79 { 80 81 this.Dispose(true); 82 //不自動釋放 83 GC.SuppressFinalize(this); 84 } 85 } 86 87 /// <summary> 88 /// Redis緩存 89 /// </summary> 90 public class RedisCache : BaseCache 91 { 92 public RedisClient redis = null; 93 94 public RedisCache() 95 { 96 97 //這裡去讀取預設配置文件數據 98 def_ip = "172.16.2.56"; 99 def_port = 6379; 100 def_password = ""; 101 } 102 103 #region Redis緩存 104 105 public override void InitCache(string ip = "", int port = 0, string password = "") 106 { 107 108 if (redis == null) 109 { 110 ip = string.IsNullOrEmpty(ip) ? def_ip : ip; 111 port = port == 0 ? def_port : port; 112 password = string.IsNullOrEmpty(password) ? def_password : password; 113 114 redis = new RedisClient(ip, port, password); 115 } 116 } 117 118 public override bool SetCache<T>(string key, T t, int timeOutMinute = 10) 119 { 120 121 var isfalse = false; 122 123 try 124 { 125 if (string.IsNullOrEmpty(key)) { return isfalse; } 126 127 InitCache(); 128 isfalse = redis.Set<T>(key, t, TimeSpan.FromMinutes(timeOutMinute)); 129 } 130 catch (Exception ex) 131 { 132 } 133 finally { this.Dispose(); } 134 return isfalse; 135 } 136 137 public override T GetCache<T>(string key) 138 { 139 var t = default(T); 140 try 141 { 142 if (string.IsNullOrEmpty(key)) { return t; } 143 144 InitCache(); 145 t = redis.Get<T>(key); 146 } 147 catch (Exception ex) 148 { 149 } 150 finally { this.Dispose(); } 151 return t; 152 } 153 154 public override bool Remove(string key) 155 { 156 var isfalse = false; 157 try 158 { 159 if (string.IsNullOrEmpty(key)) { return isfalse; } 160 161 InitCache(); 162 isfalse = redis.Remove(key); 163 } 164 catch (Exception ex) 165 { 166 } 167 finally { this.Dispose(); } 168 return isfalse; 169 } 170 171 public override void Dispose(bool isfalse) 172 { 173 174 if (isfalse && redis != null) 175 { 176 177 redis.Dispose(); 178 redis = null; 179 } 180 } 181 182 #endregion 183 } 184 185 186 /// <summary> 187 /// Memcached緩存 188 /// </summary> 189 public class MemcachedCache : BaseCache 190 { 191 192 193 }View Code
這次分享的Redis緩存從搭建到使用希望給您們有幫助,還請多多支持點贊,謝謝。