Redis 所有的資料結構都可以設定過期時間,時間一到,就會自動洗掉,你可以想象 Redis 內部有一個死神,時刻盯著所有設定了過期時間的 key,壽命一到就會立即收割,
你還可以進一步站在死神的角度思考,會不會因為同一時間太多的 key 過期,以至于忙不過來,同時因為 Redis 是單執行緒的,收割的時間也會占用執行緒的處理時間,如果收割的太過于繁忙,會不會導致線上讀寫指令出現卡頓,
這些問題 Antirez 早就想到了,所有在過期這件事上,Redis 非常小心,
過期的 key 集合
redis 會將每個設定了過期時間的 key 放入到一個獨立的字典中,以后會定時遍歷這個字典來洗掉到期的 key,除了定時遍歷之外,它還會使用惰性策略來洗掉過期的 key,所謂惰性策略就是在客戶端訪問這個 key 的時候,redis 對 key 的過期時間進行檢查,如果過期了就立即洗掉,定時洗掉是集中處理,惰性洗掉是零散處理,
定時掃描策略
Redis 默認會每秒進行十次過期掃描,過期掃描不會遍歷過期字典中所有的 key,而是采用了一種簡單的貪心策略,
- 從過期字典中隨機 20 個 key;
洗掉這 20 個 key 中已經過期的 key;
如果過期的 key 比率超過 1/4,那就重復步驟 1;
同時,為了保證過期掃描不會出現回圈過度,導致執行緒卡死現象,演算法還增加了掃描時間的上限,默認不會超過 25ms,
設想一個大型的 Redis 實體中所有的 key 在同一時間過期了,會出現怎樣的結果?
毫無疑問,Redis 會持續掃描過期字典 (回圈多次),直到過期字典中過期的 key 變得稀疏,才會停止 (回圈次數明顯下降),這就會導致線上讀寫請求出現明顯的卡頓現象,導致這種卡頓的另外一種原因是記憶體管理器需要頻繁回收記憶體頁,這也會產生一定的 CPU 消耗,
當客戶端請求到來時,服務器如果正好進入過期掃描狀態,客戶端的請求將會等待至少 25ms 后才會進行處理,如果客戶端將超時時間設定的比較短;
- 比如 10ms,那么就會出現大量的鏈接因為超時而關閉,業務端就會出現很多例外,而且這時你還無法從 Redis 的 slowlog 中看到慢查詢記錄,因為慢查詢指的是邏輯處理程序慢,不包含等待時間,
所以業務開發人員一定要注意過期時間,如果有大批量的 key 過期,要給過期時間設定一個隨機范圍,而不宜全部在同一時間過期,分散過期處理的...
以上內容希望幫助到大家,很多PHPer在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,不知道該從那里入手去提升,對此我整理了一些資料,包括但不限于:分布式架構、高可擴展、高性能、高并發、服務器性能調優、Redis、Kafka、Mysql優化、shell腳本、Docker、微服務、Nginx等多個知識點高級進階干貨需要的可以免費分享給大家
相應的文章已經整理形成檔案,git掃碼獲取資料看這里
https://gitee.com/biwangsheng/personal.git
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/59813.html
標籤:Java
