redis 限制內(nèi)存使用大小的實(shí)現(xiàn)
記錄一次生產(chǎn)環(huán)境問(wèn)題排查過(guò)程:
生產(chǎn)環(huán)境部署方式:nginx + uwsgi + flask
問(wèn)題描述:
發(fā)現(xiàn)生產(chǎn)環(huán)境中之前正常運(yùn)行的服務(wù)突然不可用了,查看程序日志發(fā)現(xiàn)部分接口訪問(wèn)時(shí)報(bào)I/O寫錯(cuò)誤,nginx acess.log顯示504,error.log顯示 upstream time out.
同時(shí)netstat -apn | grep 6379 | wc -l檢查發(fā)現(xiàn)redis存在大量連接,進(jìn)一步檢查發(fā)現(xiàn)其中大多為SYN_SENT包,連接大多歸屬于uwsgi進(jìn)程。
因?yàn)槌绦蛑杏泻芏嘟涌诒徽{(diào)用是會(huì)訪問(wèn)redis, 以為是redis連接池導(dǎo)致,對(duì)程序中的redis連接池進(jìn)行優(yōu)化后重啟服務(wù),剛啟動(dòng)時(shí)一切正常,http 200, 但幾分鐘后服務(wù)再次掛掉,http 504.
檢查系統(tǒng)資源使用情況,發(fā)現(xiàn) kswapd0 進(jìn)程CPU占用很高,這個(gè)進(jìn)程是當(dāng)物理內(nèi)存不足時(shí),會(huì)將一部分硬盤當(dāng)做虛擬內(nèi)存來(lái)使用, 使用swap分區(qū)與內(nèi)存換頁(yè)操作交換數(shù)據(jù),導(dǎo)致CPU占用過(guò)高, 再細(xì)看發(fā)現(xiàn)redis-server內(nèi)存占用已超過(guò)100%:

進(jìn)入redis中查看info memory和各存儲(chǔ)數(shù)據(jù)的key下數(shù)據(jù)量,果然存在大量未處理完畢的數(shù)據(jù)。
到此問(wèn)題終于是找到了。
設(shè)置redis最大占用內(nèi)存
# 編輯redis配置文件,加入最大內(nèi)存使用限制,我根據(jù)服務(wù)器的情況設(shè)置為3G maxmemory 3221225472
設(shè)置redis數(shù)據(jù)過(guò)期策略:
redis中有6種過(guò)期策略:
# 根據(jù)LRU算法生成的過(guò)期時(shí)間來(lái)刪除 # volatile-lru -> remove the key with an expire set using an LRU algorithm # 根據(jù)LRU算法刪除任何key。 # allkeys-lru -> remove any key accordingly to the LRU algorithm # 根據(jù)過(guò)期設(shè)置來(lái)隨機(jī)刪除key。 # volatile-random -> remove a random key with an expire set # 無(wú)差別隨機(jī)刪。 # allkeys-random -> remove a random key, any key # 根據(jù)最近過(guò)期時(shí)間來(lái)刪除(輔以TTL) # volatile-ttl -> remove the key with the nearest expire time (minor TTL) # 誰(shuí)也不刪,直接在寫操作時(shí)返回錯(cuò)誤。 # noeviction -> don't expire at all, just return an error on write operations
在redis配置文件中設(shè)置過(guò)期策略為:maxmemory-policy allkeys-lru
一開(kāi)始是設(shè)置為volatile-lru的,但是該策略只是清除設(shè)置過(guò)期時(shí)間的key值,因?yàn)楹芏鄈ey并沒(méi)有設(shè)置過(guò)期時(shí)間。因此修改為maxmemory-policy allkeys-lru,指明非活躍近期很少用的key值清除.
在使用maxmemory-policy allkeys-lru策略時(shí),內(nèi)存超限后將不再存儲(chǔ)數(shù)據(jù),但數(shù)據(jù)的讀取刪除操作不會(huì)受影響,超限時(shí)顯示錯(cuò)誤
OOM command not allowed when used memory > 'maxmemory'

重啟程序,至此服務(wù)終于正常運(yùn)行。
總結(jié):本次的問(wèn)題歸根結(jié)底是redis中存儲(chǔ)入了大量臟數(shù)據(jù),但數(shù)據(jù)處理并沒(méi)有及時(shí)的清理掉這部分?jǐn)?shù)據(jù),最終導(dǎo)致服務(wù)停滯,allkeys-lru策略有可能會(huì)將長(zhǎng)期未用但實(shí)際有用的數(shù)據(jù)清理掉,所以還是應(yīng)優(yōu)化數(shù)據(jù)處理為主。
到此這篇關(guān)于redis 限制內(nèi)存使用大小的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)redis 限制內(nèi)存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
NestJS+Redis實(shí)現(xiàn)手寫一個(gè)限流器
限流是大型系統(tǒng)必備的保護(hù)措施,本文將結(jié)合redis , lua 腳本 以及 Nestjs Guard 來(lái)實(shí)現(xiàn) 限流的效果,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11
Redis鏈表底層實(shí)現(xiàn)及生產(chǎn)實(shí)戰(zhàn)
Redis 的 List 是一個(gè)雙向鏈表,鏈表中的每個(gè)節(jié)點(diǎn)都包含了一個(gè)字符串。是redis中最常用的數(shù)據(jù)結(jié)構(gòu)之一,本文主要介紹了Redis鏈表底層實(shí)現(xiàn)及生產(chǎn)實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03
Redis?中使用?list,streams,pub/sub?幾種方式實(shí)現(xiàn)消息隊(duì)列的問(wèn)題
這篇文章主要介紹了Redis?中使用?list,streams,pub/sub?幾種方式實(shí)現(xiàn)消息隊(duì)列,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03
簡(jiǎn)單粗暴的Redis數(shù)據(jù)備份和恢復(fù)方法
這里我們來(lái)講解一個(gè)簡(jiǎn)單粗暴的Redis數(shù)據(jù)備份和恢復(fù)方法,有一個(gè)在不同主機(jī)上遷移Redis數(shù)據(jù)的示例,還有一個(gè)備份腳本實(shí)現(xiàn)的關(guān)鍵點(diǎn)提示,一起來(lái)看一下:2016-06-06
SpringBoot整合Redis實(shí)現(xiàn)序列化存儲(chǔ)Java對(duì)象的操作方法
這篇文章主要介紹了SpringBoot整合Redis實(shí)現(xiàn)序列化存儲(chǔ)Java對(duì)象,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
redis客戶端實(shí)現(xiàn)高可用讀寫分離的方式詳解
基于sentienl 獲取和動(dòng)態(tài)感知 master、slaves節(jié)點(diǎn)信息的變化,我們的讀寫分離客戶端就能具備高可用+動(dòng)態(tài)擴(kuò)容感知能力了,接下來(lái)通過(guò)本文給大家分享redis客戶端實(shí)現(xiàn)高可用讀寫分離的方式,感興趣的朋友一起看看吧2021-07-07
基于redis樂(lè)觀鎖實(shí)現(xiàn)并發(fā)排隊(duì)
這篇文章主要介紹了基于redis樂(lè)觀鎖實(shí)現(xiàn)并發(fā)排隊(duì)的相關(guān)資料,需要的朋友可以參考下2022-12-12

