網(wǎng)站首頁 編程語言 正文
Redis服務(wù)器實際使用的是惰性刪除和定期刪除兩種策略:通過配合使用這兩種刪除策略,服務(wù)器可以很好地在合理使用CPU時間和避免浪費內(nèi)存空間之間取得平衡。
惰性刪除
惰性刪除策略對CPU時間來說是最友好的:程序只會在取出鍵時才對鍵進行過期檢查,這可以保證刪除過期鍵的操作只會在非做不可的情況下進行,并且刪除的目標僅限于當前處理的鍵,這個策略不會在刪除其他無關(guān)的過期鍵上花費任何CPU時間。
惰性刪除策略的缺點是,它對內(nèi)存是最不友好的:如果一個鍵已經(jīng)過期,而這個鍵又仍然保留在數(shù)據(jù)庫中,那么只要這個過期鍵不被刪除,它所占用的內(nèi)存就不會釋放。
在使用惰性刪除策略時,如果數(shù)據(jù)庫中有非常多的過期鍵,而這些過期鍵又恰好沒有被訪問到的話,那么它們也許永遠也不會被刪除(除非用戶手動執(zhí)行FLUSHDB),我們甚至可以將這種情況看作是一種內(nèi)存泄漏——無用的垃圾數(shù)據(jù)占用了大量的內(nèi)存,而服務(wù)器卻不會自己去釋放它們,這對于運行狀態(tài)非常依賴于內(nèi)存的Redis服務(wù)器來說,肯定不是一個好消息。
舉個例子,對于一些和時間有關(guān)的數(shù)據(jù),比如日志(log),在某個時間點之后,對它們的訪問就會大大減少,甚至不再訪問,如果這類過期數(shù)據(jù)大量地積壓在數(shù)據(jù)庫中,用戶以為服務(wù)器已經(jīng)自動將它們刪除了,但實際上這些鍵仍然存在,而且鍵所占用的內(nèi)存也沒有釋放,那么造成的后果肯定是非常嚴重的。
定期刪除
從上面對惰性刪除的討論來看,這刪除方式在單一使用時有明顯的缺陷:
惰性刪除浪費太多內(nèi)存,有內(nèi)存泄漏的危險。定期刪除策略是前兩種策略的一種整合和折中:
定期刪除策略每隔一段時間執(zhí)行一次刪除過期鍵操作,并通過限制刪除操作執(zhí)行的時長和頻率來減少刪除操作對CPU時間的影響。除此之外,通過定期刪除過期鍵,定期刪除策略有效地減少了因為過期鍵而帶來的內(nèi)存浪費。定期刪除策略的難點是確定刪除操作執(zhí)行的時長和頻率:
如果刪除操作執(zhí)行得太頻繁,或者執(zhí)行的時間太長,定期刪除策略就會退化成定時刪除策略,以至于將CPU時間過多地消耗在刪除過期鍵上面。
如果刪除操作執(zhí)行得太少,或者執(zhí)行的時間太短,定期刪除策略又會和惰性刪除策略一樣,出現(xiàn)浪費內(nèi)存的情況。因此,如果采用定期刪除策略的話,服務(wù)器必須根據(jù)情況,合理地設(shè)置刪除操作的執(zhí)行時長和執(zhí)行頻率。
惰性刪除策略
過期鍵的惰性刪除策略由db.c/expireIfNeeded函數(shù)實現(xiàn),所有讀寫數(shù)據(jù)庫的Redis命令在執(zhí)行之前都會調(diào)用expireIfNeeded函數(shù)對輸入鍵進行檢查:
如果輸入鍵已經(jīng)過期,那么expireIfNeeded函數(shù)將輸入鍵從數(shù)據(jù)庫中刪除。
如果輸入鍵未過期,那么expireIfNeeded函數(shù)不做動作。
expireIfNeeded函數(shù)就像一個過濾器,它可以在命令真正執(zhí)行之前,過濾掉過期的輸入鍵,從而避免命令接觸到過期鍵。
另外,因為每個被訪問的鍵都可能因為過期而被expireIfNeeded函數(shù)刪除,所以每個命令的實現(xiàn)函數(shù)都必須能同時處理鍵存在以及鍵不存在這兩種情況:
當鍵存在時,命令按照鍵存在的情況執(zhí)行。
當鍵不存在或者鍵因為過期而被expireIfNeeded函數(shù)刪除時,命令按照鍵不存在的情況執(zhí)行。
定期刪除策略的實現(xiàn)
過期鍵的定期刪除策略由redis.c/activeExpireCycle函數(shù)實現(xiàn),每當Redis的服務(wù)器周期性操作redis.c/serverCron函數(shù)執(zhí)行時,activeExpireCycle函數(shù)就會被調(diào)用,它在規(guī)定的時間內(nèi),分多次遍歷服務(wù)器中的各個數(shù)據(jù)庫,從數(shù)據(jù)庫的expires字典中隨機檢查一部分鍵的過期時間,并刪除其中的過期鍵。
整個過程可以用偽代碼描述如下
activeExpireCycle函數(shù)的工作模式可以總結(jié)如下:
函數(shù)每次運行時,都從一定數(shù)量的數(shù)據(jù)庫中取出一定數(shù)量的隨機鍵進行檢查,并刪除其中的過期鍵。
全局變量current_db會記錄當前activeExpireCycle函數(shù)檢查的進度,并在下一次activeExpireCycle函數(shù)調(diào)用時,接著上一次的進度進行處理。比如說,如果當前activeExpireCycle函數(shù)在遍歷10號數(shù)據(jù)庫時返回了,那么下次activeExpireCycle函數(shù)執(zhí)行時,將從11號數(shù)據(jù)庫開始查找并刪除過期鍵。
隨著activeExpireCycle函數(shù)的不斷執(zhí)行,服務(wù)器中的所有數(shù)據(jù)庫都會被檢查一遍,這時函數(shù)將current_db變量重置為0,然后再次開始新一輪的檢查工作。
當服務(wù)器運行在復(fù)制模式下時,從服務(wù)器的過期鍵刪除動作由主服務(wù)器控制:
主服務(wù)器在刪除一個過期鍵之后,會顯式地向所有從服務(wù)器發(fā)送一個DEL命令,告知從服務(wù)器刪除這個過期鍵。
從服務(wù)器在執(zhí)行客戶端發(fā)送的讀命令時,即使碰到過期鍵也不會將過期鍵刪除,而是繼續(xù)像處理未過期的鍵一樣來處理過期鍵
從服務(wù)器只有在接到主服務(wù)器發(fā)來的DEL命令之后,才會刪除過期鍵。
通過由主服務(wù)器來控制從服務(wù)器統(tǒng)一地刪除過期鍵,可以保證主從服務(wù)器數(shù)據(jù)的一致性,也正是因為這個原因,當一個過期鍵仍然存在于主服務(wù)器的數(shù)據(jù)庫時,這個過期鍵在從服務(wù)器里的復(fù)制品也會繼續(xù)存在。舉個例子,有一對主從服務(wù)器,它們的數(shù)據(jù)庫中都保存著同樣的三個鍵message、xxx和yyy,其中message為過期鍵,如圖所示。
如果這時有客戶端向從服務(wù)器發(fā)送命令GET message,那么從服務(wù)器將發(fā)現(xiàn)message鍵已經(jīng)過期,但從服務(wù)器并不會刪除message鍵,而是繼續(xù)將message鍵的值返回給客戶端,就好像message鍵并沒有過期一樣
假設(shè)在此之后,有客戶端向主服務(wù)器發(fā)送命令GET message,那么主服務(wù)器將發(fā)現(xiàn)鍵message已經(jīng)過期:主服務(wù)器會刪除message鍵,向客戶端返回空回復(fù),并向從服務(wù)器發(fā)送DEL message命令
從服務(wù)器在接收到主服務(wù)器發(fā)來的DEL message命令之后,也會從數(shù)據(jù)庫中刪除message鍵,在這之后,主從服務(wù)器都不再保存過期鍵message了
原文鏈接:https://blog.csdn.net/qq_28056571/article/details/103911095
相關(guān)推薦
- 2023-09-12 SpringBoot整合MQTT(MqttClient)
- 2024-01-14 三種線程安全的List
- 2022-08-20 python?memory_profiler庫生成器和迭代器內(nèi)存占用的時間分析_python
- 2023-12-10 記錄一次多數(shù)據(jù)源配置失效的情況
- 2022-11-20 golang?實現(xiàn)?pdf?轉(zhuǎn)高清晰度?jpeg的處理方法_Golang
- 2022-06-01 SQL為什么不建議執(zhí)行超過3表以上的多表關(guān)聯(lián)查詢_MsSql
- 2022-10-09 React高階組件的使用淺析_React
- 2022-10-16 pytorch中.numpy()、.item()、.cpu()、.detach()以及.data的使
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支