Redis所有的數(shù)據(jù)結(jié)構(gòu)都可以設(shè)置過期時間恬口,時間一到就會自動刪除比伏。
思考:Redis是單線程的,刪除key的時間也會占用線程的處理時間账月,如果刪除過于頻繁综膀,會導(dǎo)致CPU負載過高嗎,會導(dǎo)致線上讀寫指令出現(xiàn)卡頓嗎局齿?
下面來談?wù)凴edis的兩種刪除策略剧劝。
兩種刪除策略
定時刪除(集中處理)
Redis會將每個設(shè)置了過期時間的key放入到一個獨立的字典中,定時遍歷這個字典來刪除到期的key抓歼。
Redis默認每秒進行十次過期掃描讥此,過期掃描不會遍歷過期字典中的所有key,而是采用了一種簡單的貪心策略谣妻。
- 從過期字典中隨機20個key萄喳;
- 刪除這20個key中已經(jīng)過期的key;
- 如果過期Key的比率超過四分之一蹋半,重復(fù)步驟1他巨。
同時為了保證不會出現(xiàn)循環(huán)過度導(dǎo)致線程卡死,算法增加了掃描時間上線(默認25ms)减江。
惰性刪除(零散處理)
Redis在客戶端訪問這個key的時候染突,會對key的過期時間進行檢查,如果過期了就立即刪除辈灼。
Redis中大量key同一時間過期問題
Redis實例中存在大量同一時間過期的key過期時份企,Redis會持續(xù)掃描過期(循環(huán)多次),直到過期字段中過期的key變得稀疏茵休,才會停止(循環(huán)次數(shù)明顯下降)薪棒。這就會導(dǎo)致線上讀寫請求出現(xiàn)明顯的卡頓現(xiàn)象。導(dǎo)致這種卡頓的另外一種原因是內(nèi)存管理器需要頻繁的回收內(nèi)存頁榕莺,產(chǎn)生CPU消耗俐芯。
掃描上線25ms看起來不會導(dǎo)致卡頓,假設(shè)101個客戶端同事將請求發(fā)送過來钉鸯,前100個請求的執(zhí)行時間都是25ms吧史,那么第101個指令需要等待2500ms才能執(zhí)行,這就是客戶端卡頓時間唠雕,由于服務(wù)器不間斷的小卡頓積少成多贸营。
所以開發(fā)時需要注意過期時間吨述,如果有大批量key過期,要給過期時間設(shè)置一個隨機范圍钞脂,而不能全部在同一時間過期揣云。
實踐中如電商降價活動是一期一期舉辦的,下期舉辦時冰啃,前面幾期的數(shù)據(jù)可以過期了邓夕,所以一般都會設(shè)置一個過期時間,減少不必要的內(nèi)存占用阎毅,這個時候就需要將這些同時設(shè)置過期時間的商品使用固定時間+隨機時間焚刚,讓這些key不會同時過期。
從庫的過期策略
從庫不會進行定期掃描扇调,對過期的處理是被動的矿咕。主庫在key到期時,會在AOF文件里面增加一條del命令狼钮,同步到所有的從庫碳柱,從庫通過執(zhí)行這條del指令來刪除過期的key。
因為指令同步是異步進行的燃领,所以主庫過期的key的del指令沒有及時同步到從庫的話士聪,會出現(xiàn)主從數(shù)據(jù)不一致的情況。例如集群環(huán)境下分布式鎖的算法漏洞就是因為這個同步延時產(chǎn)生的猛蔽。