天天看點

記一次redis異常停止排查及參數優化調節配置參數

背景

跑一個程式,程式采取redis存儲任務狀态及任務值,程式通過redis擷取任務後進行任務下發

記一次redis異常停止排查及參數優化調節配置參數

現象

正在運作的任務進度突然停止,檢視執行應用日志,發現報錯

日志報錯資訊

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

處理過程

根據報錯猜測的可能原因有:

  • 1 Jedis 對象用完以後,沒有釋放掉,被一直占用,是以會出現無法擷取新的資源
  • 2 redis服務找不到了

    考慮到隻有一個程式在連接配接redis,應該不會出現連接配接不夠用的情況

是以先從redis的狀态開始排查

1 檢視redis狀态

ps  -ef | grep  redis
           

發現redis程序沒了,檢視曆史登陸和曆史指令,沒有人工停止的迹象

因為沒發現什麼問題,就手動重新開機了redis

/redis-server ../redis.conf &
           

重新開機後觀察應用日志,發現開始又報新的錯誤:

redis.clients.jedis.exceptions.JedisDataException: MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error.

redis.clients.jedis.exceptions.JedisDataException: MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk.

通過日志可以看到,報空間不足,是以進行檢視伺服器狀态

檢視磁盤空間顯示是充足的

檢視記憶體狀态

free -m
           

發現記憶體剩餘不足

記一次redis異常停止排查及參數優化調節配置參數

登陸redis用戶端檢視記憶體使用情況

redis-cli -h ip -p port
 info memory
           
記一次redis異常停止排查及參數優化調節配置參數
參數詳解:

used_memory : 由 Redis 配置設定器配置設定的記憶體總量,以位元組(byte)為機關

used_memory_human : 以人類可讀的格式傳回 Redis 配置設定的記憶體總量

used_memory_rss : 從作業系統的角度,傳回 Redis 已配置設定的記憶體總量(俗稱常駐集大小)。這個值和 top 、 ps 等指令的輸出一緻

used_memory_peak : Redis 的記憶體消耗峰值(以位元組為機關)

used_memory_peak_human : 以人類可讀的格式傳回 Redis 的記憶體消耗峰值

used_memory_lua : Lua 引擎所使用的記憶體大小(以位元組為機關)

mem_fragmentation_ratio : used_memory_rss 和 used_memory 之間的比率

mem_allocator : 在編譯時指定的, Redis 所使用的記憶體配置設定器。可以是 libc 、 jemalloc 或者 tcmalloc

對比幾個值

1)當 rss > used ,且兩者的值相差較大時,表示存在(内部或外部的)記憶體碎片。

記憶體碎片的比率可以通過 mem_fragmentation_ratio 的值看出。

2)當 used > rss 時,表示 Redis 的部分記憶體被作業系統換出到交換空間了,在這種情況下,操作可能會産生明顯的延遲

參數參考:

https://jingyan.baidu.com/article/2c8c281dbd079f0008252a0f.html

發現redis使用記憶體已經4G了,比最開始啟動時的記憶體多出來很多,檢視相關資料了解:

Redis的記憶體如果不在啟動前限制,預設是無限制的,32位的redis會限制在3G,目前使用的是64位,是以在使用過程中因為key的增加記憶體不斷的增加

調節配置參數

總結實際修改過的的步驟:

  • 1 将stop-writes-on-bgsave-error設定為no
stop-writes-on-bgsave-error no
           
  • 2 配置maxmemory(部分起到作用)
maxmemory 記憶體大小(位元組)
           
  • 3 系統層面添加overcommit_memory
vim /etc/sysctl.conf
vm.overcommit_memory=1 
使檔案生效
sysctl -p /etc/sysctl.conf           
  • 4 修改redis

    清理不使用的key(實際解決問題的辦法)

實際試錯的排查過程

1 查詢資料說可能是bgsave失敗,臨時的解決辦法是

stop-writes-on-bgsave-error yes修改為 stop-writes-on-bgsave-error no

bgsave方法的介紹:

記一次redis異常停止排查及參數優化調節配置參數
記一次redis異常停止排查及參數優化調節配置參數

結果:

修改了,重新開機,沒效果

2 又看到需要修改系統層面參數

vim /etc/sysctl.conf

vm.overcommit_memory=1
           

使檔案生效

sysctl -p /etc/sysctl.conf
           
記憶體仍然沒有下去,不可用
           

3 修改redis key過期算法

maxmemory-policy volatile-lru

LRU是Least Recently Used 近期最少使用算法。
  1. volatile-lru -> 根據LRU算法生成的過期時間來删除。
  2. allkeys-lru -> 根據LRU算法删除任何key。
  3. volatile-random -> 根據過期設定來随機删除key。
  4. allkeys->random -> 無差别随機删。
  5. volatile-ttl -> 根據最近過期時間來删除(輔以TTL)
  6. noeviction -> 誰也不删,直接在寫操作時傳回錯誤。
    記一次redis異常停止排查及參數優化調節配置參數

記憶體占用還是4G,沒有消減

記一次redis異常停止排查及參數優化調節配置參數

4 修改maxmemory

檢視redis相關資料,發現:

如果不設定maxmemory或者設定為0,64位系統不限制記憶體,32位系統最多使用3GB記憶體。

是以通過修改redis.conf配置,指定可使用的最大記憶體

修改maxmemory 3221225472(3G)
           
記一次redis異常停止排查及參數優化調節配置參數

重新開機

啟動後直接報錯:

redis.clients.jedis.exceptions.JedisDataException: OOM command not allowed when used memory > 'maxmemory'.

使用config get * 指令得到redis 的maxmemory

>config get *
           
記一次redis異常停止排查及參數優化調節配置參數

檢視修改的配置是生效的

檢視實際使用的記憶體:

>info memory
           
記一次redis異常停止排查及參數優化調節配置參數

實際使用還是4G

看來還是key太大了,自動清理機制還是不能解決問題

解決

為了任務能繼續跑下去,把key消費完,手動的調低同伺服器其他機器的jvm啟動參數,程式繼續跑了下去

5 手動清理key

在任務跑的差不多時候,手動清理不需要的key值

總結

這次問題最原始的原因是沒有做記憶體限制,導緻随着key的不斷增加,記憶體逐漸變多

以後在安裝配置64位的redis時,最開始就要設定最大使用記憶體和清理key的算法,這樣不會影響其他服務