www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 單片機 > 架構(gòu)師社區(qū)
[導讀]最近DBA反饋線上的一個Redis資源已經(jīng)超過了預先設(shè)計時的容量,并且已經(jīng)進行了兩次擴容,內(nèi)存增長還在持續(xù)中,希望業(yè)務(wù)方排查一下容量增長是否正常,若正常則期望重新評估資源的使用情況,若不正常請盡快查明問題并給出解決方案進行處理。


記錄一次生產(chǎn)環(huán)境中Redis內(nèi)存增長異常排查全流程!

作者:z小趙

一枚用心堅持寫原創(chuàng)的“無趣”程序猿,在自身受益的同時也讓朋友們在技術(shù)上有所提升。


最近 DBA 反饋線上的一個 Redis 資源已經(jīng)超過了預先設(shè)計時的容量,并且已經(jīng)進行了兩次擴容,內(nèi)存增長還在持續(xù)中,希望業(yè)務(wù)方排查一下容量增長是否正常,若正常則期望重新評估資源的使用情況,若不正常請盡快查明問題并給出解決方案進行處理。

問題現(xiàn)象

下面是當時資源容量使用和 key 數(shù)量的監(jiān)控情況:

記錄一次生產(chǎn)環(huán)境中Redis內(nèi)存增長異常排查全流程!

記錄一次生產(chǎn)環(huán)境中Redis內(nèi)存增長異常排查全流程!

從監(jiān)控可以看出,6.1 號開始容量和 keys 的增長陡增。首先懷疑是有惡意刷量的操作導致 key 數(shù)量增加比較多,經(jīng)過代碼排查后發(fā)現(xiàn),確實有代碼漏洞導致可以惡意刷量,后經(jīng)過 bug 修復后上線。你以為到這里就完事了?天真,要不然寫這篇文章還有什么用?

但是從接口的請求量來看的話,刷量的情況并沒有那么明顯,下面是接口請求的 qps:

記錄一次生產(chǎn)環(huán)境中Redis內(nèi)存增長異常排查全流程!

繼續(xù)排查存儲設(shè)計發(fā)現(xiàn),存儲使用了 Set 結(jié)構(gòu)(由于產(chǎn)品最開始沒有明確說明一個 key 下存儲多少元素,所以采用了 Set,這也為后續(xù)容量異常增長打下了 堅實的基礎(chǔ) ),實際每個 Set 中只存儲了一個元素,但實際容量卻增長了 30M,根據(jù)容量計算公式 9w * 14(key 長度) * 1(元素個數(shù)) * 10(元素長度)= 8.4M,實際容量卻超出了近 4 倍。

到此,產(chǎn)生了兩個懷疑點,其一:實際存儲的數(shù)據(jù)占用內(nèi)存大小有問題,其二:容量評估公式有問題。

疑點一:實際存儲的數(shù)據(jù)占用內(nèi)存大小有問題

