Memcached 是一個開源的,高性能的內存綬存軟件,從名稱上看 Mem 就是內存 的意思,而 Cache 就是緩存的意思。Memcached 的做用:經過在事先規劃好的 內存空間中臨時綬存數據庫中的各種數據,以達到減小業務對數據庫的直接高並 發訪問,從而達到提高數據庫的訪問性能,加速網站集羣動態應用服務的能力。前端
memcached 服務在企業集羣架構中有哪些應用場景?mysql
1、做爲數據庫的前端緩存應用web
a、完整緩存(易),靜態緩存redis
例如:商品分類(京東),以及商品信息,可事先放在內存裏,而後再對外提供 數據訪問,這種先放到內存,咱們稱之爲預熱,(先把數據存緩存中),用戶訪 問時能夠只讀取 memcached 緩存,不讀取數據庫了。算法
b、執點緩存(難)sql
須要前端web 程序配合,只緩存熱點的數據,即緩存常常被訪問的數據。 先預熱數據庫裏的基礎數據,而後在動態更新,選讀取緩存,若是緩存裏沒有對 應的數據,程序再去讀取數據庫,而後程序把讀取的新數據放入緩存存儲。數據庫
特殊說明 :後端
例如:稱殺只是獲取資格,而不是瞬間秒殺到手商品。數組
那麼什麼是獲取資格?緩存
2、做業集羣的 session 會話共享存儲。
特殊說明:Memcached 集羣和 web 服務集羣是不同的,全部 Memcached 的 數據總和纔是數據庫的數據。每臺 Memcached 都是部分數據。
(一臺 memcached 的數據,就是一部分 mysql 數據庫的數據)
a、程序端實現 程序加載全部 mc 的 ip 列表,經過對 key 作 hash (一致性哈希算法)
例如:web1 (key)===>對應 A,B,C,D,E,F,G…..若干臺服務器。(經過哈希算法實 現)
b、負載均衡器
經過對 key 作 hash (一致性哈希算法)
一致哈希算法的目的是不但保證每一個對象只請求一個對應的服務器,並且當節點 宕機,緩存服務器的更新從新分配比例降到最低。
a、徹底基於內存緩存的
b、節點之間相互獨立
c、C/S 模式架構,C 語言編寫,總共 2000 行代碼。
d、異步I/O 模型,使用 libevent 做爲事件通知機制。
e、被緩存的數據以 key/value 鍵值對形式存在的。
f、所有數據存放於內存中,無持久性存儲的設計,重啓服務器,內存裏的數據會 丟失。
g、當內存中緩存的數據容量達到啓動時設定的內存值時,就自動使用 LRU 算法 刪除過時的緩存數據。
h、能夠對存儲的數據設置過時時間,這樣過時後的數據自動被清除,服務自己不 會監控過時,而是在訪問的時候查看 key 的時間戳,判斷是否過時。
j、memcache 會對設定的內存進行分塊,再把塊分組,而後再提供服務。
早期的 Memcached 內存管理方式是經過 malloc 的分配的內存,使用完後經過 free 來回收內存,這種方式容易產生內存碎片,並下降操做系統對內存的管理效 率。加劇操做系統內存管理器的負擔,最壞的狀況下,會致使操做系統比memcached 進程自己還慢,爲了解決這個問題,Slab Allocation 內存分配機制 就延生了。
如今 Memcached 利用 Slab Allocation 機制來分配和管理內存。
Slab
Allocation 機制原理是按照預先規定的大小,將分配給 memcached 的內存分割 成特定長度的內存塊(chunk),再把尺寸相同的內存塊,分紅組 (chunks slab class),這些內存塊不會釋放,能夠重複利用。
並且,slab allocator 還有重複使用已分配的內存的目的。 也就是說,分配到的 內存不會釋放,而是重複利用。
Slab Allocation 的主要術語
Page
分配給 Slab 的內存空間,默認是 1MB。分配給 Slab 以後根據 slab 的大小切分紅 chunk。
Chunk
用於緩存記錄的內存空間。
SlabClass
特定大小的chunk 的組。
集羣架構方面的問題
Memcached 的神奇來自兩階段哈希(two-stage hash)。Memcached 就像一 個巨大的、存儲了不少對的哈希表。經過 key,能夠存儲或查詢任意 的數據。
客戶端能夠把數據存儲在多臺 memcached 上。當查詢數據時,客戶端首先參節點列表計算出 key 的哈希值(階段一哈希),進而選中一個節點;客戶端將請 求發送給選中的節點,而後 memcached 節點經過一個內部的哈希算法(階段二 哈希),查找真正的數據(item)。
Memcached 最大的好處就是它帶來了極佳的水平可擴展性,特別是在一個巨大的 系統中。因爲客戶端本身作了一次哈希,那麼咱們很容易增長大量 memcached 到集羣中。memcached 之間沒有相互通訊,所以不會增長 memcached 的負載; 沒有多播協議,不會網絡通訊量爆炸(implode)。memcached 的集羣很好用。 內存不夠了?增長几臺 memcached 吧;CPU 不夠用了?再增長几臺吧;有多餘 的內存?在增長几臺吧,不要浪費了。
基於 memcached 的基本原則,能夠至關輕鬆地構建出不一樣類型的緩存架構。除 了這篇 FAQ,在其餘地方很容易找到詳細資料的。
cache 相比,有什麼優缺點?
把 memcached 引入應用中,仍是須要很多工做量的。MySQL 有個使用方便的 query cache,能夠自動地緩存 SQL 查詢的結果,被緩存的 SQL 查詢能夠被反覆 地快速執行。Memcached 與之相比,怎麼樣呢?MySQL 的 query cache 是集中 式的,鏈接到該 query cache 的 MySQL 服務器都會受益。
首先,local cache 有許多與上面(query cache)相同的問題。local cache 可以利 用的內存容量受到(單臺)服務器空閒內存空間的限制。不過,localcache 有一點比 memcached 和 query cache 都要好,那就是它不但能夠存儲任 意的數據,並且沒有網絡存取的延遲。
Memcached 主要的 cache 機制是 LRU(最近最少用)算法+超時失效。當您存 數據到 memcached 中,能夠指定該數據在緩存中能夠呆多久 Which is forever, or some time in the future。若是 memcached 的內存不夠用了,過時的 slabs 會優先被替換,接着就輪到最老的未被使用的 slabs。
不實現!咱們對這個問題感到很驚訝。Memcached 應該是應用的緩存層。它的設 計自己就不帶有任何冗餘機制。若是一個 memcached 節點失去了全部數據,您 應該能夠從數據源(好比數據庫)再次獲取到數據。您應該特別注意,您的應用 應該能夠容忍節點的失效。不要寫一些糟糕的查詢代碼,寄但願於 memcache來保證一切!若是您擔憂節點失效會大大加劇數據庫的負擔,那麼您能夠採起一 些辦法。好比您能夠增長更多的節點(來減小丟失一個節點的影響),熱備節點 (在其餘節點 down 了的時候接管 IP),等等。
不處理! 在 memcached 節點失效的狀況下,集羣沒有必要作任何容錯處理。如 果發生了節點失效,應對的措施徹底取決於用戶。節點失效時,下面列出幾種方 案供您選擇:
您不該該這樣作!Memcached 是一個非阻塞的服務器。任何可能致使 memcached 暫停或瞬時拒絕服務的操做都應該值得深思熟慮。向 memcached 中批量導入數據每每不是您真正想要的!想象看,若是緩存數據在導出導入之間 發生了變化,您就須要處理髒數據了;
所以,批量導出導入數據並不像您想象中的那麼有用。不過在一個場景卻是頗有 用。若是您有大量的從不變化的數據,而且但願緩存很快熱(warm)起來,批量 導入緩存數據是頗有幫助的。雖然這個場景並不典型,但卻常常發生,所以咱們 會考慮在未來實現批量導出導入的功能。
若是一個 memcached 節點 down 了讓您很痛苦,那麼您還會陷入其餘不少麻煩。 您的系統太脆弱了。您須要作一些優化工做。好比處理」驚羣」問題(好比 memcached 節點都失效了,反覆的查詢讓您的數據庫不堪重負…這個問題在 FAQ 的其餘提到過),或者優化很差的查詢。記住,Memcached 並非您逃避優化 查詢的藉口。
沒有身份認證機制!memcached 是運行在應用下層的軟件(身份驗證應該是應用 上層的職責)。memcached 的客戶端和服務器端之因此是輕量級的,部分緣由就 是徹底沒有實現身份驗證機制。這樣,memcached 能夠很快地建立新鏈接,服務 器端也無需任何配置。
若是您但願限制訪問,您可使用防火牆,或者讓 memcached 監聽 unix domain socket。
線程就是定律(threads rule)!在 Steven Grimm 和 Facebook 的努力下, memcached 1.2 及更高版本擁有了多線程模式。多線程模式容許 memcached 能 夠充分利用多個 CPU,並在 CPU 之間共享全部的緩存數據。memcached 使用一 種簡單的鎖機制來保證數據更新操做的互斥。相比在同一個物理機器上運行多個 memcached 實例,這種方式可以更有效地處理 multi gets。
若是您的系統負載並不重,也許您不須要啓用多線程工做模式。若是您在運行一 個擁有大規模硬件的、龐大的網站,您將會看到多線程的好處。
簡單地總結一下:命令解析(memcached 在這裏花了大部分時間)能夠運行在多 線程模式下。memcached 內部對數據的操做是基於不少全局鎖的(所以這部分工 做不是多線程的)。將來對多線程模式的改進,將移除大量的全局鎖,提升 memcached 在負載極高的場景下的性能。
key 的最大長度是 250 個字符。須要注意的是,250 是 memcached 服務器端內 部的限制,若是您使用的客戶端支持」key 的前綴」或相似特性,那麼 key(前+原始 key)的最大長度是能夠超過 250 個字符的。咱們推薦使用使用較短的 key, 由於能夠節省內存和帶寬。
memcached 對 item 的過時時間有什麼限制?
過時時間最大能夠達到 30 天。memcached 把傳入的過時時間(時間段)解釋成 時間點後,一旦到了這個時間點,memcached 就把 item 置爲失效狀態。這是一 個簡單但 obscure 的機制。
1MB。若是你的數據大於 1MB,能夠考慮在客戶端壓縮或拆分到多個 key中。
爲何單個 item 的大小被限制在 1M byte 以內?
啊…這是一個你們常常問的問題!
簡單的回答:由於內存分配器的算法就是這樣的。
詳細的回答:Memcached 的內存存儲引擎(引擎未來可插拔…),使用 slabs 來 管理內存。內存被分紅大小不等的 slabs chunks(先分紅大小相等的 slabs,而後 每一個 slab 被分紅大小相等 chunks,不一樣 slab 的 chunk 大小是不相等的)。chunk 的大小依次從一個最小數開始,按某個因子增加,直到達到最大的可能值。
Memcache 客戶端僅根據哈希算法來決定將某個 key 存儲在哪一個節點上,而不考 慮節點的內存大小。所以,您能夠在不一樣的節點上使用大小不等的緩存。可是一 般都是這樣作的:擁有較多內存的節點上能夠運行多個 memcached 實例,每一個 實例使用的內存跟其餘節點上的實例相同。
關於二進制最好的信息固然是二進制協議規範:
二進制協議嘗試爲端提供一個更有效的、可靠的協議,減小客戶端/服務器端因處 理協議而產生的 CPU 時間。
根據 Facebook 的測試,解析 ASCII 協議是 memcached 中消耗 CPU 時間最多的 環節。因此,咱們爲何不改進 ASCII 協議呢?
實際上,這是一個編譯時選項。默認會使用內部的 slab 分配器。您確實確實應該 使用內建的 slab 分配器。最先的時候,memcached 只使用 malloc/free 來管理 內存。然而,這種方式不能與 OS 的內存管理之前很好地工做。反覆地 malloc/free 形成了內存碎片,OS 最終花費大量的時間去查找連續的內存塊來知足 malloc 的 請求,而不是運行 memcached 進程。若是您不一樣意,固然可使用 malloc!只 是不要在郵件列表中抱怨啊
slab 分配器就是爲了解決這個問題而生的。內存被分配並劃分紅 chunks,一直被 重複使用。由於內存被劃分紅大小不等的 slabs,若是 item 的大小與被選擇存放 它的 slab 不是很合適的話,就會浪費一些內存。Steven Grimm 正在這方面已經 作出了有效的改進。
全部的被髮送到 memcached 的單個命令是徹底原子的。若是您針對同一份數據 同時發送了一個 set 命令和一個 get 命令,它們不會影響對方。它們將被串行化、 前後執行。即便在多線程模式,全部的命令都是原子的,除非程序有 bug:)
命令序列不是原子的。若是您經過 get 命令獲取了一個 item,修改了它,而後想 把它 set 回 memcached,咱們不保證這個 item 沒有被其餘進程(process,未 必是操做系統中的進程)操做過。在併發的狀況下,您也可能覆寫了一個被其餘 進程 set 的 item。
memcached 1.2.5 以及更高版本,提供了 gets 和 cas 命令,它們能夠解決上面 的問題。若是您使用 gets 命令查詢某個 key 的 item,memcached 會給您返回 該 item 當前值的惟一標識。若是您覆寫了這個 item 並想把它寫回到 memcached 中,您能夠經過 cas 命令把那個惟一標識一塊兒發送給 memcached。若是該 item 存放在 memcached 中的惟一標識與您提供的一致,您的寫操做將會成功。若是 另外一個進程在這期間也修改了這個 item,那麼該 item 存放在 memcached 中的 惟一標識將會改變,您的寫操做就會失敗
Session 是運行在一臺服務器上的,全部的訪問都會到達咱們的惟一服務器上,樣咱們能夠根據客戶端傳來的 sessionID,來獲取 session,或在對應 Session 存在的狀況下(session 生命週期到了/用戶第一次登陸),建立一個新的 Session; 可是,若是咱們在集羣環境下,假設咱們有兩臺服務器 A,B,用戶的請求會由 Nginx 服務器進行轉發(別的方案也是同理),用戶登陸時,Nginx 將請求轉發 至服務器 A 上,A 建立了新的 session,並將 SessionID 返回給客戶端,用戶在瀏 覽其餘頁面時,客戶端驗證登陸狀態,Nginx 將請求轉發至服務器 B,因爲 B 並無對應客戶端發來 sessionId 的 session,因此會從新建立一個新的 session, 而且再將這個新的 sessionID 返回給客戶端,這樣,咱們能夠想象一下,用戶一次操做都有 1/2 的機率進行再次的登陸,這樣不只對用戶體驗特別差,還會讓 服務器上的 session 激增,加大服務器的運行壓力。
爲了解決集羣環境下的 seesion 共享問題,共有 4 種解決方案:
1.粘性 session
粘性 session 是指 Ngnix 每次都將同一用戶的全部請求轉發至同一臺服務器上即將用戶與服務器綁定。
2.服務器 session 複製
即每次 session 發生變化時,建立或者修改,就廣播給全部集羣中的服務器,使 全部的服務器上的 session 相同。
3.session 共享
緩存 session,使用 redis, memcached。
4.session 持久化
將 session 存儲至數據庫中,像操做數據同樣才作 session
一、Redis 不只僅支持簡單的 k/v 類型的數據,同時還提供 list,set,zset,hash 等數據結構的存儲。而 memcache 只支持簡單數據類型,須要客戶端本身處理復 雜對象
二、Redis 支持數據的持久化,能夠將內存中的數據保持在磁盤中,重啓的時候可 以再次加載進行使用(PS:持久化在 rdb、aof)。
三、因爲 Memcache 沒有持久化機制,所以宕機全部緩存數據失效。Redis 配置 爲持久化,宕機重啓後,將自動加載宕機時刻的數據到緩存系統中。具備更好的 災備機制。
四、Memcache 可使用 Magent 在客戶端進行一致性 hash 作分佈式。Redis 支 持在服務器端作分佈式(PS:Twemproxy/Codis/Redis-cluster 多種分佈式實現方 式)
五、Memcached 的簡單限制就是鍵(key)和 Value 的限制。最大鍵長爲 250 個 字符。能夠接受的儲存數據不能超過 1MB(可修改配置文件變大),由於這是型 slab 的最大值,不適合虛擬機使用。而 Redis 的 Key 長度支持到 512k。
六、Redis 使用的是單線程模型,保證了數據按順序提交。Memcache 須要使用 cas 保證數據一致性。CAS(Check and Set)是一個確保併發一致性的機制,屬 於「樂觀鎖」範疇;原理很簡單:拿版本號,操做,對比版本號,若是一致就做,不一致就放棄任何操做 cpu 利用。因爲 Redis 只使用單核,而 Memcached 可使用多核,因此平均每 一個核上 Redis 在存儲小數據時比 Memcached 性能更 高。而在 100k 以上的數 據中,Memcached 性能要高於 Redis 。
七、memcache 內存管理:使用 Slab Allocation。原理至關簡單,預先分配一系 列大小固定的組,而後根據數據大小選擇最合適的塊存儲。避免了內存碎片。(缺 點:不能變長,浪費了必定空間)memcached 默認狀況下下一個 slab 的最大值 爲前一個的 1.25 倍。
八、redis 內存管理: Redis 經過定義一個數組來記錄全部的內存分配狀況, Redis 採用的是包裝的 malloc/free,相較於 Memcached 的內存 管理方法來講,要簡 單不少。因爲 malloc 首先以鏈表的方式搜索已管理的內存中可用的空間分配,導 致內存碎片比較多