如果你想增加網站的效率,達到分散式暫存的功能,memcached或許就是你要找的。Facebook也是用這一套。
首先取得相關資源。我用的是memcached Win32版本 http://jehiah.cz/projects/memcached-win32/ version 1.2.1
然後要一個memcached用戶端 http://memcachedproviders.codeplex.com/ version 1.2
記得把用戶端的使用手冊也要一份來讀一下,我開始時沒有手冊浪費了很多日時間。
然後我會跟大家分享一些使用心得。
官方的文件只有一點點,新手也不好懂,所以先簡單握要地說明一下memcached是要做甚麼的。
1. Memcached是一個通用的分散式暫存伺服器系統。
意思是它可以同時運作多個伺服器,編寫程式時可以把它看成一個大的雜湊,可以用任何程式語言存取它。
2. 它並不會儲存物件,你需要把物件序列化才能儲存到暫存裡。
3. 不管發生其麼事它都不會產生例外,這樣才不會影響程式運作。
我會集中講怎樣使用memcached,而不會解釋怎樣去建置,因為建置不困難,大概沒有人會有問題。
接下來就要為你的應用程式建立用戶端,解壓縮你下載回來的檔案,把三個.dll都加到你專案的參考裡。
然後在web.config或app.config裡的<configSections>區塊加入下列設定:
<section name="cacheProvider" type="MemcachedProviders.Cache.CacheProviderSection, MemcachedProviders" allowDefinition="MachineToApplication" restartOnExternalChanges="true"/> <sectionGroup name="enyim.com"> <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching"/> </sectionGroup> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
這個設定會告訴應用程式將會有一個<cacheprovider>組態和一個<log4net>組態。還會有一個<enyim.com>組態,它裡面還會包含一個<memcached>區塊。你可以直接複制貼上這裡的程式碼,應該不會有問題。
然後在<configuration>區塊裡加入下面的詳細設定。
<cacheProvider defaultProvider="MemcachedCacheProvider">
<providers>
<add name="MemcachedCacheProvider" type="MemcachedProviders.Cache.MemcachedCacheProvider, MemcachedProviders"
keySuffix="_MySuffix_" defaultExpireTime="2000"/>
</providers>
</cacheProvider>
<enyim.com>
<memcached>
<servers>
<add address="192.168.1.2" port="11211" />
</servers>
<socketPool minPoolSize="10" maxPoolSize="100" connectionTimeout="00:00:10" deadTimeout="00:02:00" />
</memcached>
</enyim.com>
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}]- %message%newline" />
</layout>
</appender>
<root>
<priority value="WARN"/>
<appender-ref ref="ConsoleAppender">
<filter type="log4net.Filter.LevelRangeFilter">
<levelMin value="WARN"/>
<levelMax value="FATAL"/>
</filter>
</appender-ref>
</root>
</log4net>
你可以設定一些如預設過期時間等。<servers>區塊裡的<address>就是memcached伺服器的位置,11211是預設的連接埠。
暫存字串和序列化的物件應該是你已經會的事情,序列化一般簡單的類別只需要為類別加上[Serializable]標籤。
現在來看看怎樣和LINQ一起使用。
要序列化LINQ的物件,首先打開.dbml的設計介面,把序列化模式設定為單向。
然後你需要使用DataContractSerializer去實行物件的序列化。更多資訊可以看這裡。
.NET有提供好幾種序列器。XML, binary, JSON, 等。我的例子會使用JSON,因為它的效率應該比XML好。
下面的程式碼會示範怎樣序列化和儲存到暫存。
//建立特定類別的序列器
DataContractJsonSerializer serializeProvider = new DataContractJsonSerializer(typeof(myClass[]));
//使用一個記憶體流做緩衝.因為序列器不會直接輸出字串
using (MemoryStream ms = new MemoryStream())
{
serializeProvider.WriteObject(ms, myClassArrayObject);
byte[] l_buffer = new byte[ms.Length];
ms.Position = 0;
//如果序列化結果長度大於int的長度,會跳過,但你可以根據你的需求作任何處理
if (ms.Length < int.MaxValue)
{
ms.Read(l_buffer, 0, (int)ms.Length);
string l_serialized = Encoding.Unicode.GetString(l_buffer);
//移除可能存在的相同雜湊值暫存
DistCache.Remove("keyString");
DistCache.Add("keyString", l_serialized);
}
else
{
throw new Exception("object data large.");
}
}
然後你可以用telnet去檢查你是否成功把序列化後的物件儲存到memcached裡。
Telnet 到你的伺服器,輸入指令'stats',就可以看到目前memcached的狀態。
curr_items 是目前memcached裡暫存物件的數量。
怎樣選擇好的雜湊值,有很多前人的常規可以跟著用。但我不會在這裡多說明。
我用的方法是 Application:Method:Parameters:Salt 然後用SHA256去產生值,再轉成base64格式。
作為範例這樣的方法應該夠用,你可以設計你自己的雜湊值產生法。
接下來就是取得並反序列化你的暫存。
string l_serialized = (string)DistCache.Get("keyString");
DataContractJsonSerializer serializeProvider = new DataContractJsonSerializer(typeof(myClass[]));
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(l_serialized)))
{
myClass[] members = (myClass[])serializeProvider.ReadObject(ms);
} 你可以用這方法序列化並暫存你的物件、物件陣列、物件集合等。
但要記得你從暫存取出來的物件是在不同的LINQ資料背景(DataContext)。
如果你要更新或刪除這些資料,要再做一些處理。
有時間我會在別的文章再探討這個問題。