學習筆記之Memcached原理

0x00 Memcached簡述

Memcached是一套高性能的分佈式內存對象緩存系統,用於在動態系統中減小數據庫負載,提高性能。html

0x01 Memcached特性

  • 基於libevent的事件處理算法

  • 內置內存存儲方式SLab Allocation機制數據庫

  • 並不單一的數據刪除機制緩存

  • 基於客戶端的分佈式系統服務器

0x02 高性能的基礎:libevent事件處理

Libevent 是一個用C語言編寫的、輕量級的開源高性能網絡庫,主要有如下幾個亮點:事件驅動( event-driven),高性能;輕量級,專一於網絡,不如 ACE 那麼臃腫龐大;源代碼至關精煉、易讀;跨平臺,支持 Windows、 Linux、 *BSD 和 Mac Os;支持多種 I/O 多路複用技術, epoll、 poll、 dev/poll、 select 和 kqueue 等;支持 I/O,定時器和信號等事件;註冊事件優先級。網絡

以上引自百度百科,在不支持I/O多路複用的狀況下,一個線程同時只能處理一個socket文件操做符,因此當一個任務未完成時,線程須要等待任務的處理,這種處理模型效率低下。而I/O多路複用無需等待任務完成,而是將全部任務維護在一個I/O組中,在等待過程當中線程能夠去處理其餘的任務,當某個任務完成後,再去操做該socket操做符。值得一提的是,在I/O多路複用技術中,epoll是很是棒的,相比於select模型,epoll沒有文件操做符數量的限制;而且select模型是將全部操做符維護在一個I/O組中,當有socket數據可操做時,線程須要在組中尋找哪一個文件操做符可操做,而epoll只將可操做的socket文件操做符給線程,線程無需本身尋找,能夠直接操做該socket,提升了處理性能。socket

因此,使用libevent時間處理模型,很是好的提高了memcached的性能。分佈式

0x03 SLab Allocation機制

在memcached中,內存不是直接C語言提供的malloc() free() 進行管理的,由於原生的內存管理方式會形成內存碎片,會加劇內存管理器的內存管理負擔。而SLab Allocation機制完美的解決了內存碎片化的問題。memcached

a.解決內存碎片化

SLab Allocator 在初始化時,經過將內存分配成預先設置的大小,將這些內存分割成特定長度的塊(chunk),並把尺寸相同的chunk分紅一個組,也就是chunk集合,而這種方式就解決了內存碎片化的問題。性能

b.內存預分配

在須要存儲緩存數據時,memcached會在chunk中選擇與所存數據大小最接近的chunk,並將數據存儲到該chunk中,這樣不須要每次在存儲數據時,都向操做系統申請空間,提高了memcached的處理性能。
SLab模型

c.內存重複利用

當存儲的數據過時後,memcached不會釋放該數據的所佔用的內存,而僅僅是將該數據標記爲不可用,當有新數據須要存儲時,memcached會將數據從新存儲到該空間中,用這種方式對內存進行重複利用。

d.缺點

由於Slab Allocator將內存分割成固定大小的塊,當存儲的數據小於chunk的長度,會致使該chunk剩餘空間的浪費。例如:當一個數據佔用60K,而最接近的chunk長度爲64K,此時就有4K的空間形成浪費。而目前僅有的調優方案是調整Growth Factor因子,讓chunk的大小盡量的接近,減小空間的浪費。

0x04 memached的刪除機制
a.不會真正刪除記錄

當存儲在memcached中的記錄過時時,memcached不會釋放該內存,而是讓客戶端對該記錄不可見。留下內存來,讓以後的存儲記錄進行內存重複利用。

b.Lazy Expiration(懶過時機制)

memcached爲了提高性能,在內部不會對存儲在memcached中的記錄進行監視,而是在每次get數據的時候,對該記錄的過時時間進行校驗,當記錄過時,則不返回數據。

c.LRU(最近最少使用)

雖然memcached擁有內存重複利用的機制,可是進行大量數據緩存時,仍是會出現內存吃滿,memcached沒法在SLab中獲取到空閒的內存,在這種狀況下,memcached會觸發LRU,會在最近未被使用的記錄中進行搜索,並將這些空間分配給新的記錄。

0x05 memcached的分佈式

不一樣於其餘軟件的分佈式,memcached的分佈式不存在於服務端,而是徹底由客戶端進行分佈式的處理。這樣的好處是,減小memcached服務端之間的網絡鏈接,當某一個服務器宕機時,不至於影響其餘機器的正常使用。

memcached的分佈式

a.根據餘數計算分散

經過crc32()計算出鍵的整數哈希值,而後除以服務器的臺數,求得餘數進行服務器節點的選擇,此種方式的優勢是,簡單易操做,而且數據的分散性也很是優秀。但缺點是,當改變服務器的數量時,緩存重組的代價巨大,在此過程當中緩存的命中率急劇降低。

b.Consistent Hashing(一致性哈希)

首先求出memcached服務器節點的哈希值,並將其分配到一個0~2^32的圓上,咱們稱該這個圓爲值域,以後經過一樣的計算方式求出鍵的哈希值,並將值映射到圓上,而後從數據映射到的位置開始順時針尋找,並將數據存儲到找到的第一個服務器節點上,若是找到2^32仍然找不到就將數據存儲到第一臺memcached機器上。

一致性哈希

當添加一臺新機器時,經過一樣的hash算法將該機器映射到圓上,影響的僅僅是新機器的節點到它的上一個節點之間的數據。

一致性哈希添加節點

當刪除一臺機器時,一樣也僅僅影響映射到刪除的機器和它的上一臺機器之間的數據,而不會形成大面積的緩存重組即rehash.

0x06 擴展閱讀

memcached徹底剖析

使用 libevent 和 libev 提升網絡應用性能

高性能IO模型淺析

備註:資源和圖片等均來自網絡

原文做者:我纔是二亮
原文連接:http://blog.2liang.me/2016/11/28/learn-memcached-principle/轉載請在正文中標註並保留原文連接、做者等信息。

相關文章
相關標籤/搜索