一、為什么要用漸進式rehash?
假設你家的舊柜子(哈希表)裝滿了,需要換個大柜子。如果一次性把所有東西倒騰到新柜子,你可能得停下手頭所有事,累得半死(這就是傳統rehash的問題:卡頓)。Redis為了不“累死”,選擇邊搬邊用,每次搬一點,這就是“漸進式”。
二、具體怎么“搬家”?
1?? 先準備好新柜子(分配空間)
? Redis會先申請一個更大的新哈希表(比如舊表兩倍大),這時候系統里同時有「舊表」和「新表」。
2?? 貼個標簽記錄搬到哪里了(rehashidx)
? 用一個標記rehashidx?(類似搬家進度條),初始設為0,表示從舊表的第0個位置開始搬。
3?? 邊干活邊搬東西(每次操作順帶遷移)
? 每次有人來查、改、刪數據時,Redis除了干活,還會順手把舊表當前進度條位置的數據搬到新表。比如你查了個數據,Redis搬完舊表第0個位置的數據后,把rehashidx?+1,下次搬第1個位置。
4?? 偷偷加班搬(定時任務輔助)
? 如果一直沒人操作,Redis也會自己開個“定時任務”,每次最多搬1毫秒,防止徹底擺爛。
5?? 搬完收尾(釋放舊表)
? 等舊表全搬空了,就把舊表扔掉,新表改名叫“舊表”,等待下次擴容。
三、搬家期間怎么保證正常使用?
? 查數據:先翻舊柜子,找不到再去新柜子找(兩邊都查)。
? 新增數據:直接扔到新柜子,舊柜子不再放新東西(保證舊柜子越來越空)。
? 刪/改數據:兩個柜子都要操作,比如刪舊柜子的數據,新柜子有的話也得刪。
四、這樣做有啥好處?
- 不卡頓:分攤搬家壓力,用戶無感知。
- 內存可控:舊柜子只減不增,不會無限膨脹。
- 平滑過渡:就像一邊開車一邊換輪胎,服務不中斷。
舉個栗子🌰
假設舊表有4個位置(0~3),現在要搬到8個位置的新表:
? 第1次有人查數據,Redis搬完位置0的數據,rehashidx?變成1。
? 第2次有人刪數據,順手搬位置1的數據,rehashidx?變成2。
? 搬完位置3后,舊表清空,換上新表,搬家完成!
總結:漸進式rehash就是“螞蟻搬家”,把大任務拆成小步驟,邊服務邊遷移,既保證速度,又不影響用戶體驗。這下明白了吧?👨💻