redis主從從庫沒同步的時候?
首先,在redis社區版本中正常的主從復制也會出現過期時間不一致問題,主要是由于主從進行全同步期間,如果主庫此時有expire 命令,那么到從庫中,該命令將會被延遲執行。因為全同步需要耗費時間,數據量越大,那么過期時間差距就越大。
這個問題其實已經是官方的已知問題,解決方案有兩個:
1、業務采用expireat timestamp 方式,這樣命令傳送到從庫就沒有影響
2、在Redis代碼中將expire命令轉換為expireat命令
官方沒有做第二個選擇,反而是提供expireat命令來給用戶選擇。其實從另外一個角度來看,從庫的過期時間大于主庫的過期時間,其實影響不大。因為主庫會主動觸發過期刪除,如果該key刪除之后,主庫也會向從庫發送刪除的命令。但是如果主庫的key已經到了過期時間,redis沒有及時進行淘汰,這個時候訪問從庫該key,那么這個key是不會被觸發淘汰的,這樣如果對于過期時間要求非常苛刻的業務還是會有影響的。
而且目前針對于我們大規模遷移的時間,在進行過期時間校驗的時候,發現大量key的過期時間都不一致,這樣也不利于我們進行校驗。
所以針對第一個問題,我們將expire/pexpire/setex/psetex 命令在復制到從庫的時候轉換成時間戳的方式,比如expire 轉成expireat命令,setex轉換成set和expireat命令
2、遷移前后Redis key 數量不一致。
針對于第二個問題,Redis key 遷移前后數量不一致問題,其實在Redis社區版本的主從復制中,也會經常出現key數量不一致。其中一個非常關鍵的問題是,redis在做主從復制的時候,會對當前的存量數據做一個RDB快照(bgsave命令),然后將RDB快照傳給從庫,從庫會解析RDB文件并且load到內存中。然而在下面的兩個步驟中Redis會忽略過期的key:
1、主庫在做RDB快照文件的時候,發現key已經過期了,則此時不會將過期時間寫在RDB中
2、從庫在load RDB 文件到內存中的時候,發現key已經過期了,則此時不會將過期的key load進去
針對上述問題,目前我們將以上兩個步驟都改為不忽略過期key,過期key的刪除統一由主庫觸發刪除,然后將刪除命令傳送到從庫中。這樣key的數量就完全一致了。
最終在打上以上兩個patch之后,再進