1. 程式人生 > >.NET下實現分散式快取系統Memcached

.NET下實現分散式快取系統Memcached

IT168 技術文件】在Web應用程式中,資料通常儲存在RDBMS中,應用伺服器從資料庫中讀取資料並在瀏覽器中顯示。但隨著資料量的增大、訪問的集中,就會出現RDBMS的負載加重、資料庫響應變慢、網站顯示延遲等重大影響。為了緩解資料庫的壓力,提升Web應用程式的響應速度,人們提出了Web快取的概念,這裡快取的概念不同於計算機硬碟控制器上的一塊記憶體晶片。Web快取位於Web伺服器(1個或多個,內容源伺服器)和客戶端之間(1個或多個),快取會根據進來的請求儲存輸出內容的副本,例如html頁面, 圖片,檔案(統稱為副本),然後,當下一個請求來到的時候,如果是相同的URL,快取直接使用副本響應訪問請求,而不是向內容源伺服器再次傳送請求。使用快取可以減少相應延遲,因為請求在快取伺服器(離客戶端更近)而不是源伺服器被相應,這個過程耗時更少,讓web伺服器看上去相應更快;當副本被重用時還可以減少

網路頻寬消耗。

  快取的工作方式

  快取的工作方式如下圖所示:

  上圖中的快取伺服器維護一個集中快取並在其中存放經常被請求的物件,任何 Web 瀏覽器客戶端都可以訪問該快取。來自記憶體/磁碟快取的物件所需的處理資源比來自其他網路的物件所需的處理資源要少得多。因此,這可以提高客戶端瀏覽器效能、縮短使用者響應時間並減少Internet 連線所消耗的頻寬。

  上圖1到6標示了當使用者請求物件時,快取伺服器是如何響應的,主要經過下列步驟:

  第一個使用者(客戶端 1)請求 Web 物件。

  快取伺服器檢查該物件是否存在於快取中。由於該物件不存在於快取伺服器快取中,因此,快取伺服器從Internet中的伺服器請求該物件。

  Internet上的伺服器將該物件返回給快取伺服器計算機。

  快取伺服器將該物件的一個副本保留在其快取中,並將物件返回給客戶端 1。

  客戶端 2請求相同的物件。

  快取伺服器從其快取中返回該物件,而不是從Internet中獲取該物件。

  一般在組織的Web伺服器前面部署快取伺服器。Web伺服器是主持商業 Web 業務或可由業務合作伙伴訪問的伺服器。使用傳入的Web請求,快取伺服器可以充當外部環境的 Web 伺服器,並通過其快取來完成客戶端對Web內容的請求。只有在快取無法處理請求時,快取伺服器才將請求轉發到Web伺服器。

  目前實現快取的機制有幾種,Memcached就是其中的一種。本文介紹了Memcached的概念,基本原理以及工作機制,並介紹瞭如何在ASP.NET中使用Memcache進行開發Web應用程式以提升Web應用程式的效能。

  Memcached介紹

  Memcached是一個高效能的分散式的記憶體物件快取系統。Memcached是為了加快http://www.livejournal.com/訪問速度而誕生的一個專案,由Danga Interactive開發的,它通過在記憶體裡維護一個統一的巨大的hash表來儲存各種格式的資料,包括影象、視 頻、檔案以及資料庫檢索的結果等。雖然最初為了加速 LiveJournal 訪問速度而開發的,但是後來被很多大型的網站採用。它的快取是一種分散式的,也就是可以允許不同主機上的多個使用者同時訪問這個快取系統,這種方法不僅解決了共享記憶體只能是單機的弊端,同時也解決了資料庫檢索的壓力,最大的優點是提高了訪問獲取資料的速度,Memcached用於在動態應用中減少資料庫負載,提升訪問速度,但是用來加速Web應用、降低資料庫負載時比較多。Memcached也完全可以用到其他地方,比如分散式資料庫,分散式計算等領域。

