如何構建高效能web站點之 分布式快取

2022-08-28 15:39:32 字數 4336 閱讀 4529

要明白資料庫前段的緩衝區,首先要明白什麼是檔案系統核心緩衝區(buffer area):它位於物理記憶體的核心位址空間,除了使用o_direct標記開啟的檔案以外,所有對磁碟的讀寫操作,都需要經過它,所以,可以把它看作磁碟的前段裝置。

這塊核心緩衝區也稱為:頁快取記憶體(page cache),實際上它包括兩部分:

1、讀快取區

2、寫快取區

讀緩衝區儲存著系統最近從磁碟上讀取的資料,一旦下次需要這些資料,那麼核心將直接在讀快取區中獲得,而不需要再次讀取磁碟。

寫快取區的主要作用是減少對磁碟的物理寫操作,通常情況下,向磁碟的寫操作並不著急,程式的執行並不會因為磁碟的寫操作而等待,核心緩衝區可以將多個寫操作指令累積起來,通過一次磁碟的磁頭移動來完成,當然,寫快取區會導致資料的實際寫入延長幾秒,在實際寫入之前,這些資料被稱為dirty page ,髒頁。

實際上,從職能上來看,將寫快取區叫做緩衝區更加形象,緩衝區的例子在生活中隨處可見,例如城市的十字路口,它就像乙個寫緩衝區,紅燈亮起的時候,車輛都停在緩衝區,當綠燈時,車輛依次前進,就像核心中的資料積累到一定程度時被寫入磁碟。同樣,我們可以在資料庫和動態內容之間建立一層快取區,它可以獨立部署在伺服器上,用於加速資料庫的讀寫操作,這個快取區實際上是由動態內容來控制的。這個時候就使用到了memcached。

首先為了實現快取記憶體,我們不會將快取內容放在磁碟上,基於這個原則,memcached使用物理記憶體來作為快取區,當我們啟動memcached的時候,需要指定分配給快取區的記憶體大小,比如分配4g

s-colin:~ # memcached -d -m 4086 -l 10.0.1.12 -p 11711
memcached 使用key-value 的方式來儲存資料,每個資料之間相互獨立,每個資料都已key作為唯一的索引。

由於快取區是有大小限制的,一旦快取區沒有足夠的空間儲存新的資料項的時候,memcached便會想辦法淘汰一些資料項來騰出空間,淘汰機制基於lru(least recently used)演算法,將最近不常訪問的資料項淘汰掉。一般都是為其設定過期時間,過期時間的取值,需要根據自己站點來平衡把握。

作為分布式系統,memcached可以獨立執行在伺服器上,動態內容通過 tcp  socket 來訪問它,這樣一來,memcached 本身的網路併發處理能力尤為重要。memcached 使用libevent 函式庫來實現網路併發模型,其中包括epoll,所以在較大併發使用者數的情況下,我們仍然可以放心使用memcached。

我們可以在memcached上儲存什麼樣的資料呢?這需要考慮到網路傳輸,意思就是,我們可以在網路傳輸中傳輸什麼樣的內容?哈哈,自然是二進位制了,那麼,對於陣列或者物件這樣的抽象資料型別而言,是否可以儲存在memcached中呢?

基於序列化機制,沒有可以將更好層次的抽象資料型別轉化為二進位制字串,以便通過網路進入快取伺服器,同時,在讀取這些資料的時候,二進位制字串又可以轉換回原來的資料型別。

有點需要注意的是,我們在試圖將乙個類的物件進行序列化時,物件的成員函式是不會被序列化的,被序列化的知識物件的資料成員。當需要從持久化資料中恢復物件時(也就算反序列化時),我們會首先例項化乙個新的物件,然後將之前持久化的資料成員依次賦值給新物件的相應資料成員。順便提下,json格式,可以很好的應用在序列化中,任何陣列和物件都可以很容易的與json格式的字串互相轉換,且計算量不大。

很早以前,我們喜歡將使用者id直接寫入瀏覽器的cookies,並以此為榮,但是黑客很容易的篡改本地cookies來冒充其他使用者,這時候新的方法出現了,那就是在使用者登入的時候,我們會給其乙個ticket字串, 並將它寫入瀏覽器cookies,隨後的每次請求,我們都檢查這個ticket,由於客戶不知道我們發給其他使用者的ticket,所以無法冒充其他使用者。

但是有一點即使我們的查詢效率很高,查詢本身還是存在開銷的,這很大程度上在於資料庫的i/o操作,這個時候,就需要memcached了。這個時候應該充分的利用emcached的序列化,並且設定快取資料的有效期,但是提醒一點,如果是使用者登出了登入的話,記得清楚memcached中的登入狀態快取。

對於乙個資料庫寫操作頻繁的站點來說,通過引入寫快取來減少寫資料庫的次數顯得至關重要。通常的資料寫操作包括插入、更新、刪除,這些操作的同時可能又伴隨著條件查詢和索引的更新,所以這東西的開銷往往是讓人印象深刻的。

這個時候,就會用到memcached的原子遞增操作,事實上,也正是因為它,我們才會考慮在訪問量遞增更新的應用中引入寫快取,寫快取的本質是,在對資料庫的寫入操作累積到你程式定義的數量時,它在一次行的去執行這些操作,雖然實際的寫入往往會延遲幾秒鐘,但是通常情況下,我們對寫入的操作也不是要求實時的,這樣既提高了效率又滿足了我們業務的需求,何樂不為?

作為乙個分布式系統,雖然memcached能夠出色的完成你交給它的任務,但是並不是代表你能對它放任不管,相反,我們需要知道它的執行狀況,memcached提供了這樣的協議,可以讓你獲得對它的實時狀態。

