天天看點

memcached&redis等分布式緩存的實作原理

嘉賓簡介  

陳科

河狸家資深架構師

有十多年網際網路從業經驗,曾就職阿裡華為58等企業架構部門

演講實錄  

memcached&redis是現在比較常見的緩存軟體。我們今天對它進行一番剖析。這兩個軟體麻雀雖小,五髒俱全,對他們進行分析也有助于我們學習如何閱讀c程式,以及如何進行開源軟體的分析工作。

針對這樣的伺服器軟體,我對它分析一般分為幾個步驟:

伺服器的模型

請求的協定

記憶體管理機制

1伺服器的模型

memcached和redis都采用了事件機制的模型,比如在linux下,都是封裝了epoll的實作。memcached采用了libevent的解決方案,而redis為了考慮性能,則直接封裝了epoll。

另外,memcached在後端的工作采用了線程池的模型,select線程和工作程序進行通信采用了pipe管道的模式。

而redis則是把工作流程拆分成了多個步驟,然後交由epoll異步來完成,這樣讓一個線程盡量利用了cpu。是以,它是單線程的模式。

2請求的協定 

關于請求協定,相對都比較簡單,memcahced和redis都實作了文本協定,比如memcached的格式為:

\r\n

redis的文本協定分為了兩種:inline單行和mutibulk多行。

例如,如果想要批量set,格式為:“*3\r\n$3\r\nset\r\n$3\r\foo\r\n$3\r\bar\r\n”。*開頭代表了mutibulk類型。

另外,memcached也支援binary的二進制協定。

3記憶體管理機制 

在後端工作内容上,memcached相對比較簡單,隻是一個記憶體存放的過程,至于記憶體管理的方式,我們後面再介紹。redis則相對比較複雜,它不隻是一個緩存,還實作一些服務端的資料結構。比如list,map,set等。

在記憶體管理的方式上,memcached采用了預配置設定的方式,slab機制可以做到記憶體複用,減少碎片的産生。當然缺點就是會造成記憶體的浪費。

memcached&redis等分布式緩存的實作原理

這張圖說明了memcached的記憶體管理機制。

順便補充一下memcached和redis的伺服器模型圖:

memcached&redis等分布式緩存的實作原理
memcached&redis等分布式緩存的實作原理

redis的記憶體配置設定相對簡單,直接利用了malloc:

memcached&redis等分布式緩存的實作原理

由于malloc和free這樣的機制會造成記憶體碎片,是以很多人會替換成jemalloc這樣的機制來替換。

還有類似tcmalloc這樣的算法。這個配置設定器可以在編譯的時候自己選擇。

我之前自己測試過tcmalloc時碎片率是最低的為1.01,jemalloc為1.02,而libc的配置設定器碎片率為1.31。大家也可以自己去測試下看看。

很多人把在使用redis和memcached的選型時,經常會不知道使用哪一個。其實很多場景隻需要考慮防止資料庫被擊穿。其實memcached就夠用了。而且用戶端hash做分庫也沒什麼大問題。

spymemcached這樣的用戶端軟體也封裝了連接配接池,序列化和反序列化的工作也都已經做了,相對操心少一些。

假如需要做一些持久化,以及記憶體計算的工作,可以使用redis,這樣就需要考慮一些ha和分庫的解決方案。

其實一個redis執行個體,平常支撐上萬的tps是沒什麼大問題的,基本上世面上很多小公司根本沒那麼大的量。短期内,采用master/slave這樣的機制。來支撐,并且做讀寫分離就夠用了。至于官方的叢集模式,短期内我個人還是不太建議采用。還不如自己做一些分區,例如結合zookeeper來做一套這樣的方案。

另外,redis做一些定制,用來做一些記憶體計算還是不錯的選擇。例如geohash,類似uber/滴滴,這樣的公司。他們的geohash之前都是基于mongodb來實作的。

mongodb可以做位置的索引。但是mongodb本身這塊是一個針對多邊形的算法實作,geohash隻是其中一部分,算法相對複雜,還要考慮持久化。是以性能相對差一些。需要按照全國來根據田字格劃分區域來分庫。

有人基于redis開發了geohash的實作。每秒支撐7-8000的tps沒問題。而且是單個節點。是以類似的需求大家有興趣也可以基于redis定制開發玩玩。

<b>本文來自雲栖社群合作夥伴"dbaplus",原文釋出時間:2015-12-13</b>

繼續閱讀