Memcache的特點

  Memcached作為高速執行的分散式快取伺服器,具有以下的特點。

   協議簡單。Memcached的伺服器客戶端通訊並不使用複雜的XML等格式, 而使用簡單的基於文字行的協議。因此,通過telnet也能在memcached上儲存資料、取得資料。

   基於libevent的事件處理,libevent是一個事件觸發的網路庫,適用於windows、linux、bsd等多種平臺,內部使用select、epoll、kqueue等系統呼叫管理事件機制。而且libevent在使用上可以做到跨平臺,而且根據libevent官方網站上公佈的資料統計,似乎也有著非凡的效能。

   內建記憶體儲存方式。為了提高效能,memcached中儲存的資料都儲存在memcached內建的記憶體儲存空間中。 由於資料僅存在於記憶體中,因此重啟memcached、重啟作業系統會導致全部資料消失。 另外,內容容量達到指定值之後,就基於LRU(Least Recently Used)演算法自動刪除不使用的快取。 memcached本身是為快取而設計的伺服器,因此並沒有過多考慮資料的永久性問題。memcached預設情況下采用了名為Slab Allocator的機制分配、管理記憶體。 在該機制出現以前,記憶體的分配是通過對所有記錄簡單地進行malloc和free來進行的。 但是,這種方式會導致記憶體碎片,加重作業系統記憶體管理器的負擔,最壞的情況下,會導致作業系統比memcached程序本身還慢。

  memcached不互相通訊的分散式。memcached儘管是“分散式”快取伺服器,但伺服器端並沒有分散式功能。各個memcached不會互相通訊以共享資訊。那麼,怎樣進行分散式呢?這完全取決於客戶端的實現。Cache::Memcached的分散式方法簡單來說,就是“根據伺服器臺數的餘數進行分散”。 求得鍵的整數雜湊值,再除以伺服器臺數,根據其餘數來選擇伺服器。

  Memcached的快取是一種分散式的,可以讓不同主機上的多個使用者同時訪問, 因此解決了共享記憶體只能單機應用的侷限,更不會出現使用資料庫做類似事情的時候,磁碟開銷和阻塞的發生。

  Memcached使用了libevent(如果可以的話,在linux下使用epoll)來均衡任何數量的開啟連結,使用非阻塞的網路I/O, 對內部物件實現引用計數(因此,針對多樣的客戶端,物件可以處在多樣的狀態), 使用自己的頁塊分配器和雜湊表, 因此虛擬記憶體不會產生碎片並且虛擬記憶體分配的時間複雜度可以保證為O(1)。

  許多語言都實現了連線memcached的客戶端,其中以Perl、PHP為主。 僅僅memcached網站上列出的語言就有Perl、PHP、Python、Ruby、C#、C/C++等等。

  Memcached的工作機制

  Memcached通過在記憶體中開闢一塊區域來維持一個大的hash表來加快頁面訪問速度,雖然和資料庫是獨立的,但是目前主要用來快取資料庫的資料。允許多個server通過網路形成一個大的hash,使用者不必關心資料存放在哪,只調用相關介面就可。存放在記憶體的資料通過LRU演算法進行淘汰出記憶體。同時可以通過刪除和設定失效時間來淘汰存放在記憶體的資料。