來看個包括快取狀態的陣列:

真的很全面,比如 uptime表示memcached持續執行的時間;cmd_get表示讀取資料項的次數;cmd_set表示更新資料項的次數;get_hits表示快取命中的次數;bytes_read表示讀取位元組的總數;bytes表示快取區已經使用的大小;limit_maxbytes表示快取區的總大小。

以上這麼多的資訊,我們可以從三個方面去看:

持續關注快取空間的使用率,可以讓我們知道何時需要為快取系統擴容,以避免由於快取空間已滿造成的資料被動淘汰,有些資料項在過期之前被lru演算法淘汰可能會造成一定不良後果。

終端使用者訪問加速節點時,如果該節點有快取住了要被訪問的資料時就叫做命中,如果沒有的話需要回原伺服器取,就是沒有命中。取資料的過程與使用者訪問是同步進行的,所以即使是重新取的新資料,使用者也不會感覺到有延時。 命中率=命中數/(命中數+沒有命中數), 快取命中率是判斷加速效果好壞的重要因素之一。非常教科書式的解釋,大家自行消化。

我們還需要關注memcached中資料項讀寫位元組數的增長速度,這反應了它的工作量,我們從中可以得知memcached是忙還是空閒。同時我們也可能希望在監控系統中整合對memcached的監控,例如cacti監控系統,後面學習。

有很多理由讓我們不得不擴充套件memcached的規模,包括併發處理能力和快取空間容量等,不論哪個達到了極限,擴充套件都在所難免。對於快取空間的容量,擴充套件既意味著增加物理記憶體,這有點不切實際,而對於併發處理能力,這正是memcached的特長所在,所以,我們只能增加快取伺服器來達到擴充套件的目的。

當有多台快取伺服器的時候,我們面臨的是如何將快取資料均衡的分布在多台伺服器上,

一種是我們可以以商業邏輯來劃分設計,另外一種是基於key的劃分方式

比如一台用來快取使用者登入狀態,一台用來快取訪問量統計:

10.0.1.12-->使用者登入狀態快取

10.0.1.13-->訪問量統計快取

有兩個問題出現:

一是這兩台伺服器的工作量均衡麼?

二是如果兩台仍不能滿足需要,那如何繼續擴充套件呢?

對於第乙個問題,嚴格來說,要想達到真正的均衡是不現實的,由於它們的職責所在不同,它們的開銷和訪問率也不盡相同,所以有的只是相對的均衡。

對於第二個問題,加入訪問量統計快取需要擴充套件,那麼我們準備一台新的伺服器:10.0.1.14.然後將訪問量統計快取再次劃分,同樣基於業務邏輯為基礎,例如將子站點劃分為兩部分,讓它們分別儲存在兩台伺服器上,這樣就形成了:

10.0.1.12-->使用者登入狀態快取

10.0.1.13-->訪問量統計快取 group1

10.0.1.14-->訪問量統計快取 group2

為此,我們需要設計一種不需要依賴資料項內容的雜湊演算法,將所有資料項的key均衡分配在這三颱快取伺服器上。乙個簡單而且有效的方法是取餘運算,就像是打撲克時的發牌,讓所有的資料項按照乙個順序在不同的快取伺服器上輪詢,這樣可以達到乙個較好的均衡。

舉個例子:

取餘之前,我們要做一些準備工作,目的是讓key變成整數,而且盡量唯一,比如這個key是:jessonlv-1986.htm

我們先對它進行md5運算,得到乙個32位元組的字串比如是:e6e87fc57lkji1245lki1547iuhgt632,同時也是乙個十六進製制的長整數,為了節省開銷,我們取這個字串的前5個位元組,然後將其轉化為十進位制數:比如945689,這個時候我們再將這個數字進行「模3」的運算。取餘的結果就是我們伺服器的編號,伺服器的編號從0開始。

這裡有個問題也許你一直在思考,那就是我們擴充套件快取系統後,由於分割槽演算法的改變,會涉及快取資料需要從一台快取伺服器遷移到另一台快取伺服器的問題,如何遷移呢?事實上,根本不需要考慮遷移的問題,因為是快取,它應該具備關鍵時刻犧牲自己的勇氣,你必須明白快取不是永續性儲存,並且從引入分布式快取時就得時刻提醒自己。

沒錯,當調整快取區演算法後,我們需要時間來等待快取的重建和預熱,但這往往並不影響站點的正常運轉,前提是你要按照文章前面堵快取和寫快取的設計理念來進行設計。。。

構建高效能Web站點 筆記四

第七章 web伺服器快取 對url對映進行快取 ssi模式下對內容的通讀 有什麼提高?需要了解url解析過程。對於apache,它提供了兩個磁碟快取和記憶體快取mod disk cache,mod mem cache。mod disk cache在磁碟上維護了一塊多個程序的快取區,在效能上比mod ...

原創 構建高效能的Web站點

原創 構建高效能的web站點 一 web站點高效能主要體現在 高可用,低成本,高效能,可擴充套件,易維護 二 構建高效能的web站點措施 1 瀏覽器端優化 快取1 瀏覽器快取 2 web負載均衡 快取2 反向 快取 3 web元件分離 快取3 動態內容快取 快取4 分布式快取 快取5 資料庫快取及效...

Web站點的傳輸 《構建高效能Web站點》閱讀1

1 資料是如何傳送的 a 應用程式將要傳輸的資料放入記憶體中 b 應用程式使用send等庫函式,通知核心將傳輸資料放入核心快取區。資料是以佇列的形式進入的,如果資料較多,則等前一波資料傳送完後,再傳送另外一撥資料,具體顯示為send會多呼叫幾次 c cpu通知網絡卡將核心緩衝區的資料存放到網絡卡緩衝...