日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

.net redis定时_一场由fork引发的超时,让我们重新探讨Redis的抖动问题

發(fā)布時間:2024/9/27 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 .net redis定时_一场由fork引发的超时,让我们重新探讨Redis的抖动问题 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

????????????????????????????摘要:一次由fork引發(fā)的時延抖動問題。

背景介紹

華為云數(shù)據(jù)庫GaussDB(for Redis) 是一款基于計算存儲分離架構(gòu),兼容Redis生態(tài)的云原生NoSQL數(shù)據(jù)庫;它依靠共享存儲池實現(xiàn)了強一致,支持持久化落盤存儲,保證數(shù)據(jù)的安全可靠。其核心特點是:存算分離、強一致、低成本、超大容量。

GaussDB(forRedis)服務(wù)團隊在支撐某客戶業(yè)務(wù)上云的過程中,發(fā)現(xiàn)一次由fork引發(fā)的時延抖動問題,本著對客戶負責(zé)任的態(tài)度,我們詳細探究了fork這個系統(tǒng)調(diào)用的性能影響,并且在最新的GaussDB(for Redis)版本已解決了這個抖動問題,清零了內(nèi)部的fork使用,與原生Redis相比,徹底解決了fork的性能隱患。

問題焦點

1)華為云GaussDB(for Redis) 服務(wù)在某客戶上云線調(diào)測過程中發(fā)現(xiàn),系統(tǒng)上量后規(guī)律性的出現(xiàn)每5分鐘1次的時延抖動問題。

2)華為云GaussDB(for Redis)團隊經(jīng)過攻關(guān),最終確認抖動原因是fork導(dǎo)致并解決了這個問題。而fork是開源Redis的一個重要依賴,希望通過本文的分享,能夠幫助大家在使用開源Redis的時候,充分認識fork的影響,從而選擇更優(yōu)的方案。

問題現(xiàn)象

某客戶業(yè)務(wù)接入GaussDB(for Redis)壓測發(fā)現(xiàn),每5分鐘系統(tǒng)出現(xiàn)一次規(guī)律性的時延抖動:

1)正常情況消息時延在1-3ms,抖動時刻時延達到300ms左右。

2)通常是壓測一段時間后開始出現(xiàn)抖動;抖動一旦出現(xiàn)后就非常規(guī)律的保持在每5分鐘1次;每次抖動的持續(xù)時長在10ms以內(nèi)。

下圖是從系統(tǒng)慢日志中捕獲到的發(fā)生抖動的消息樣例(對敏感信息進行了遮掩):

問題分析

1. 排查抖動源:

1)由于故障的時間分布非常規(guī)律,首先排除定時任務(wù)的影響,主要包括:

l agent:和管控對接的周期性統(tǒng)計信息上報任務(wù)

l 內(nèi)核:執(zhí)行引擎(Redis協(xié)議解析)和存儲引擎(rocksdb)的周期性操作(包括rocskdb統(tǒng)計,wal清理等)

屏蔽上述2類定時任務(wù)后,抖動依然存在。

2)排除法未果后,決定回到正向定位的路上來。通過對數(shù)據(jù)訪問路徑增加分段耗時統(tǒng)計,最終發(fā)現(xiàn)抖動時刻內(nèi)存操作(包括allocate、memcpy等)的耗時顯著變長;基本上長出來的時延,都是阻塞在了內(nèi)存操作上。(截圖為相關(guān)日志,單位是微秒)

3)既然定位到是系統(tǒng)級操作的抖動,那么下一步的思路就是捕獲抖動時刻系統(tǒng)是否有異常。我們采取的方法是,通過腳本定時抓取top信息,分析系統(tǒng)變化。運氣比較好,腳本部署后一下就抓到了一個關(guān)鍵信息:每次在抖動的時刻,系統(tǒng)中會出現(xiàn)一個frm-timer進程;該進程為GaussDB(for Redis)進程的子進程,且為瞬時進程,持續(xù)1-2s后退出。