查看 Redis 的 Set 底層存儲結(jié)構(gòu)發(fā)現(xiàn),Set 集合采用了整數(shù)集合和字典兩種方式來實現(xiàn)的,當滿足如下兩個條件的時候,采用整數(shù)集合實現(xiàn);一旦有一個條件不滿足時則采用字典來實現(xiàn)。

  • Set 集合中的所有元素都為整數(shù)
  • Set 集合中的元素個數(shù)不大于 512(默認 512,可以通過修改 set-max-intset-entries 配置調(diào)整集合大?。?


排查到這里,按照正常情況的話,其應(yīng)該采用的是整數(shù)集合存儲的才對啊,但是登陸到機器上,使用memory usage key命令查看內(nèi)存的使用情況發(fā)現(xiàn),單個 key 的內(nèi)存占用竟然達到了 218B :

記錄一次生產(chǎn)環(huán)境中Redis內(nèi)存增長異常排查全流程!

是不是覺得不可思議,只是存儲一個 10 位的數(shù)據(jù)且內(nèi)容是數(shù)字,為什么會占用這么大的內(nèi)存呢?

到此我們開始懷疑是不是序列化的方式有問題導致實際寫入 Redis 的內(nèi)容不是一個數(shù)字,所以接著查數(shù)據(jù)實際寫入時用的序列化方式。經(jīng)過排查發(fā)現(xiàn)寫入的 value 被序列化以后變成了一個十六進制的數(shù)據(jù),到這里這個疑點基本就真相大白了,因為此時 Redis 認為存儲的內(nèi)容已經(jīng)不適用于整數(shù)集合存儲了,而改為字典存儲。將序列化方式修改以后,測試添加一個元素進去,發(fā)現(xiàn)實際內(nèi)存占用只有 72B,縮減為原來的 1/3:

記錄一次生產(chǎn)環(huán)境中Redis內(nèi)存增長異常排查全流程!

疑點二:容量評估公式有問題

容量評估公式忽略了 Redis 對于不同的情況下內(nèi)存的占用情況,統(tǒng)一按照元素的大小去計算,導致實際內(nèi)容占用過小。

到此,整個 Redis 內(nèi)存容量增長異?;旧峡梢愿嬉欢温妨?,接下來就是修改正確的序列化和反序列化方式,然后進行洗庫操作,經(jīng)業(yè)務(wù)調(diào)查發(fā)現(xiàn),目前的實際使用方式可以改為 KV 結(jié)構(gòu),所以將底層存儲進行了改造。

洗庫流程介紹

  1. 上線雙寫邏輯
  2. 同步歷史數(shù)據(jù)
  3. 切換讀取新數(shù)據(jù)源
  4. 觀察線上業(yè)務(wù)是否正常
  5. 關(guān)閉舊存儲的寫入
  6. 刪除舊資源
  7. 下線舊的讀寫邏輯

關(guān)于新數(shù)據(jù)的存儲位置有兩種選擇,

  • 第一種方式是:舊數(shù)據(jù)正常寫舊資源,新數(shù)據(jù)寫到新部署的資源下。此種方式的優(yōu)點是,將舊數(shù)據(jù)全量洗入新資源后,然后下線舊資源就可以了;缺點是,需要在代碼層重新寫一套到資源的配置,DBA 也需要新部署一個資源。
  • 第二種方式是:新舊數(shù)據(jù)都寫到舊資源里面,然后將舊數(shù)據(jù)映射到新數(shù)據(jù)結(jié)構(gòu)上,然后全量洗入舊資源。此種方式的優(yōu)點是,不需要重新寫一套到資源的配置,DBA 也不需要新部署資源,只需要將舊資源的內(nèi)存進行擴容操作即可;缺點是,全量數(shù)據(jù)洗入完成后,需要手動剔除舊數(shù)據(jù)。

兩種方案都可行,可以根據(jù)自己的喜好來選擇,我們最終選擇了第二種方案進行數(shù)據(jù)清洗操作。

上線雙寫邏輯

在資源存儲層,對上下行讀寫操作分別增加 switcher(開關(guān)),然后增加讀寫新存儲的邏輯,代碼測試通過后上線。

這一步的流程在于開關(guān),可以選擇熱部署的任何方式來修改標志位,從而控制代碼流程的執(zhí)行,另外需要注意的一點是:開關(guān)狀態(tài)的修改不能被工程上下線所影響。

同步歷史數(shù)據(jù)

上線完成后,導出線上庫的 RDB 文件,解析出所有 key(關(guān)于 RDB 文件的解析,如果有專門的 DBA 同事,可以讓 DBA 同事給解析好,如果沒有的話,可以自己在網(wǎng)上查查 RDB 文件解析的工具,也不是很難);依次遍歷解析出來的 key,查詢 key 對應(yīng)的舊數(shù)據(jù),將舊數(shù)據(jù)映射到新數(shù)據(jù)結(jié)構(gòu)下,最后寫入到新的存儲下。

關(guān)于同步歷史數(shù)據(jù),需要根據(jù)自身實際的業(yè)務(wù)場景去做適當?shù)恼{(diào)整,這里只提供一個思路。下面是洗數(shù)據(jù)可以使用的小工具,需要的朋友可以適當調(diào)整代碼邏輯就可以使用了:

public class fixData { public static void main(String[] args) {
        String fileName = "test.txt"; int rate = 500; int size = 200; if (args != null) {
            fileName = args[0];
            rate = Integer.parseInt(args[1]);
            size = Integer.parseInt(args[2]);
        }
        RateLimiter rateLimiter = RateLimiter.create(rate);
        ThreadPoolExecutor executorService = new ThreadPoolExecutor(size, size, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue());
        executorService.prestartAllCoreThreads(); try {
            FileReader fr = new FileReader(fileName);
            LineNumberReader br = new LineNumberReader(fr);
            String line; while ((line = br.readLine()) != null) { try {
                    rateLimiter.acquire();
                    executorService.submit(() -> { // TODO 編寫自己的數(shù)據(jù)處理邏輯 });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.exit(0);
    }
}

切換讀取新數(shù)據(jù)源

歷史所以數(shù)據(jù)同步完成后,將讀操作的開關(guān)關(guān)閉,讓其走讀新存儲的邏輯

這一步需要注意的是,此時只修改下行讀取數(shù)據(jù)的開關(guān)狀態(tài),讓其讀取新數(shù)據(jù)源,上行寫入數(shù)據(jù)開關(guān)不動,依舊讓其進行雙寫操作,防止下行切到新數(shù)據(jù)源有問題需要回滾導致新舊數(shù)據(jù)不一致的尷尬情況發(fā)生。

觀察線上業(yè)務(wù)是否正常

切到讀新存儲的邏輯下,觀察線上業(yè)務(wù),有無用戶投訴數(shù)據(jù)異常的情況

關(guān)閉就存儲的寫入

線上業(yè)務(wù)無異常情況,將寫操作也切到只寫新存儲的邏輯下,停止舊資源的寫入

刪除舊資源

將寫上所有舊 key 全部剔除,剔除舊數(shù)據(jù)的操作方式可以復用洗數(shù)據(jù)的流程即可。

下線舊的讀寫邏輯

將線上就的讀寫邏輯代碼全部下線,最終完成整個數(shù)據(jù)清洗的全流程

總結(jié)

以上,是一次完整的真實生產(chǎn)環(huán)境中問題排查及數(shù)據(jù)清洗全過程,通過本次問題的排查,也進一步加深了對 Redis 的底層實現(xiàn)的認識和理解;

同時,透過本次事故需要我們反思的是,面對親手寫下的每一行代碼,都需要懷著一顆敬畏心理,永遠不要輕視,有可能一個不小心就會釀成一個災(zāi)難性的事故。文章到此就先告一段落了,但是排查問題的腳步還在繼續(xù),歡迎關(guān)注我學習更多有干貨的知識。


免責聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