一、为什么要用渐进式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就是“蚂蚁搬家”,把大任务拆成小步骤,边服务边迁移,既保证速度,又不影响用户体验。这下明白了吧?👨💻