【問題追查】mc叢集寫入恍惚問題排查

funnyok發表於2021-09-09

1.現象

業務方反饋在向memcache叢集寫入資料時,出現不穩定。表現為向mc寫入一個creative和ad物件的list,有的時候能寫進去並讀出來,有的時候寫成功但是讀不出來。

2.問題排查

2.1 復現問題

  • a.有的key沒有問題,能夠一直寫+讀。

  • b.有的key一直都是寫ok,讀None。

  • c.有的key寫ok,有的時候讀ok有的時候讀None.

2.2 proxy的問題?

使用同一個proxy的再次復現問題,出現了之前的多種情況。所以排除proxy問題。

另外在排查中發現出現問題的key長度小於20B、value長度在9K~10K左右。

2.3.mc叢集問題?

2.3.1 叢集各節點狀態

叢集各個節點狀態,以10.2.10.10:11211為例:

圖片描述

透過看叢集各個節點的狀態,發現節點的slab存在不同程度的Full.

情節較為嚴重的是10.2.10.8:11211,10.2.10.9:11211,10.2.10.10:11211這三個節點,並且Evicted很多。

2.3.2 再次復現問題

用client直接連線不同的節點,在有的節點上讀寫都ok,有的節點上出現了之前的問題。確定是叢集節點出現問題。

基本確定問題和mc叢集節點上5.5K~16.9K之間的slab的Full狀態以及Evicted有關。

2.3.3 叢集記憶體使用情況

記憶體使用情況

圖片描述

最大記憶體5GB,每個例項用了1.5GB左右。 記憶體沒滿啊,為什麼存不進去?

再次返回來看各個節點的狀態,以10.2.10.10:11211為例:

把分配的Page都加起來:158+2+1+1+1+1+1+1+2+7+4+9+5+754+58+558+576+2869+90+7+6+2+1+1+1+1+1+1+1+1=5121 ~ 5GB

5GB是分配給每個節點的maxmemory.

說明所有的memory page都被分配給相應的slab了,目前即使有一部分page回收後空閒,但是這部分空閒的page沒有被重新分配到全域性空閒空間,供其他slab使用。

看一下chunk size為1.8K的一行,分配page為754,item數量1209,也就是說這個slab裡面,實際只有1MB左右的資料,卻分配了754M的空間,嚴重浪費。

為什麼mc就不能把已經分配的空閒空間回收呢?

問題定位:mc沒有把已經分配的空閒空間回收。

3.問題解決

3.1 再造叢集復現問題

1.自己搭了一個64M的mc節點。

2.用4k的value資料寫滿:

圖片描述

3.刪除所有資料:

圖片描述

4.再用1k的value寫滿:

圖片描述

發現這次value大小為1k的很多都Evited了。並且上次value大小為4k的資料雖然已經刪除了,但是page大多數還處於被分配狀態。

圖片描述

在stats裡面看到,slabs也出現了reassign(就是在啟動引數裡面指定了slabsreassign和slabsautomove),但是和我們要的差距有點大。

在1.4.11的ReleaseNote裡面看到:

圖片描述

圖片描述

圖片描述

可以透過命令手動重新分配slot,試一下

圖片描述

寫滿1k資料:

圖片描述

有4個page遷移了

圖片描述

再寫一遍1k資料:

圖片描述

寫一遍2k的資料:

圖片描述

能看到reassign的速度變快了。但還是和我們要的差距有點大。我們不能經常手動執行slabs reassign.

我們用的mc是1.4.13,新版本的mc是不是解決了這個問題?

於是下載最新的1.4.33,重複上面的測試。

3.3 新版本測試

下載最新版本1.4.33,重試上面的測試:

用4k的value資料寫滿:

圖片描述

刪除所有資料:

圖片描述

用1k的value寫滿:

圖片描述

貌似沒什麼變化啊,趕緊下載最新的程式碼看看在申請空間的時候怎麼做的。

圖片描述

這4個函式基本就是lru_maintainer執行緒回收空間的核心程式碼了,限於篇幅不再羅列程式碼。

概括一下就是:

maintainer執行緒處於一個while迴圈中,不斷對所有的slabscls進行迴圈,看看哪些slabscls裡面空閒空間的>2.5個page,就標記一下到slab_reb裡面,等待回收。

並且不斷對lru表維護,如果hot,warm lru佔有記憶體超過限定額度,將hot lru的item移至warm lru, warm lru的item移至cold lru,以及對cold lru裡面物件的回收等等.

slabclass_t對應三條lru佇列,即hot,warm,cold lru,最終記憶體不足的時候會有優先刪除cold lru的資料。

另外,最新的mc裡面也支援一個crawler執行緒和maintainer執行緒配合。crawler執行緒用來檢查當前memcache裡面的所有item是否過期等。

3.4 新版本再測試

1.啟動引數:

增加lru_maintainer引數

2.寫4k資料:

圖片描述

3.全部刪除:

圖片描述

4.寫入8k資料:

圖片描述

5.刪除8k資料:

圖片描述

6.寫滿6k資料:

圖片描述

7.寫入4k無過期資料,8k有過期的資料600s

圖片描述

8.寫入5k的不過期資料:

圖片描述

9.寫入5k無過期資料,8k有過期的資料600s

圖片描述

10.寫入4k帶過期資料:

圖片描述

刪除了8k的過期資料。

加入lru_maintainer執行緒之後效果大好,另外,如果增加crawler執行緒的話會佔用鎖,可能會影響mc的效能(需要效能測試)

4.結論

透過上面的實驗看出,1.4.33的mc在page分配完成後的回收上效果很好。

如果叢集已經出現了page分配完的情況,如果使用新版的mc,一方面會快取之前1.4.13版本寫不進去的資料,提高在slab鈣化情況下的空間利用率,提高mc命中率。另一方面因為將資料分別放在hot,warm,cold lru裡面,能快速的找到替換的空間,大大降低查詢已經過期的空間回收時間,進一步提高效能。

5.升級新版本

目前廣告的所有mc都已經升級到1.4.33版本。

6.Ref

 

原文地址:https://techblog.toutiao.com/2018/05/29/untitled-22/

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/3137/viewspace-2802046/,如需轉載,請註明出處,否則將追究法律責任。

相關文章