4)為了確認該進程的影響,我們又抓取了perf信息,發(fā)現(xiàn)在該進程出現(xiàn)時刻,Kmalloc, memset_sse,memcopy_sse等內(nèi)核系統(tǒng)調(diào)用增多。從上述信息推斷,frm-timer進程應(yīng)該是被fork出來的,抖動源基本可鎖定在fork frm-timer這個動作上。

2.確定引發(fā)抖動的代碼:

1)分析frm-timer的來歷是下一步的關(guān)鍵。因為這個標識符不在我們的代碼中,所以就需要拉通給我們提供類庫的兄弟部門聯(lián)合分析了。經(jīng)過大家聯(lián)合排查,確認frm-timer是日志庫liblog中的一個定時器處理線程。如果這個線程fork了一個匿名的子進程,就會復(fù)用父進程的線程名,表現(xiàn)為Redis進程創(chuàng)建出1個名為frm-timer的子進程的現(xiàn)象。

2)由于frm-timer負責(zé)處理liblog中所有模塊的定時器任務(wù),究竟是哪個模塊觸發(fā)了上述fork?這里我們采取了一個比較巧妙的方法,我們在定時器處理邏輯中增加了一段代碼:如果處理耗時超過30ms,則調(diào)用std:: abort()退出,以生成core棧。

3)通過分析core棧,并結(jié)合代碼排查,最終確認引發(fā)抖動的代碼如下:

上述代碼是用來周期性歸檔日志的,它每5分鐘會執(zhí)行1次 system系統(tǒng)調(diào)用來運行相關(guān)腳本,完成歸檔日志的操作。而Linux system系統(tǒng)調(diào)用的源碼如下,實際上是一個先fork子進程,再調(diào)用execl的過程。

4)分析至此,我們還需要回答最后一個問題:究竟是fork導(dǎo)致的抖動,還是腳本內(nèi)容導(dǎo)致的抖動?為此,我們設(shè)計了一組測試用例:

l 用例1:將腳本內(nèi)容改為最簡單的echo操作

l 用例2:在Redis進程里模擬1個類似frm-timer的線程,通過命令觸發(fā)該線程執(zhí)行fork操作

l 用例3:在Redis進程里模擬1個類似frm-timer的線程,通過命令觸發(fā)該線程執(zhí)行先fork,再excel的操作

l 用例4:在Redis進程里模擬1個類似frm-timer的線程,通過命令觸發(fā)該線程執(zhí)行system的操作

l 用例5:在Redis進程里模擬1個類似frm-timer的線程,通過命令觸發(fā)該線程執(zhí)行先vfork,再excel的操作

最終的驗證結(jié)果:

l 用例1:有抖動。

l 用例2:有抖動。

l 用例3:有抖動。

l 用例4:有抖動。

l 用例5:無抖動。

用例1結(jié)果表明抖動和腳本內(nèi)容無關(guān);用例2、3、4的結(jié)果表明調(diào)用system引發(fā)抖動的根因是因為其中執(zhí)行了fork操作;用例5的結(jié)果進一步佐證了抖動的根因就是因為fork操作。最終的故障原因示意圖如下:

3. 進一步探究fork的影響:

1)眾所周知,fork是Linux(嚴格說是POSIX接口)創(chuàng)建子進程的系統(tǒng)調(diào)用,歷史上看,主流觀點大多對其贊譽有加;但近年間隨著技術(shù)演進,也陸續(xù)出現(xiàn)了反對的聲音:有人認為fork是上個時代遺留的產(chǎn)物,在現(xiàn)代操作系統(tǒng)中已經(jīng)過時,有很多害處。激進的觀點甚至認為它應(yīng)該被徹底棄用。(參見附錄1,2)

