回到目錄
對于目前的網站來說,為了滿足高可用,高并發,高負載,一台WEB伺服器已經遠遠不夠用了,以後的WEB應用伺服器應該是一種叢集的環境,它們之間使用一些工具進行資料的同步,在由1台變成多台伺服器時,有一個問題是我們必須要考慮的,Session機制,我們都知道Session被用來存儲使用者的一些憑證資訊,持久化到伺服器上,這在安全性方面得到了保證(比存儲到用戶端的cookies),而當你的WEB應用伺服器是多台時(多台之間做了負載均衡),這種Session機制就有問題了,因為你無法實作從一台伺服器到别一台伺服器的記憶體(緩存)共享,這也是不安全的,是以,在出現緩存中間件出現之後,就有了一種新的技術也跟着出現了,即Session中間件,比較成熟的元件是StackExchange.Redis+RedisSessionStateProvider,即使用Redis實作的Session機制,它将session資料存儲到了一台(可以是redis叢集)redis伺服器上,這時,多台WEB應用伺服器之間的資料就是唯一的了,不需要進行同步了。
下面介紹實作步驟
1 使用nuget安裝redis緩存 StackExchange.Redis
2 使用nuget安裝RedisSession服務 RedisSessionStateProvider
3 從nuget添加RedisSession之後,它會在你的config檔案中寫入以下内容,主要是對session進行持久化設定的
<sessionState mode="Custom" customProvider="MySessionStateStore">
<providers>
<!-- Either use 'connectionString' and provide all parameters as string OR use 'host','port','accessKey','ssl','connectionTimeoutInMilliseconds' and 'operationTimeoutInMilliseconds'. -->
<!-- 'throwOnError','retryTimeoutInMilliseconds','databaseId' and 'applicationName' can be used with both options. -->
<!--
<add name="MySessionStateStore"
host = "127.0.0.1" [String]
port = "" [number]
accessKey = "" [String]
ssl = "false" [true|false]
throwOnError = "true" [true|false]
retryTimeoutInMilliseconds = "5000" [number]
databaseId = "0" [number]
applicationName = "" [String]
connectionTimeoutInMilliseconds = "5000" [number]
operationTimeoutInMilliseconds = "1000" [number]
connectionString = "<Valid StackExchange.Redis connection string>" [String]
loggingClassName = "<Assembly qualified class name that contains logging method specified below>" [String]
loggingMethodName = "<Logging method should be defined in loggingClass. It should be public, static, does not take any parameters and should have a return type of System.IO.TextWriter.>" [String]
/>
-->
<add name="MySessionStateStore" type="Microsoft.Web.Redis.RedisSessionStateProvider" host="127.0.0.1" accessKey="" ssl="false" />
</providers>
</sessionState>
4 下載下傳是新版本的redis服務端,可以是windows版的,我用的是2.6.13,低版本的redis會出現Eval指令無法識别的問題
5 處理完成,可以測試你的session了,預設過期時間為1200秒
前台使用Session時和原來沒有任何分别
public ActionResult TestSession()
{
Session["username"] = "zzl";
Session["test"] = "hello world!";
return Content("完成..." + Session["test"]);
}
這種不修改以有代碼就可以實作不同功能政策的方式就是我們的IoC,控制反轉技術(也是依賴注入DI的範疇),這也是程式設計語言發展到一定階段的必然産物,即解決複雜的業務的應對之道!
下面是網友對rediscache進行的擴充,讓它支援複雜類型,預設支援簡單類型,如果希望支援複雜類型,需要為類型添加“可序列化”的特性,因為我們在redis裡存儲時,都是以二進制位元組數組的形式存儲的。
/// <summary>
/// 對RedisCache的擴充,讓它支援複雜類型、
/// RedisValue 類型可以直接使用位元組數組,是以,
/// 調用 Get 幫助程式方法時,它會将對象序列化為位元組流,然後再緩存該對象。
/// 檢索項目時,項目會重新序列化為對象,然後傳回給調用程式。
/// </summary>
public static class SampleStackExchangeRedisExtensions
{
public static T Get<T>(this IDatabase cache, string key)
{
return Deserialize<T>(cache.StringGet(key));
}
public static object Get(this IDatabase cache, string key)
{
return Deserialize<object>(cache.StringGet(key));
}
public static void Set(this IDatabase cache, string key, object value)
{
cache.StringSet(key, Serialize(value));
}
static byte[] Serialize(object o)
{
if (o == null)
{
return null;
}
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (MemoryStream memoryStream = new MemoryStream())
{
binaryFormatter.Serialize(memoryStream, o);
byte[] objectDataAsStream = memoryStream.ToArray();
return objectDataAsStream;
}
}
static T Deserialize<T>(byte[] stream)
{
if (stream == null)
{
return default(T);
}
BinaryFormatter binaryFormatter = new BinaryFormatter();
using (MemoryStream memoryStream = new MemoryStream(stream))
{
T result = (T)binaryFormatter.Deserialize(memoryStream);
return result;
}
}
}
對複雜類型進行存儲和讀取的方法如下
cache.Set("zzlList", new List<TestCache> { new TestCache { ID = 1, Name = "占占", AddTime = DateTime.Now } });
var o = cache.Get("zzlList");
回到目錄
作者:倉儲大叔,張占嶺,
榮譽:微軟MVP
QQ:853066980
支付寶掃一掃,為大叔打賞!
