天天看點

雲資料庫memcached之熱點key問題解決方案

在分布式k-v存儲系統中,對某個key進行讀寫時,會根據該key的hash計算出一台固定的server來存取該k-v,如果叢集不發生伺服器數量變化,那麼這一映射關系就不會變化。

雲資料庫memcached就是這樣一種k-v緩存系統。是以在實際應用中,某些高峰時段,有的雲資料庫memcached使用者會大量請求同一個key(可能對應應用的熱賣商品、熱點新聞、熱點評論等),所有的請求(且這類請求讀寫比例非常高)都會落到同一個server上,該機器的負載就會嚴重加劇,此時整個系統增加新server也沒有任何用處,因為根據hash算法,同一個key的請求還是會落到同一台新機器上,該機器依然會成為系統瓶頸。這個問題稱為“熱點key”問題。

雲資料庫memcached之熱點key問題解決方案

使用者使用雲資料庫memcached就是為了提升業務性能,難免會觸發“熱點key問題”。但雲資料庫memcached做為公有雲服務,在發現有熱點的情況下,如果繼續放任該熱點無限激增,就會帶來整個系統雪崩似當機。是以目前的做法會對每個使用者在每台伺服器上配置設定一定的qps或帶寬,當使用者在某台伺服器上的請求超過該使用者的配額,我們就會對使用者進行流控,服務端傳回temporary_failure。該限制會影響使用者正常請求,持續時間分鐘級。

使用者觸發熱點問題是業務需要,是理所當然;雲資料庫memcached對熱點key進行流控是保障系統穩定性,也在情理之中。但有沒有一種既能提供使用者熱點key通路的需求,又能保護雲資料庫memcached伺服器的方法,正是本文所要闡述的。

解決熱點問題有很多辦法,比如使用者如果提前知道某些key可能成為熱點,那麼用戶端可以提前拆分熱點key;也可以搭建一個備用叢集,寫的時候雙寫,然後随機雙讀。這些方案的實作前提和難度,可想而知。下面給出的是對應用透明,且動态發現熱點的解決方案。

本方案解決的是使用者讀熱點問題,不解決寫熱點問題。

首先,雲資料庫memcached簡單架構圖如下:

雲資料庫memcached之熱點key問題解決方案

我們的proxy是無狀态層,上面做了些通路控制功能,使用者用戶端到proxy是随機的,不受固定算法(如hash)控制。而proxy到dataserver的鍊路是根據key決定的,當使用者通路熱點key時,所有proxy上關于該key的請求都會落到同一台dataserver。

是以解決熱點問題,其核心思路是:每台dataserver對所有key進行采樣、定位,實時計算出目前熱點key,将其回報給proxy層,由proxy緩存備份。即負載壓力由dataserver轉向proxy。理由是:proxy可以無狀态擴容,而dataserver不可以。

每台伺服器有個hotkey邏輯,讓每個到達伺服器的目标請求(可配置不同類型請求)經曆三個流水階段:

采樣階段(根據配置設定采樣次數sample_max)

本階段輸出:是否有熱點現象,如果有熱點,輸出熱點的桶号供下階段使用。

定位階段(根據配置設定采樣次數reap_max)

本階段輸出:熱點key(如果滿足門檻值)。 并添加到服務端的lru連結清單。

回報階段

對到達伺服器的目标請求,取出key,然後查詢lru連結清單判斷該key是否為熱點key。如果是熱點,就會在請求結束後,向proxy發送一個feedback包,通知proxy。

至此,伺服器hot-key邏輯結束。流程圖如下:

雲資料庫memcached之熱點key問題解決方案

當proxy收到dataserver的熱點回報之後,會将該key寫入到自己的lru-cache裡面,該cache的過期時間和容量大小都交由使用者通過控制台設定,預設分别是100ms和30。這樣,熱點的key就已經存在于與proxy中了,下次使用者請求就可以直接傳回了。

下面讨論都是使用者client已經觸發了熱點key問題,假設使用者client跟每個proxy都建立了連結,并且每個proxy上都有對熱點key的請求,那麼理論上每個proxy的lru-cache都有一份資料。

我們保證單條連接配接上的一緻性。

當使用者client和proxy1建立連接配接,使用者修改了一個key(任何寫操作),proxy1上會在lru-cache中同步删除該key,新key就會寫到dataserver上,然後在讀資料的時候,由于lru-cache不命中,就會從dataserver上拿到最新資料。

不同連結上隻能提供弱一緻性。

如果這個時候使用者從proxy2上讀熱點資料呢?理論上就會讀到老資料,該資料将于100ms之後從proxy-cache中過期淘汰掉,之後就會更新會最新資料,即不同連接配接間可能有100ms不一緻。

怎樣看待弱一緻性。

事實上,不開啟熱點key功能,在不同連結上也會存在弱一緻。假設使用者client建立了兩條連結到雲資料庫memcached,在連結1上寫入key-value1,在連結1、2上分别讀該key。當連結1上使用者update了key-value2,這個請求需要一定的網絡延遲才能寫入到服務端,如果這個時候連結2上同時發起對key的讀取操作,如果讀請求先到服務端,它将讀到的是value1的老值。

是以開啟熱點key功能,隻是增加了不一緻時間,且該功能為可選。控制權由使用者掌握。

由以上分析可以看到,開啟熱點key功能之後,隻會對使用者的讀請求産生影響,該影響增加了不同連結上的弱一緻性的時間。是以,該功能适合讀多寫少,且對強一緻性要求不高的應用。

整個方案核心是負載壓力由dataserver轉移到proxy。好處如下:

1、因為dataserver擴容也解決不了熱點問題,而proxy可以無狀态擴容,對使用者來講就極大提升了熱點key通路的能力,不受單點制約。

2、縮短了服務端處理鍊路,對使用者平均rt也所降低。

3、免除服務端熱點流控的分鐘級别影響。