日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

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


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

作者:z小趙

一枚用心堅(jiān)持寫(xiě)原創(chuàng)的“無(wú)趣”程序猿,在自身受益的同時(shí)也讓朋友們?cè)诩夹g(shù)上有所提升。


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

問(wèn)題現(xiàn)象

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

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

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

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

但是從接口的請(qǐng)求量來(lái)看的話(huà),刷量的情況并沒(méi)有那么明顯,下面是接口請(qǐng)求的 qps:

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

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

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

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

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

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


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

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

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

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

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

疑點(diǎn)二:容量評(píng)估公式有問(wèn)題

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

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

洗庫(kù)流程介紹

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

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

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

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

上線(xiàn)雙寫(xiě)邏輯

在資源存儲(chǔ)層,對(duì)上下行讀寫(xiě)操作分別增加 switcher(開(kāi)關(guān)),然后增加讀寫(xiě)新存儲(chǔ)的邏輯,代碼測(cè)試通過(guò)后上線(xiàn)。

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

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

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

關(guān)于同步歷史數(shù)據(jù),需要根據(jù)自身實(shí)際的業(yè)務(wù)場(chǎng)景去做適當(dāng)?shù)恼{(diào)整,這里只提供一個(gè)思路。下面是洗數(shù)據(jù)可以使用的小工具,需要的朋友可以適當(dāng)調(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 編寫(xiě)自己的數(shù)據(jù)處理邏輯 });
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.exit(0);
    }
}

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

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

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

觀(guān)察線(xiàn)上業(yè)務(wù)是否正常

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

關(guān)閉就存儲(chǔ)的寫(xiě)入

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

刪除舊資源

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

下線(xiàn)舊的讀寫(xiě)邏輯

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

總結(jié)

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

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


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

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

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

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

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

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

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

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

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

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

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

關(guān)鍵字: 電動(dòng)汽車(chē) 新能源 驅(qū)動(dòng)電源

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

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

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

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

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

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

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

關(guān)鍵字: LED 驅(qū)動(dòng)電源 開(kāi)關(guān)電源

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

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