如何构建高性能web站点之:分布式缓存
生活随笔
收集整理的這篇文章主要介紹了
如何构建高性能web站点之:分布式缓存
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、數據庫前段的緩沖區
要明白數據庫前段的緩沖區,首先要明白什么是文件系統內核緩沖區(Buffer Area):它位于物理內存的內核地址空間,除了使用O_DIRECT標記打開的文件以外,所有對磁盤的讀寫操作,都需要經過它,所以,可以把它看作磁盤的前段設備。 這塊內核緩沖區也稱為:頁高速緩存(Page Cache),實際上它包括兩部分: 1、讀緩存區 2、寫緩存區讀緩存區
讀緩沖區保存著系統最近從磁盤上讀取的數據,一旦下次需要這些數據,那么內核將直接在讀緩存區中獲得,而不需要再次讀取磁盤。寫緩存區
寫緩存區的主要作用是減少對磁盤的物理寫操作,通常情況下,向磁盤的寫操作并不著急,程序的運行并不會因為磁盤的寫操作而等待,內核緩沖區可以將多個寫操作指令累積起來,通過一次磁盤的磁頭移動來完成,當然,寫緩存區會導致數據的實際寫入延長幾秒,在實際寫入之前,這些數據被稱為Dirty Page ,臟頁。實際上,從職能上來看,將寫緩存區叫做緩沖區更加形象,緩沖區的例子在生活中隨處可見,例如城市的十字路口,它就像一個寫緩沖區,紅燈亮起的時候,車輛都停在緩沖區,當綠燈時,車輛依次前進,就像內核中的數據積累到一定程度時被寫入磁盤。同樣,我們可以在數據庫和動態內容之間建立一層緩存區,它可以獨立部署在服務器上,用于加速數據庫的讀寫操作,這個緩存區實際上是由動態內容來控制的。這個時候就使用到了memcached。
二、使用memcached
key-value ?
首先為了實現高速緩存,我們不會將緩存內容放在磁盤上,基于這個原則,memcached使用物理內存來作為緩存區,當我們啟動memcached的時候,需要指定分配給緩存區的內存大小,比如分配4Gs-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算法淘汰可能會造成一定不良后果。緩存命中率
終端用戶訪問加速節點時,如果該節點有緩存住了要被訪問的數據時就叫做命中,如果沒有的話需要回原服務器取,就是沒有命中。取數據的過程與用戶訪問是同步進行的,所以即使是重新取的新數據,用戶也不會感覺到有延時。 命中率=命中數/(命中數+沒有命中數), 緩存命中率是判斷加速效果好壞的重要因素之一。非常教科書式的解釋,大家自行消化。I/O流量
我們還需要關注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變成整數,而且盡量唯一,比如這個key是:jessonlv-1986.htm
我們先對它進行md5運算,得到一個32字節的字符串比如是:e6e87fc57lkji1245lki1547iuhgt632,同時也是一個十六進制的長整數,為了節省開銷,我們取這個字符串的前5個字節,然后將其轉化為十進制數:比如945689,這個時候我們再將這個數字進行“模3”的運算。取余的結果就是我們服務器的編號,服務器的編號從0開始。
這里有個問題也許你一直在思考,那就是我們擴展緩存系統后,由于分區算法的改變,會涉及緩存數據需要從一臺緩存服務器遷移到另一臺緩存服務器的問題,如何遷移呢?事實上,根本不需要考慮遷移的問題,因為是緩存,它應該具備關鍵時刻犧牲自己的勇氣,你必須明白緩存不是持久性存儲,并且從引入分布式緩存時就得時刻提醒自己。
沒錯,當調整緩存區算法后,我們需要時間來等待緩存的重建和預熱,但這往往并不影響站點的正常運轉,前提是你要按照文章前面堵緩存和寫緩存的設計理念來進行設計。。。
轉載于:https://www.cnblogs.com/jessonlv/p/4387986.html
總結
以上是生活随笔為你收集整理的如何构建高性能web站点之:分布式缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: getInitParameter方法
- 下一篇: POJ 1160 Post Office