2)fork當(dāng)前被詬病的主要問題之一是它的性能。大家對fork通常的理解是其采用copy-on-wirte寫時復(fù)制策略,因此對其的性能影響不甚敏感。但實際上,雖然fork時可共享的數(shù)據(jù)內(nèi)容不需要復(fù)制,但其相關(guān)的內(nèi)核數(shù)據(jù)結(jié)構(gòu)(包括頁目錄、頁表、vm_area_struc等)的復(fù)制開銷也是不容忽視的。附錄1、2中的文章對fork開銷有詳細介紹,我們這回遇到的問題也是一個鮮活的案例:對于Redis這樣的時延敏感型應(yīng)用,1次fork就可能導(dǎo)致消息時延出現(xiàn)100倍的抖動,這對于應(yīng)用來說無疑是不可接受的。

4.原生Redis的fork問題:

4.1 原生Redis同樣被fork問題困擾(參見附錄3,4,5),具體包括如下場景:

1)數(shù)據(jù)備份

備份時需要生成RDB文件,因此Redis需要觸發(fā)一次fork。

2)主從同步

全量復(fù)制場景(包括初次復(fù)制或其他堆積嚴重的情況),主節(jié)點需要產(chǎn)生RDB文件來加速同步,同樣需要觸發(fā)fork。

3)AOF重寫

當(dāng)AOF文件較大,需要合并重寫時,也會產(chǎn)生一次fork。

4.2 上述fork問題對原生Redis的影響如下:

1)業(yè)務(wù)抖動

原生Redis采用單線程架構(gòu),如果在電商大促、熱點事件等業(yè)務(wù)高峰時發(fā)生上述fork,會導(dǎo)致Redis阻塞,進而對業(yè)務(wù)造成雪崩的影響。

2)內(nèi)存利用率只有50%

Fork時子進程需要拷貝父進程的內(nèi)存空間,雖然是COW,但也要預(yù)留足夠空間以防不測,因此內(nèi)存利用率只有50%,也使得成本高了一倍。

3)容量規(guī)模影響

為減小fork的影響,生產(chǎn)環(huán)境上原生Redis單個進程的最大內(nèi)存量,通常控制在5G以內(nèi),導(dǎo)致原生Redis實例的容量大大受限,無法支撐海量數(shù)據(jù)。

解決方法

1.修改日志庫liblog中的周期性歸檔邏輯,不再fork子進程。

2.系統(tǒng)排查并整改GaussDB(for Redis)代碼(包括使用的類庫代碼)中的fork調(diào)用。

3.最終排查結(jié)果,實際只有本次的這個問題點涉及fork。當(dāng)前修改后即可確保GaussDB(for Redis)的時延保持穩(wěn)定,不再受fork性能影響。

注:GaussDB(for Redis)由華為云基于存算分離架構(gòu)自主開發(fā),因此不存在原生Redis的fork調(diào)用的場景。

總結(jié)

本文通過分析GaussDB(for Redis)的一次由fork引發(fā)的時延抖動問題,探究了fork這個系統(tǒng)調(diào)用的性能影響。最新的GaussDB(for Redis)版本已解決了這個抖動問題,并清零了內(nèi)部的fork使用,與原生Redis相比,徹底解決了fork的性能隱患。希望通過這個問題的分析,能夠帶給大家一些啟發(fā),方便大家更好的選型。

附:

1.[是時候淘汰對操作系統(tǒng)的 fork() 調(diào)用了]

https://www.infoq.cn/article/BYGiWI-fxHTNvSohEUNW

2.[Linux fork那些隱藏的開銷]

https://www.mdeditor.tw/pl/29L0

3.[Redis官方文檔]

https://redis.io/topics/latency

4.[Redis的一些坑]

https://www.jianshu.com/p/03df6fd516eb

5.[Redis 常見問題之-fork操作]

https://blog.csdn.net/longgeqiaojie304/article/details/89407214

6.[GaussDB(for Redis)官網(wǎng)鏈接]

https://www.huaweicloud.com/product/gaussdbforredis.html

本文作者:華為云數(shù)據(jù)庫GaussDB(for Redis)團隊

點擊關(guān)注,第一時間了解華為云新鮮技術(shù)~

總結(jié)

以上是生活随笔為你收集整理的.net redis定时_一场由fork引发的超时,让我们重新探讨Redis的抖动问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。