Memcached在.NET中的應用

  一.Memcached伺服器端的安裝(此處將其作為系統服務安裝)

  下載檔案:memcached 1.2.1 for Win32 binaries (Dec 23, 2006)

  下載地址:http://jehiah.cz/projects/memcached-win32/files/memcached-1.2.1-win32.zip

  1.解壓縮檔案到c:\memcached

  2.命令列輸入 c:\memcached\memcached.exe -d install'

  3.命令列輸入 c:\memcached\memcached.exe -d start ,該命令啟動 Memcached ,預設監聽埠為 11211

  通過 memcached.exe -h 可以檢視其幫助,檢視memcache狀態,telnet 192.168.0.98 11211。輸入stats查詢狀態

   stats

   STAT pid 8601

   STAT uptime 696

  STAT time 1245832689

   STAT version 1.2.0

   STAT pointer_size 64

   STAT rusage_user 0.007998

   STAT rusage_system 0.030995

   STAT curr_items 1

   STAT total_items 1

   STAT bytes 76

   STAT curr_connections 2

   STAT total_connections 4

   STAT connection_structures 3

   STAT cmd_get 1

   STAT cmd_set 1

   STAT get_hits 1//命中次數

   STAT get_misses 0 //失效次數

   STAT bytes_read 97

   STAT bytes_written 620

   STAT limit_maxbytes 134217728

   END

   -d選項是啟動一個守護程序

   -m是分配給Memcache使用的記憶體數量,單位是MB,我這裡是10MB

   -u是執行Memcache的使用者

   -l是監聽的伺服器IP地址,如果有多個地址的話,我這裡假定指定了伺服器的IP地址為本機ip地址

      -p是設定Memcache監聽的埠,我這裡設定了12000,最好是1024以上的埠

   -c選項是最大執行的併發連線數,預設是1024,我這裡設定了256,按照你伺服器的負載量來設定

   -P是設定儲存Memcache的pid檔案

  二..NET memcached client library(memcached的.NET客戶端類庫)

  下載memcached的.NET客戶端類庫,下載地址:https://sourceforge.net/projects/memcacheddotnet/裡面有.net1.1 和 .net2.0的兩種版本,裡面還有.NET應用memcached的例子。

