如果你想增加網站的效率,達到分散式暫存的功能,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)。
如果你要更新或刪除這些資料,要再做一些處理。
有時間我會在別的文章再探討這個問題。