主要就是要知道內(nèi)部的原理勋锤,以及一些內(nèi)存相關的配置。當內(nèi)存不足時醉冤,知道如何通過調(diào)整相關的配置來實現(xiàn)內(nèi)存優(yōu)化。
一篙悯、reids 內(nèi)存分析
redis內(nèi)存使用情況:info memory
示例:
可以看到,當前節(jié)點內(nèi)存碎片率為226893824/209522728≈1.08
鸽照,使用的內(nèi)存分配器是jemalloc韵吨。
used_memory_rss
通常情況下是大于 used_memory
的,因為內(nèi)存碎片的存在移宅。
但是當操作系統(tǒng)把redis內(nèi)存swap到硬盤時,memory_fragmentation_ratio 會小于1椿疗。redis使用硬盤作為內(nèi)存漏峰,因為硬盤的速度,redis性能會受到極大的影響届榄。
二浅乔、redis 內(nèi)存使用
redis的內(nèi)存使用分布:自身內(nèi)存,鍵值對象占用、緩沖區(qū)內(nèi)存占用及內(nèi)存碎片占用靖苇。
redis 空進程自身消耗非常的少席噩,可以忽略不計,優(yōu)化內(nèi)存可以不考慮此處的因素贤壁。
1悼枢、對象內(nèi)存
對象內(nèi)存,也即真實存儲的數(shù)據(jù)所占用的內(nèi)存脾拆。
redis k-v結(jié)構(gòu)存儲馒索,對象占用可以簡單的理解為 k-size + v-size
。
redis的鍵統(tǒng)一都為字符串類型名船,值包含多種類型:string绰上、list、hash渠驼、set蜈块、zset五種基本類型及基于string的Bitmaps和HyperLogLog類型等。
在實際的應用中迷扇,一定要做好kv的構(gòu)建形式及內(nèi)存使用預期百揭,可以參考 關于redis,你需要了解的幾點谋梭!中關于不同值類型不同形式下的內(nèi)部存儲實現(xiàn)介紹信峻。
2、緩沖內(nèi)存
緩沖內(nèi)存包括三部分:客戶端緩存瓮床、復制積壓緩存及AOF緩沖區(qū)盹舞。
1)客戶端緩存
接入redis服務器的TCP連接輸入輸出緩沖內(nèi)存占用,TCP輸入緩沖占用是不受控制的隘庄,最大允許空間為1G踢步。輸出緩沖占用可以通過client-output-buffer-limit參數(shù)配置。
redis 客戶端主要分為從客戶端丑掺、訂閱客戶端和普通客戶端获印。
從客戶端連接占用:也就是我們所說的slave,主節(jié)點會為每一個從節(jié)點建立一條連接用于命令復制街州,緩沖配置為:client-output-buffer-limit slave 256mb 64mb 60
兼丰。
主從之間的間絡延遲及掛載的從節(jié)點數(shù)量是影響內(nèi)存占用的主要因素。因此在涉及需要異地部署主從時要特別注意唆缴,另外鳍征,也要避免主節(jié)點上掛載過多的從節(jié)點(<=2);
訂閱客戶端內(nèi)存占用:發(fā)布訂閱功能連接客戶端使用單獨的緩沖區(qū)面徽,默認配置:client-output-buffer-limit pubsub 32mb 8mb 60艳丛。
當消費慢于生產(chǎn)時會造成緩沖區(qū)積壓匣掸,因此需要特別注意消費者角色配比及生產(chǎn)、消費速度的監(jiān)控氮双。
普通客戶端內(nèi)存占用:除了上述之外的其它客戶端碰酝,如我們通常的應用連接,默認配置:client-output-buffer-limit normal 1000戴差。
可以看到送爸,普通客戶端沒有配置緩沖區(qū)限制,通常一般的客戶端內(nèi)存消耗也可以忽略不計造挽。
但是當redis服務器響應較慢時碱璃,容易造成大量的慢連接,主要表現(xiàn)為連接數(shù)的突增饭入,如果不能及時處理嵌器,此時會嚴重影響redis服務節(jié)點的服務及恢復。
關于此谐丢,在實際應用中需要注意幾點:
- maxclients最大連接數(shù)配置必不可少爽航。
- 合理預估單次操作數(shù)據(jù)量(寫或讀)及網(wǎng)絡時延ttl。
- 禁止線上大吞吐量命令操作乾忱,如keys等讥珍。
高并發(fā)應用情景下,redis內(nèi)存使用需要有實時的監(jiān)控預警機制窄瘟,
2)復制積壓緩沖區(qū)
v2.8之后提供的一個可重用的固定大小緩沖區(qū)衷佃,用以實現(xiàn)向從節(jié)點的部分復制功能,避免全量復制蹄葱。配置單數(shù):repl-backlog-size
氏义,默認1M。單個主節(jié)點配置一個復制積壓緩沖區(qū)图云。
3)AOF緩沖區(qū)
AOF重寫期間增量的寫入命令保存惯悠,此部分緩存占用大小取決于AOF重寫時間及增量。
3竣况、內(nèi)存碎片內(nèi)存占用
關于redis克婶,你需要了解的幾點!簡單介紹過redis的內(nèi)存分配方式丹泉。(更多面試題情萤,歡迎關注公眾號 Java面試題精選)
三、redis 子進程內(nèi)存消耗
子進程即redis執(zhí)行持久化(RDB/AOF)時fork的子任務進程摹恨。
1筋岛、關于linux系統(tǒng)的寫時復制機制:
父子進程會共享相同的物理內(nèi)存頁,父進程處理寫請求時會對需要修改的頁復制一份副本進行修改睬塌,子進程讀取的內(nèi)存則為fork時的父進程內(nèi)存快照,因此,子進程的內(nèi)存消耗由期間的寫操作增量決定揩晴。
2勋陪、關于linux的透明大頁機制THP(Transparent Huge Page):
THP機制會降低fork子進程的速度;寫時復制內(nèi)存頁由4KB增大至2M硫兰。高并發(fā)情境下诅愚,寫時復制內(nèi)存占用消耗影響會很大,因此需要選擇性關閉劫映。
3违孝、關于linux配置:
一般需要配置linux系統(tǒng) vm.overcommit_memory=1
,以允許系統(tǒng)可以分配所有的物理內(nèi)存泳赋。防止fork任務因內(nèi)存而失敗雌桑。
四、redis 內(nèi)存管理
redis的內(nèi)存管理主要分為兩方面:內(nèi)存上限控制及內(nèi)存回收管理祖今。
1校坑、內(nèi)存上限:maxmemory
目的:緩存應用內(nèi)存回收機制觸發(fā) + 防止物理內(nèi)存用盡(redis 默認無限使用服務器內(nèi)存) + 服務節(jié)點內(nèi)存隔離(單服務器上部署多個redis服務節(jié)點)
在進行內(nèi)存分配及限制時要充分考慮內(nèi)存碎片占用影響。
動態(tài)調(diào)整千诬,擴展redis服務節(jié)點可用內(nèi)存:config set maxmemory {}
耍目。
2、內(nèi)存回收
回收時機:鍵過期徐绑、內(nèi)存占用達到上限
1)過期鍵刪除:
redis 鍵過期時間保存在內(nèi)部的過期字典中邪驮,redis采用惰性刪除機制+定時任務刪除機制。
惰性刪除:即讀時刪除傲茄,讀取帶有超時屬性的鍵時毅访,如果鍵已過期,則刪除然后返回空值烫幕。這種方式存在問題是俺抽,觸發(fā)時機,加入過期鍵長時間未被讀取较曼,那么它將會一直存在內(nèi)存中磷斧,造成內(nèi)存泄漏。
定時任務刪除:redis內(nèi)部維護了一個定時任務(默認每秒10次捷犹,可配置)弛饭,通過自適應法進行刪除。
刪除邏輯如下:
定時任務在每個數(shù)據(jù)庫空間隨機檢查20個鍵萍歉,當發(fā)現(xiàn)過期時刪除對應的鍵侣颂。
如果超過檢查數(shù)25%的鍵過期,循環(huán)執(zhí)行回收邏輯直到不足25%或運行超時為止枪孩,慢模式下超時時間為25ms癣漆。
如果之前回收鍵邏輯超時,則在Redis觸發(fā)內(nèi)部事件之前再次以快模式運行回收過期鍵任務顶考,快模式下超時時間為1ms且2s內(nèi)只能運行1次腮出。
快慢兩種模式內(nèi)部刪除邏輯相同,只是執(zhí)行的超時時間不同。
2)內(nèi)存溢出控制
當內(nèi)存達到maxmemory,會觸發(fā)內(nèi)存回收策略,具體策略依據(jù)maxmemory-policy來執(zhí)行州弟。
- noevication:默認不回收,達到內(nèi)存上限低零,則不再接受寫操作婆翔,并返回錯誤。
- volatile-lru:根據(jù)LRU算法刪除設置了過期時間的鍵掏婶,如果沒有則不執(zhí)行回收啃奴。
- allkeys-lru:根據(jù)LRU算法刪除鍵,針對所有鍵气堕。
- allkeys-random:隨機刪除鍵纺腊。
- volatitle-random:速記刪除設置了過期時間的鍵。
- volatilte-ttl:根據(jù)鍵ttl茎芭,刪除最近過期的鍵揖膜,同樣如果沒有設置過期的鍵,則不執(zhí)行刪除梅桩。
動態(tài)配置:config set maxmemory-policy {}
在設置了maxmemory情況下壹粟,每次的redis操作都會檢查執(zhí)行內(nèi)存回收,因此對于線上環(huán)境宿百,要確保所這只的maxmemory>used_memory
趁仙。
另外,可以通過動態(tài)配置maxmemory來主動觸發(fā)內(nèi)存回收垦页。