三.應用

  1.新建ASP.NET站點,將Commons.dll,ICSharpCode.SharpZipLib.dll,log4net.dll,Memcached.ClientLibrary.dll新增到web引用。

  2.為了進行後續的測試,我們建立兩個aspx頁面,memcache.aspx和nomemcache.aspx,memcache.aspx是使用MemcacheClient類加入了快取機制的頁面。nomemcache.aspx是沒有加入快取機制的頁面,直接連線的資料庫。一會我們通過觀察資料庫事件和進行壓力測試來測試在壓力測試的情況下應用程式的效能。

  3.memcache.aspx.cs中新增對Memcached.ClientLibrary.dll的引用,即:using Memcached.ClientLibrary;Page_Load()中加入如下程式碼。

  protected void Page_Load(object sender, EventArgs e)

  {

  string[] serverlist = new string[] { "127.0.0.1:11211" };

  string poolName = "MemcacheIOPool";

  SockIOPool pool = SockIOPool.GetInstance(poolName);

  //設定連線池的初始容量,最小容量,最大容量,Socket 讀取超時時間,Socket連線超時時間

  pool.SetServers(serverlist);

  pool.InitConnections = 1;

  pool.MinConnections = 1;

  pool.MaxConnections = 500;

  pool.SocketConnectTimeout = 1000;

  pool.SocketTimeout = 3000;

  pool.MaintenanceSleep = 30;

  pool.Failover = true;

  pool.Nagle = false;

  pool.Initialize();//容器初始化

  //例項化一個客戶端

  MemcachedClient mc = new MemcachedClient();

  mc.PoolName = poolName;

  mc.EnableCompression = false;

  string key = "user_info";//key值

  object obj = new object();

  if (mc.KeyExists(key)) //測試快取中是否存在key的值

  {

  obj = mc.Get(key);

  User user2 = (User)obj;

  Response.Write("
" + user2.Name + "," + user2.Pwd + "
");

  }

  else {

  string conStr = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;

  SqlConnection conn = new SqlConnection(conStr);

  conn.Open();

  string sql = "Select * From T_User Where id=1";

  SqlCommand cmd = new SqlCommand(sql, conn);

  SqlDataReader dr = cmd.ExecuteReader();

  User user = new User();

  while (dr.Read())

  {

  user.Name = dr["name"].ToString();

  user.Pwd = dr["pwd"].ToString();

  }

  dr.Close();

  conn.Close();

  mc.Set(key, user, System.DateTime.Now.AddMinutes(2)); //儲存資料到快取伺服器,這裡將user這個物件快取,key 是"user_info1"

  Response.Write("
姓名:" + user.Name + ",密碼:" + user.Pwd + "
");

  }

  }

  4.nomemcache.aspx是沒有加快取機制的直接連線資料庫的頁面。nomemcache.aspx.cs中的程式碼:

  protected void Page_Load(object sender, EventArgs e)

  {

  string conStr = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;

  SqlConnection conn = new SqlConnection(conStr);

  conn.Open();

  string sql = "Select * From T_User Where id=2";

  SqlCommand cmd = new SqlCommand(sql, conn);

  SqlDataReader dr = cmd.ExecuteReader();

  User user = new User();

  while (dr.Read())

  {

  user.Name = dr["name"].ToString();

  user.Pwd = dr["pwd"].ToString();

  }

  dr.Close();

  conn.Close();

  Response.Write("
姓名:" + user.Name + ",密碼:" + user.Pwd + "
");

  }

  }

  5.測試

  測試memcache.aspx頁面,該測試的主要目的是訪問memcache.aspx頁面,看是否看該頁面走的是memcached而非訪問的資料庫(第一次是訪問資料庫)。首先,我們執行memcache.aspx頁面,通過Sql Server Profiler來檢視執行memcache.aspx頁面對資料庫的操作情況。第一次執行memcache.aspx的時候,Sql Server Profiler裡面顯示memcache.aspx對資料庫的操作,即執行了Select * From T_User Where id=1。

  memcache.aspx頁面上第一次執行的時候顯示如下資訊:

  通過讀取資料庫得到的資料:

  姓名:lucy,密碼:lucy。

  接著我們重新整理memcache.aspx頁面,頁面上還顯示上述資訊:

  通過讀取快取得到的資料:

  姓名:lucy,密碼:lucy

  但從Sql Server Profiler觀察,memcache.aspx頁面沒有對資料庫進行任何操作。說明我們第二次訪問該頁面是讀取的快取,接著不停的重新整理頁面,都顯示的是通過讀取快取得到的資料。直到到達快取失效時間。

  測試nomemcache.aspx,我們執行nomemcache.aspx頁面,每重新整理一次(包括第一次),Sql Server Profiler都記錄了,nomemcache.aspx頁面對資料庫進行的操作,即之行了Select * From T_User Where id=2語句。說明每訪問一次該頁面,都要進行一次資料庫的訪問操作。

四.壓力測試以及效能分析

  這裡我們使用Microsoft Web Application Stress Tool對web進行壓力測試,Microsoft Web Application Stress Tool 是由微軟的網站測試人員所開發,專門用來進行實際網站壓力測試的一套工具。透過這套功能強大的壓力測試工具,您可以使用少量的客戶端計算機模擬大量使用者上 線對網站服務所可能造成的影響,在網站實際上線之前先對您所設計的網站進行如同真實環境下的測試,以找出系統潛在的問題,對系統進行進一步的調整、設定工 作。就是因為這些特性,才使它具備了DOS轟炸的功能。

  1、工具簡單設定

  開啟Web Application Stress Tool,很簡潔的一個頁面,上面是工具欄,左下方是功能選項,右下方是詳細設定選項。在對目標Web伺服器進行壓力測試之前,先對它進行一些必要的設定。

  (1).在“settings”的功能設定中(如下圖),一個是Stress level (threads)這裡是指定程式在後臺用多少執行緒進行請求,也就是相當於模擬多少個客戶機的連線,更加形象的就是說設定多少轟炸的執行緒數。一般填寫 500~1000,因為這個執行緒數是根據本機的承受力來設定的,如果你對自己的機器配置有足夠信心的話,那麼設定的越高,轟炸的效果越好。

  (2).在“Test Run Time”中來指定一次壓力測試需要持續的時間,分為天、小時、分、秒幾個單位級別,你根據實際情況來設定吧!這裡面設定測試時間為1分鐘。

  (3).其餘的選項大家可以根據自己的情況設定。

  2、壓力測試

  步驟1:在工具中點右鍵,選擇Add命令,增加了一個新的測試專案:memcache,對它進行設定,在主選項中的server中填寫要測試的伺服器的IP地址,這裡我們是在本機上進行測試,所以填寫localhost。在下方選擇測試的Web連線方式,這裡的方式Verb選擇 get,path選擇要測試的Web頁面路徑,這裡填寫/WebMemCache/memcache.aspx,即加入快取的memcache.aspx頁面(如下圖)。

  步驟2:在“Settings”的功能設定中將Stress level (threads)執行緒數設定為500。完畢後,點工具中的灰色三角按鈕即可進行測試(如下圖)。

  同理,我們在建一個nomemcach的專案用來測試nomemcache.aspx頁面。Memcach和nomemcach測試完畢後,點選工具欄上的Reports按鈕檢視測試報告:

  3.效能分析

  Memcache.aspx的測試報告:

  Overview

  ================================================================================

  Report name: 2009-7-20 10:52:00

  Run on: 2009-7-20 10:52:00

  Run length: 00:01:12

  Web Application Stress Tool Version:1.1.293.1

  Number of test clients: 1

  Number of hits: 2696

  Requests per Second: 44.93

  Socket Statistics

  --------------------------------------------------------------------------------

  Socket Connects: 3169

  Total Bytes Sent (in KB): 646.80

  Bytes Sent Rate (in KB/s): 10.78

  Total Bytes Recv (in KB): 2019.37

  Bytes Recv Rate (in KB/s): 33.65

  Socket Errors

  --------------------------------------------------------------------------------

  Connect: 0

  Send: 0

  Recv: 0

  Timeouts: 0

  RDS Results

  --------------------------------------------------------------------------------

  Successful Queries: 0

  Page Summary

  Page Hits TTFB Avg TTLB Avg Auth Query

  ================================================================================

  GET /WebMemCache/memcache.aspx 2696 1.94 1.95 No No

  Nomemcache.aspx的測試報告:

  Overview

  ================================================================================

  Report name: 2009-7-20 10:54:01

  Run on: 2009-7-20 10:54:01

  Run length: 00:01:12

  Web Application Stress Tool Version:1.1.293.1

  Number of test clients: 1

  Number of hits: 2577

  Requests per Second: 42.95

  Socket Statistics

  --------------------------------------------------------------------------------

  Socket Connects: 2860

  Total Bytes Sent (in KB): 589.32

  Bytes Sent Rate (in KB/s): 9.82

  Total Bytes Recv (in KB): 1932.75

  Bytes Recv Rate (in KB/s): 32.21

  Socket Errors

  --------------------------------------------------------------------------------

  Connect: 0

  Send: 0

  Recv: 0

  Timeouts: 0

  RDS Results

  --------------------------------------------------------------------------------

  Successful Queries: 0

  Page Summary

  Page Hits TTFB Avg TTLB Avg Auth Query

  ================================================================================

  GET /WebMemCache/nomemcache.aspx 2577 4.75 4.79 No No

  從測試報告上看出memcache.aspx頁面在一分鐘內的Hits(命中次數)2696,平均TTFB是(Total Time to First Byte)1.94,平均TTLB(Total Time to Last Byte)是1.95。這些引數都低於nomemcache.aspx。另外memcache.aspx的Requests per Second(每秒請求的次數)是 44.93高於nomemcache.aspx頁面的42.95.這些引數都說明memcache.aspx頁面的執行效能要高於nomemcache.aspx頁面。快取起到了提高效能的作用。當然我這裡面進行的測試只是模擬500個使用者在1分鐘內的訪問對Web伺服器效能的影響。

  總結

  本文簡單介紹了Memcached的基本原理,特點以及工作方式,接下來介紹了Windows下Memcached伺服器端程式的安裝方法、在.NET應用程式中使用.NET memcached client library。接下來通過執行分析程式來了解memcached的工作原理機制,最後通過壓力測試工具對沒有加入Memcached機制的頁面和加入Memcached頁面進行了壓力測試,對比加入Memcached機制前後Web應用程式的效能。瞭解Memcached內部構造, 就能知道如何在應用程式中使用memcached才能使Web應用的速度更上一層樓。提升web應用程式的效能和訪問速度。