Redis內(nèi)存使用統(tǒng)計(jì)
命令
info memory
重點(diǎn)關(guān)注的指標(biāo)有:used_memory_rss和used_memory以及它們的比值mem_fragmentation_ratio蛙粘。
當(dāng) mem_fragmentation_ratio > 1 時(shí),說明used_memory_rss - used_memory多出的部分內(nèi)存并沒有用于數(shù)據(jù)存儲(chǔ)纬霞,而是被內(nèi)存碎片所消耗息裸,如果兩者相差很大芦鳍,說明碎片率嚴(yán)重。
當(dāng) mem_fragmentation_ratio < 1 時(shí),這種情況一般出現(xiàn)在操作系統(tǒng)把Redis內(nèi)存交換到(Swap)到硬盤導(dǎo)致,出現(xiàn)這種情況時(shí)要格外關(guān)注台腥,由于硬盤速度遠(yuǎn)遠(yuǎn)慢于內(nèi)存,Redis性能會(huì)變得很差绒北,甚至僵死览爵。
內(nèi)存消耗劃分
Redis進(jìn)程內(nèi)消耗主要包括:自身內(nèi)存+對(duì)象內(nèi)存+緩沖內(nèi)存+內(nèi)存碎片。
1. 對(duì)象內(nèi)存
對(duì)象內(nèi)存是Redis內(nèi)存占用最大的一塊镇饮,存儲(chǔ)著用戶所有的數(shù)據(jù)。Redis所有數(shù)據(jù)都采用key-value數(shù)據(jù)類型箕母,每次創(chuàng)建鍵值對(duì)時(shí)储藐,至少創(chuàng)建兩個(gè)類型對(duì)象:key對(duì)象和value對(duì)象。內(nèi)存消耗可以簡(jiǎn)單的理解為sizeof(keys)+sizeof(values)嘶是。鍵對(duì)象都是字符串钙勃,在使用Redis時(shí)很容易忽略鍵對(duì)內(nèi)存消耗的影響,應(yīng)當(dāng)避免使用過長(zhǎng)的鍵聂喇。value對(duì)象更復(fù)雜些辖源,主要包括5種基本數(shù)據(jù)類型:字符串、列表希太、哈希克饶、集合、有序集合誊辉。每種value對(duì)象類型根據(jù)使用規(guī)模不同矾湃,占用內(nèi)存不同。在使用時(shí)一定要合理預(yù)估并監(jiān)控value對(duì)象占用情況堕澄,避免內(nèi)存溢出邀跃。
2. 緩沖內(nèi)存
緩沖內(nèi)存主要包括:客戶端緩沖霉咨、復(fù)制積壓緩沖區(qū)、AOF緩沖區(qū)拍屑。
- 客戶端緩沖指的是所有接入到Redis服務(wù)器TCP連接的輸入輸出緩沖途戒。輸入輸出緩沖無法控制,最大空間為1G僵驰,如果超過將斷開連接喷斋。輸入緩沖通過參數(shù)client-output-buffer-limit控制:
1.普通客戶端:除了復(fù)制和訂閱的客戶端之外的所有連接,Redis的默認(rèn)配置是:client-output-buffer-limit normal 0 0 0矢渊,Redis并沒有對(duì)普通客戶端的輸出緩沖區(qū)做限制继准,一般普通客戶端的內(nèi)存消耗可以忽略不計(jì),但是當(dāng)有大量慢連接客戶端接入時(shí)這部分內(nèi)存消耗就不能忽略了矮男,可以設(shè)置maxclients做限制移必。注意不要只用大量數(shù)據(jù)輸出的命令且數(shù)據(jù)無法及時(shí)推送給客戶端,如 monitor命令毡鉴,容易造成Redis服務(wù)器內(nèi)存突然飆升崔泵。- 從客戶端:主節(jié)點(diǎn)會(huì)為每個(gè)從節(jié)點(diǎn)單獨(dú)建立一條連接用于命令復(fù)制,默認(rèn)配置是:client-output-buffer-limit slave 256mb 64mb 60猪瞬。當(dāng)主從節(jié)點(diǎn)之間網(wǎng)絡(luò)延遲較高或主節(jié)點(diǎn)掛載大量從節(jié)點(diǎn)時(shí)這部分內(nèi)存消耗將占用很大一部分憎瘸,建議主節(jié)點(diǎn)掛載的從節(jié)點(diǎn)不要多于2個(gè),主從節(jié)點(diǎn)不要部署在較差的網(wǎng)絡(luò)環(huán)境下陈瘦,如異地跨機(jī)房幌甘,防止復(fù)制客戶端連接緩慢造成溢出。
- 訂閱客戶端:當(dāng)使用發(fā)布訂閱功能時(shí)痊项,連接客戶端使用單獨(dú)的輸出緩沖區(qū)锅风,默認(rèn)配置為:client-output-buffer-limit pubsub 32mb 8mb 60,當(dāng)訂閱服務(wù)的消息生產(chǎn)快于消費(fèi)速度時(shí)鞍泉,輸出緩沖區(qū)會(huì)產(chǎn)生積壓造成輸出緩沖區(qū)空間溢出皱埠。
- 復(fù)制積壓緩沖區(qū):Redis在2.8版本之后提供了一個(gè)可重用的固定大小緩沖區(qū)用于實(shí)現(xiàn)部分復(fù)制功能,根據(jù)repl-backlog-size參數(shù)控制咖驮,默認(rèn)為1MB边器。對(duì)于復(fù)制積壓緩沖區(qū)整個(gè)主節(jié)點(diǎn)只有一個(gè),所有從節(jié)點(diǎn)共享此緩沖區(qū)托修,因此可以設(shè)置較大的緩沖區(qū)空間忘巧,如100MB。
- AOF緩沖區(qū):這部分空間用于在Redis重寫期間保存最近的寫入命令诀黍。
3.內(nèi)存碎片
Redis默認(rèn)的內(nèi)存分配器采用jemalloc袋坑,可選的分配器還有:glibc、tcmalloc。內(nèi)存分配器為了更好地管理和重復(fù)利用內(nèi)存枣宫,分配內(nèi)存策略一般采用固定范圍的內(nèi)存塊進(jìn)行分配婆誓。
以下場(chǎng)景容易出現(xiàn)高內(nèi)存碎片問題:
- 頻繁做更新操作,例如頻繁對(duì)已存在的鍵執(zhí)行append也颤、setrange等更新操作洋幻。
- 大量過期鍵刪除,鍵對(duì)象過期刪除后翅娶,釋放的空間無法得到充分利用文留,導(dǎo)致碎片率上升。
解決方式:
1. 數(shù)據(jù)對(duì)齊:在條件允許的情況下盡量做數(shù)據(jù)對(duì)齊竭沫,比如數(shù)據(jù)盡量采用數(shù)字類型或者固定長(zhǎng)度字符串等燥翅,但是這要視具體業(yè)務(wù)而定。
2.安全重啟:重啟節(jié)點(diǎn)可以做到內(nèi)存碎片重新整理蜕提,因此可以利用高可用架構(gòu)森书,比如Sentinel或Cluster,將碎片率過高的主節(jié)點(diǎn)轉(zhuǎn)換為從節(jié)點(diǎn)谎势,進(jìn)行安全重啟凛膏。