Reddit如何使用Memcached来存储3TB的缓存数据--转
原文地址:http://www.infoq.com/cn/news/2017/01/Reddit-Memcached-3TB?utm_source=infoq&utm_medium=popular_widget&utm_campaign=popular_content_list&utm_content=homepage
Reddit如何使用Memcached來(lái)存儲(chǔ)3TB的緩存數(shù)據(jù)
作者 薛命燈 發(fā)布于 2017年1月25日. 估計(jì)閱讀時(shí)間: 0 分鐘 | 討論- 分享到: 微博 微信 Facebook Twitter 有道云筆記 郵件分享
- 稍后閱讀
- 我的閱讀清單
Reddit是著名的社交新聞網(wǎng)站,光是在2012年, 它的獨(dú)立訪客就達(dá)到了4000萬(wàn),頁(yè)面瀏覽量達(dá)到了370億次。幾年過(guò)去了,網(wǎng)站用戶有增無(wú)減,而隨著用戶的增多,網(wǎng)站的響應(yīng)速度卻一直在改進(jìn)。這要得益 于Reddit使用了大量的緩存。而隨著網(wǎng)站規(guī)模不斷增長(zhǎng),緩存數(shù)量也隨著增加,那么Reddit是如何做到在增大緩存規(guī)模的同時(shí)又能保證它們的響應(yīng)速度 的?
我們知道,緩存的命中率越高,整體速度就越快,因?yàn)椴恍枰匦聫臄?shù)據(jù)源加載數(shù)據(jù)。除此之外,如何管理緩存,比如緩存的過(guò)期時(shí)間,新舊緩存的交換,以 及緩存的設(shè)計(jì)等等,它們對(duì)緩存的整體性能都有很大影響。來(lái)自Reddit的工程師Daniel Ellis在Reddit官方博客上分享了他們是如何使用Memcached集群來(lái)存儲(chǔ)網(wǎng)站的緩存數(shù)據(jù)的。
Reddit的緩存規(guī)模和基本策略
Reddit目前使用了54個(gè)規(guī)格為r3.2xlarge的AWS EC2實(shí)例,每個(gè)實(shí)例擁有61GB內(nèi)存,也就是說(shuō)總的緩存大小差不多是3.3TB,而且這些緩存并不包括應(yīng)用程序的本地緩存。Reddit的緩存包含了多 種類(lèi)型的數(shù)據(jù),包括數(shù)據(jù)庫(kù)對(duì)象、查詢結(jié)果集、函數(shù)調(diào)用,還有一些看起來(lái)不太像緩存的東西,比如限定速率、分布式鎖等等。如何管理這么大規(guī)模的緩存是一件很 挑戰(zhàn)性的事情,Reddit采用的是“不要把所有雞蛋放在同一個(gè)籃子里”的基本策略。也就是說(shuō),他們并不是把3.3TB的內(nèi)存看成一個(gè)總的大緩存池,而是 按照負(fù)載類(lèi)型對(duì)緩存進(jìn)行分類(lèi),每種類(lèi)型占用一定數(shù)量的緩存空間。這樣做有幾個(gè)好處:
首先,按照負(fù)載類(lèi)型對(duì)緩存進(jìn)行分區(qū),每種類(lèi)型的緩存可以獨(dú)立地伸縮。例如,對(duì)于數(shù)據(jù)庫(kù)緩存來(lái)說(shuō),如果它的命中率降低,交換率變高,同時(shí)數(shù)據(jù)庫(kù)變慢,那么就要考慮對(duì)數(shù)據(jù)庫(kù)緩存進(jìn)行擴(kuò)展,而它的擴(kuò)展不會(huì)影響到其它類(lèi)型的緩存。
其次,按照負(fù)載類(lèi)型對(duì)緩存進(jìn)行分區(qū),可以有針對(duì)性地對(duì)某種類(lèi)型的緩存進(jìn)行負(fù)載測(cè)試,從而預(yù)測(cè)該類(lèi)型緩存的使用規(guī)模,并作出權(quán)衡。
第三個(gè)好處跟Memcached的內(nèi)存分配模型有關(guān)系。Memcached按照板塊(slab) 來(lái)分配內(nèi)存,例如,1至96字節(jié)的對(duì)象可能被放到板塊1,97至120字節(jié)的對(duì)象被放到板塊2,并依此類(lèi)推。這樣做可以避免出現(xiàn)內(nèi)存碎片。不 過(guò),Memcached的這種分配機(jī)制不能動(dòng)態(tài)變化,也就是說(shuō)一旦設(shè)定好了這種模式就不能對(duì)其進(jìn)行修改。如果一開(kāi)始設(shè)定了用來(lái)存儲(chǔ)1KB的對(duì)象,但后來(lái)想 用它來(lái)存儲(chǔ)500KB的對(duì)象,那么交換率就會(huì)變得很高。而按照負(fù)載類(lèi)型來(lái)區(qū)分緩存,那么就可以根據(jù)實(shí)際數(shù)據(jù)類(lèi)型的大小類(lèi)設(shè)定板塊大小。
新版本的Memcached可能支持slab_automove功能,不過(guò)這是后話了。
Reddit的緩存類(lèi)型
接下來(lái)我們來(lái)看看Reddit的幾種緩存類(lèi)型。
數(shù)據(jù)庫(kù)對(duì)象緩存(thing-cache)
| Instances | 16 r3.2xlarge |
| Memcached Version | 1.4.30 |
| Total RAM | 976 GB |
| Get Rate | ~800k/s |
| Set Rate | ~13k/s |
| Miss % | 1.2-2% |
| Typical Object Size | 384-1184 bytes |
數(shù)據(jù)庫(kù)對(duì)象緩存是Reddit最大的緩存池。這些對(duì)象是無(wú)schema的,開(kāi)發(fā)人員可以很容易地對(duì)這些對(duì)象添加新屬性,而無(wú)需對(duì)數(shù)據(jù)庫(kù)schema進(jìn)行變更。這些對(duì)象包括用戶評(píng)論、鏈接和賬戶等等。該類(lèi)型緩存是Reddit最繁忙也最有用的緩存,命中率高達(dá)99%。
主緩存(cache-main)
| Instances | 11 r3.2xlarge |
| Memcached Version | 1.4.30 |
| Total RAM | 671 GB |
| Get Rate | ~82k/s |
| Set Rate | ~10k/s |
| Miss % | ~75% |
| Typical Object Size | <96 bytes |
主緩存是Reddit第二大緩存池。這個(gè)緩存是一般性的緩存,里面存放的所有用來(lái)展示/r/all的結(jié)果集。不過(guò)從表格中可以看到,這個(gè)緩存的命中率并不高,大概只有25%左右。
渲染緩存(cache-render)
| Instances | 8 r3.2xlarge |
| Memcached Version | 1.4.30 |
| Total RAM | 488 GB |
| Get Rate | ~224k/s |
| Set Rate | ~103k/s |
| Miss % | ~45-55% |
| Typical Object Size | 240-2320 bytes |
第三大緩存用來(lái)存放渲染過(guò)的頁(yè)面模板或頁(yè)面片段。這個(gè)緩存相對(duì)安全,就算發(fā)生失效,也不會(huì)對(duì)系統(tǒng)造成太大影響。它的命中率只有大概50%左右,畢竟 頁(yè)面信息需要不斷更新,所以渲染過(guò)的頁(yè)面模板或片段也需要更新。再則,就算這個(gè)緩存失效,也不會(huì)給數(shù)據(jù)庫(kù)負(fù)載帶來(lái)多大影響,因?yàn)橛脕?lái)渲染頁(yè)面的上下文內(nèi)容 已經(jīng)在其它獨(dú)立的緩存中加載過(guò)了。不過(guò),因?yàn)榫彺娴膋ey是基于上下文內(nèi)容生成的,如果key發(fā)生變化,模板就需要重新緩存,這個(gè)需要消耗額外的CPU, 也會(huì)使頁(yè)面響應(yīng)時(shí)間變長(zhǎng)。
持久緩存(cache-perma)
| Instances | 6 r3.2xlarge |
| Memcached Version | 1.4.17 |
| Total RAM | 366 GB |
| Get Rate | 24k/s |
| Set Rate | 4k/s |
| Miss % | <1% |
| Typical Object Size | 96-120 bytes |
最后一個(gè)要細(xì)說(shuō)的緩存,也是命中率最高的緩存——持久緩存,它的命中率超過(guò)了99%。這個(gè)緩存用來(lái)存放數(shù)據(jù)庫(kù)的查詢結(jié)果,還有用戶評(píng)論和鏈接。為什么管這個(gè)緩存叫持久緩存,因?yàn)樗麄兪褂昧?strong>讀-改-寫(xiě)(read-modify-write)的模式。例如,在用戶新增一個(gè)評(píng)論時(shí),他們會(huì)同時(shí)更新緩存和后端的數(shù)據(jù)庫(kù)(Cassandra),而不是簡(jiǎn)單地讓緩存失效,這樣就避免了需要再次從數(shù)據(jù)庫(kù)加載數(shù)據(jù)。
非緩存對(duì)象池
之前提過(guò),除了上述的幾種緩存,Reddit還使用了速率限定和分布式鎖。
對(duì)于一個(gè)并發(fā)量很大的網(wǎng)站來(lái)說(shuō),采取速率限定是很重要的一個(gè)措施,它可以避免用戶無(wú)限制地消耗網(wǎng)站的資源。他們按照時(shí)間段把不同的key存放在不同 的bucket里,每個(gè)key的TTL會(huì)隨著每次調(diào)用逐步增加。通過(guò)檢查這些TTL就可以確保它們不會(huì)超出限定的范圍。因?yàn)橐坏┏^(guò)限定范圍,該用戶就無(wú) 法再做任何操作。
另一方面,得益于Memcached的“add”原子操作命令,他們可以實(shí)現(xiàn)分布式鎖。因?yàn)椤癮dd”命令每次會(huì)產(chǎn)生一個(gè)新的key,只要這個(gè) key原先不存在,那么就相當(dāng)于獲得了一把鎖。鎖用完了就會(huì)被移除,下一次調(diào)用“add”會(huì)生成新的鎖。這個(gè)操作保證同時(shí)只有一個(gè)進(jìn)程可以獲得這個(gè)鎖。不 過(guò)這也是他們的痛點(diǎn)之一。因?yàn)檫@里存在單點(diǎn)故障問(wèn)題,一旦需要做遷移或維護(hù),會(huì)讓整個(gè)網(wǎng)站不可用。Reddit團(tuán)隊(duì)計(jì)劃在未來(lái)逐步減少甚至避免使用這種 鎖。
其它緩存池
除了上述幾種緩存,Reddit還有一些小型的緩存池,比如對(duì)象關(guān)系的緩存、函數(shù)調(diào)用結(jié)果的緩存等等。因?yàn)檫@些緩存都不大,這里不一一贅述。
mcrouter
上面介紹了Reddit的緩存分區(qū)策略,以及各種緩存類(lèi)型的特點(diǎn)。接下來(lái),我們來(lái)看看Reddit是如何使用mcrouter來(lái)滿足各種復(fù)雜的使用場(chǎng)景的。
mcrouter是由Facebook開(kāi)源的Memcached連接池。為什么要用連接池?就像訪問(wèn)數(shù)據(jù)庫(kù)要使用數(shù)據(jù)庫(kù)連接池一樣,使用連接池可以 對(duì)連接進(jìn)行重用和管理,避免了重復(fù)創(chuàng)建和銷(xiāo)毀連接的開(kāi)銷(xiāo)。Reddit有很多應(yīng)用服務(wù)器,每個(gè)服務(wù)器上面運(yùn)行著多個(gè)工作進(jìn)程,如果這些進(jìn)程獨(dú)自向緩存集群 發(fā)起連接,那么連接數(shù)量會(huì)暴增。無(wú)法重用連接是一種資源浪費(fèi),同時(shí)會(huì)給緩存集群帶來(lái)更大壓力。通過(guò)在應(yīng)用服務(wù)器上使用mcrouter,當(dāng)前服務(wù)器上所有 進(jìn)程到緩存集群的連接可以形成一個(gè)連接池,并通過(guò)mcrouter這個(gè)唯一的出口連接到相應(yīng)的緩存上。
除了作為連接池,mcrouter還能處理很多復(fù)雜的場(chǎng)景。mcrouter提供了多種路由類(lèi)型,比如PrefixSelectorRoute,它通過(guò)匹配key的前綴來(lái)決定應(yīng)該到哪個(gè)緩存上獲取數(shù)據(jù)。這樣就可以把特定功能的操作路由到特定的緩存上。
如果要往緩存集群里增加新的緩存實(shí)例,那么可以使用WarmUpRoute。 新加入的緩存實(shí)例被稱(chēng)為“冷”緩存,而原先的實(shí)例叫作“熱”緩存。WarmUpRoute的工作原理是說(shuō),把所有寫(xiě)操作路由到“冷”緩存上,而把未命中的 讀操作路由到“熱”緩存上,然后把在“熱”緩存上命中的緩存結(jié)果異步地更新到“冷”緩存上,那么下次同樣的讀操作就也可以在“冷”緩存上命中。通過(guò)拷貝 “熱”緩存里的數(shù)據(jù)可以避免操作數(shù)據(jù)庫(kù),保證性能不會(huì)受到影響。
mcrouter還提供了FailoverRoute,顧名思義,這個(gè)特性可以避免緩存的單點(diǎn)故障,因?yàn)樗鼤?huì)為一種類(lèi)型的緩存創(chuàng)建多個(gè)緩存池,如果其中一個(gè)失效了,請(qǐng)求會(huì)被路由到另一個(gè)備份的緩存實(shí)例上。
Reddit還使用了影子緩存。不同于WarmUpRoute,WarmUpRoute只是把未命中的讀操作拷貝到新實(shí)例上,而影子緩存會(huì)把讀操作 和寫(xiě)操作都拷貝一份到新的實(shí)例上,但前提是不改變數(shù)據(jù)源。通過(guò)影子緩存,他們可以對(duì)緩存的負(fù)載情況進(jìn)行觀察,因?yàn)樾录拥膶?shí)例作為舊實(shí)例的“影子”而存在, 在不影響舊實(shí)例的前提下可以看到整個(gè)緩存的工作情況。
mcrouter還支持?jǐn)?shù)據(jù)復(fù)制,這個(gè)功能不僅為緩存提供了高可用性,同時(shí)防止出現(xiàn)緩存熱點(diǎn)。
自定義監(jiān)控
緩存有時(shí)候會(huì)變成一個(gè)黑盒,所以對(duì)它們進(jìn)行監(jiān)控是很有必要的。GitHub上有一個(gè)叫做Diamond的 Python腳本可以收集Memcached的基本統(tǒng)計(jì)信息,比如對(duì)象的交換和命中率等等。不過(guò)這些信息還太簡(jiǎn)單,Reddit團(tuán)隊(duì)需要知道在發(fā)生對(duì)象交 換時(shí),緩存內(nèi)部還發(fā)生了其它什么狀況。因?yàn)橥ㄟ^(guò)Memcached的“stats slabs”命令可以看到板塊的度量指標(biāo),于是他們基于這些命令自己寫(xiě)了一個(gè)追蹤板塊度量指標(biāo)的工具。他們還開(kāi)發(fā)了一個(gè)簡(jiǎn)陋的可視化儀表盤(pán):
Reddit團(tuán)隊(duì)還開(kāi)發(fā)了另外一個(gè)工具,叫作mcsauna。這個(gè)工具被部署在每個(gè)緩存服務(wù)器上,它可以檢測(cè)網(wǎng)絡(luò)流量,并根據(jù)配置規(guī)則把不同的key保存在不同的bucket里,然后把結(jié)果輸出到文件上。FilesCollector會(huì)收集這些文件,分析里面的key,并以圖形化的方式呈現(xiàn)出來(lái)。從這些圖形上可以看出那些熱點(diǎn)的key。
展望
緩存為提升網(wǎng)站的響應(yīng)速度做出了不可磨滅的貢獻(xiàn)。而在如何使用緩存方面,Reddit還有很長(zhǎng)的路要走。接下來(lái),他們可能要想著如何通過(guò)服務(wù)發(fā)現(xiàn)來(lái) 對(duì)配置進(jìn)行自動(dòng)化,從而實(shí)現(xiàn)緩存的自動(dòng)擴(kuò)展,而不需要人工的介入。而隨著Memcached版本的不斷改進(jìn),他們也要針對(duì)現(xiàn)有系統(tǒng)進(jìn)行調(diào)整,從而最大化緩 存的性能。
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/articles/6362310.html
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的Reddit如何使用Memcached来存储3TB的缓存数据--转的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: spring cloud config配
- 下一篇: Spring Cloud Netflix