数据的底层存储原理
Redis数据库是基于K-V形式存储值的,他的底层存储原理类似于hashMap。通过hash(key) % hashtable.size 存到对应的桶位置, 每个桶的位置又是基于链表形式把hash结果相同的数据存放到同一个链表中。
hash槽扩容的原理
通过复制多一倍的hashtable.size 进行扩容 (Redis版本不一样扩容方式也不一样,具体要看Redis对应版本,有的版本是翻倍扩容,有的版本是当前size(原来的size+1)的最小的2的幂次方)。
创建数组后,就会将数据进行rehash操作放置到新的hash槽里面(hash(key) % newHashtable.size)。
但是这并不是立即触发的, Redis会将数据一点点(按旧hashtable的槽顺序来,一次一个槽)的存到新的hashtable里面(因为redis工作线程是单线程,如果一次性操作所有数据的话则会造成阻塞卡顿,影响性能),这种模式也叫渐进式rehash。
rehash方式
在每一次CRUD命令执行时,都会判断当前是否是在进行rehash,如果是,则帮助进行一次rehash操作。
或者定时进行rehash,redis会有一个定时任务,定时遍历所有的db的哈希表,进行rehash操作,每次操作的时间上限目前是 1 毫秒,循环操作,一次循环操作100个key。
当rehash操作完成时,则会把旧的table进行删除,然后把旧的table地址指向新的table进行切换,把rehash的标志位进行修改成已完成,告诉redis不需要在进行rehash了(rehashidx置为-1)。
总结
过程大概如下:
1,初始化table1,rehashidx 置为0,rehash开始
2,每次CRUD操作都会辅助进行一次rehash
3,定时任务遍历16个DB,执行rehash操作,while循环,每次循环rehash100个,一次循环时间上限时一毫秒
4,在这期间,所有新增都是写table1里,查,删,改则同时在两个表进行
5,rehash结束后会回收掉table1的内存, 然后把table1的地址赋值给table0,rehashidx置为-1,至此本次rehash就完成了