緩存工廠之 Redis 緩存
正式分享今天的文章吧:
-
搭建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等常用方法
先來,上父類的代碼:
public class BaseCache : IDisposable
{
protected string def_ip = string.Empty;
protected int def_port = 0;
protected string def_password = string.Empty;
public BaseCache()
{
}
public virtual void InitCache(string ip = "", int port = 0, string password = "")
{
}
public virtual bool SetCache<T>(string key, T t, int timeOutMinute = 10) where T : class,new()
{
return false;
}
public virtual T GetCache<T>(string key) where T : class,new()
{
return default(T);
}
public virtual bool Remove(string key)
{
return false;
}
public virtual bool FlushAll()
{
return false;
}
public virtual bool Any(string key)
{
return false;
}
public virtual void Dispose(bool isfalse)
{
if (isfalse)
{ }
}
//手動釋放
public void Dispose()
{
this.Dispose(true);
//不自動釋放
GC.SuppressFinalize(this);
}
}
這里定義的方法沒有太多的注釋,更多的意思我想看方法名稱就明白了,這個父類主要實現了IDisposable,實現的Dispose()中主要用來釋放資源并且自定義了一個 public virtual void Dispose(bool isfalse)方法
這里面有一句是GC.SuppressFinalize(this);按照官網介紹的意思是阻塞自動釋放資源,其他的沒有什么了,繼續看下面的
定義RedisCache緩存類,執行Redis的Get,Set方法。 首先,咋們分別定義類RedisCache,MemcachedCache(這里暫未實現對memcache緩存的操作),并且繼承BaseCache,重寫Set,Get方法如下代碼:
/// <summary>
/// Redis緩存
/// </summary>
public class RedisCache : BaseCache
{
public RedisClient redis = null;
public RedisCache()
{
//這里去讀取默認配置文件數據
def_ip = "172.0.0.1";
def_port = 6379;
def_password = "";
}
#region Redis緩存
public override void InitCache(string ip = "", int port = 0, string password = "")
{
if (redis == null)
{
ip = string.IsNullOrEmpty(ip) ? def_ip : ip;
port = port == 0 ? def_port : port;
password = string.IsNullOrEmpty(password) ? def_password : password;
redis = new RedisClient(ip, port, password);
}
}
public override bool SetCache<T>(string key, T t, int timeOutMinute = 10)
{
var isfalse = false;
try
{
if (string.IsNullOrEmpty(key)) { return isfalse; }
InitCache();
isfalse = redis.Set<T>(key, t, TimeSpan.FromMinutes(timeOutMinute));
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
}
public override T GetCache<T>(string key)
{
var t = default(T);
try
{
if (string.IsNullOrEmpty(key)) { return t; }
InitCache();
t = redis.Get<T>(key);
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return t;
}
public override bool Remove(string key)
{
var isfalse = false;
try
{
if (string.IsNullOrEmpty(key)) { return isfalse; }
InitCache();
isfalse = redis.Remove(key);
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
}
public override void Dispose(bool isfalse)
{
if (isfalse && redis != null)
{
redis.Dispose();
redis = null;
}
}
#endregion
}
/// <summary>
/// Memcached緩存
/// </summary>
public class MemcachedCache : BaseCache
{
}
這里,用到的RedisClient類是來自nuget包引用的,這里nuget包是:
然后,來看下重寫的InitCache方法,這里面有一些ip,port(端口),password(密碼)參數,這里直接寫入在cs文件中沒有從配置文件讀取,大家可以擴展下;
這些參數通過RedisClient構造函數傳遞給底層Socket訪問需要的信息,下面簡單展示下RedisClient幾個的構造函數:
public RedisClient();
public RedisClient(RedisEndpoint config);
public RedisClient(string host);
public RedisClient(Uri uri);
public RedisClient(string host, int port);
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()對象的方法,而是使用了反射的原理,創建對應的緩存對象;
先來,定義個枚舉,枚舉里面的聲明的名字要和咋們緩存類的名稱相同,代碼如下:
public enum CacheType
{
RedisCache,
MemcachedCache
}
再來,定義個工廠來CacheRepository(緩存工廠),并且定義方法Current如下代碼:
public static BaseCache Current(CacheType cacheType = CacheType.RedisCache)
{
var nspace = typeof(BaseCache);
var fullName = nspace.FullName;
var nowspace = fullName.Substring(0, fullName.LastIndexOf('.') + 1);
return Assembly.GetExecutingAssembly().CreateInstance(nowspace + cacheType.ToString(), true) as BaseCache;
}
通過傳遞枚舉參數,來確定反射CreateInstance()方法需要用到的typeName參數,從而來定義需要訪問的那個緩存對象,這里要注意的是加上了一個命名空間nowspace,因為緩存類可能和工廠類不是同一個命名空間,但是通常會和緩存基類是同命名空間所以在方法最開始的時候截取獲取了緩存類需要的命名空間(這里看自身項目來定吧);
Assembly.GetExecutingAssembly()這個是用來獲取當前應用程序集的路徑,這里就避免了咋們使用Assembly.Load()方法還需要傳遞程序集的路徑地址了
好了滿上上面要求后,咋們可以在測試頁面調用代碼如:
CacheRepository.Current(CacheType.RedisCache).SetCache<MoFlightSearchResponse>(keyData, value);就如此簡單,咋們使用redis-cli.exe客戶端來看下緩存起來的數據:
怎么樣,您們的是什么效果呢,下面給出整體代碼:
public enum CacheType
{
RedisCache,
MemcachedCache
}
public class CacheRepository
{
public static BaseCache Current(CacheType cacheType = CacheType.RedisCache)
{
var nspace = typeof(BaseCache);
var fullName = nspace.FullName;
var nowspace = fullName.Substring(0, fullName.LastIndexOf('.') + 1);
return Assembly.GetExecutingAssembly().CreateInstance(nowspace + cacheType.ToString(), true) as BaseCache;
}
}
public class BaseCache : IDisposable
{
protected string def_ip = string.Empty;
protected int def_port = 0;
protected string def_password = string.Empty;
public BaseCache()
{
}
public virtual void InitCache(string ip = "", int port = 0, string password = "")
{
}
public virtual bool SetCache<T>(string key, T t, int timeOutMinute = 10) where T : class,new()
{
return false;
}
public virtual T GetCache<T>(string key) where T : class,new()
{
return default(T);
}
public virtual bool Remove(string key)
{
return false;
}
public virtual bool FlushAll()
{
return false;
}
public virtual bool Any(string key)
{
return false;
}
public virtual void Dispose(bool isfalse)
{
if (isfalse)
{
}
}
//手動釋放
public void Dispose()
{
this.Dispose(true);
//不自動釋放
GC.SuppressFinalize(this);
}
}
/// <summary>
/// Redis緩存
/// </summary>
public class RedisCache : BaseCache
{
public RedisClient redis = null;
public RedisCache()
{
//這里去讀取默認配置文件數據
def_ip = "172.16.2.56";
def_port = 6379;
def_password = "";
}
#region Redis緩存
public override void InitCache(string ip = "", int port = 0, string password = "")
{
if (redis == null)
{
ip = string.IsNullOrEmpty(ip) ? def_ip : ip;
port = port == 0 ? def_port : port;
password = string.IsNullOrEmpty(password) ? def_password : password;
redis = new RedisClient(ip, port, password);
}
}
public override bool SetCache<T>(string key, T t, int timeOutMinute = 10)
{
var isfalse = false;
try
{
if (string.IsNullOrEmpty(key)) { return isfalse; }
InitCache();
isfalse = redis.Set<T>(key, t, TimeSpan.FromMinutes(timeOutMinute));
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
}
public override T GetCache<T>(string key)
{
var t = default(T);
try
{
if (string.IsNullOrEmpty(key)) { return t; }
InitCache();
t = redis.Get<T>(key);
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return t;
}
public override bool Remove(string key)
{
var isfalse = false;
try
{
if (string.IsNullOrEmpty(key)) { return isfalse; }
InitCache();
isfalse = redis.Remove(key);
}
catch (Exception ex)
{
}
finally { this.Dispose(); }
return isfalse;
}
public override void Dispose(bool isfalse)
{
if (isfalse && redis != null)
{
redis.Dispose();
redis = null;
}
}
#endregion
}
/// <summary>
/// Memcached緩存
/// </summary>
public class MemcachedCache : BaseCache
{
}
這次分享的Redis緩存從搭建到使用希望給您們有幫助,還請多多支持點贊,謝謝。
【今日微信公號推薦↓】
來自:http://mp.weixin.qq.com/s?__biz=MzAxMTMxMDQ3Mw==&mid=2660099443&idx=2&sn=fa55cb05bd9c5f70f8f12b2a21a6f812&scene=0