redis 限制內存使用大小的實現
記錄一次生產環境問題排查過程:
生產環境部署方式:nginx + uwsgi + flask
問題描述:
發現生產環境中之前正常運行的服務突然不可用瞭,查看程序日志發現部分接口訪問時報I/O寫錯誤,nginx acess.log顯示504,error.log顯示 upstream time out.
同時netstat -apn | grep 6379 | wc -l
檢查發現redis存在大量連接,進一步檢查發現其中大多為SYN_SENT
包,連接大多歸屬於uwsgi
進程。
因為程序中有很多接口被調用是會訪問redis, 以為是redis連接池導致,對程序中的redis連接池進行優化後重啟服務,剛啟動時一切正常,http 200, 但幾分鐘後服務再次掛掉,http 504.
檢查系統資源使用情況,發現 kswapd0
進程CPU占用很高,這個進程是當物理內存不足時,會將一部分硬盤當做虛擬內存來使用, 使用swap分區與內存換頁操作交換數據,導致CPU占用過高, 再細看發現redis-server
內存占用已超過100%:
進入redis中查看info memory
和各存儲數據的key下數據量,果然存在大量未處理完畢的數據。
到此問題終於是找到瞭。
設置redis最大占用內存
# 編輯redis配置文件,加入最大內存使用限制,我根據服務器的情況設置為3G maxmemory 3221225472
設置redis數據過期策略:
redis中有6種過期策略:
# 根據LRU算法生成的過期時間來刪除 # volatile-lru -> remove the key with an expire set using an LRU algorithm # 根據LRU算法刪除任何key。 # allkeys-lru -> remove any key accordingly to the LRU algorithm # 根據過期設置來隨機刪除key。 # volatile-random -> remove a random key with an expire set # 無差別隨機刪。 # allkeys-random -> remove a random key, any key # 根據最近過期時間來刪除(輔以TTL) # volatile-ttl -> remove the key with the nearest expire time (minor TTL) # 誰也不刪,直接在寫操作時返回錯誤。 # noeviction -> don't expire at all, just return an error on write operations
在redis配置文件中設置過期策略為:maxmemory-policy allkeys-lru
一開始是設置為volatile-lru
的,但是該策略隻是清除設置過期時間的key值,因為很多key並沒有設置過期時間。因此修改為maxmemory-policy allkeys-lru
,指明非活躍近期很少用的key值清除.
在使用maxmemory-policy allkeys-lru
策略時,內存超限後將不再存儲數據,但數據的讀取刪除操作不會受影響,超限時顯示錯誤
OOM command not allowed when used memory > ‘maxmemory’
重啟程序,至此服務終於正常運行。
總結:本次的問題歸根結底是redis中存儲入瞭大量臟數據,但數據處理並沒有及時的清理掉這部分數據,最終導致服務停滯,allkeys-lru
策略有可能會將長期未用但實際有用的數據清理掉,所以還是應優化數據處理為主。
到此這篇關於redis 限制內存使用大小的實現的文章就介紹到這瞭,更多相關redis 限制內存內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!