作者回复: 回答的很好! 我再提个小问题,如果在数组上是随机访问,对CPU高速缓存还友好不?:)
作者回复: 渐进式rehash执行时,除了根据键值对的操作来进行数据迁移,Redis本身还会有一个定时任务在执行rehash,如果没有键值对操作时,这个定时任务会周期性地(例如每100ms一次)搬移一些数据到新的哈希表中,这样可以缩短整个rehash的过程。
作者回复: 赞!所以不同的设计选择都是有背后的考虑。
作者回复: 看得非常仔细,赞一个! zset有个ZSCORE的操作,用于返回单个集合member的分数,它的操作复杂度是O(1),这就是收益于你这看到的hash table。这个hash table保存了集合元素和相应的分数,所以做ZSCORE操作时,直接查这个表就可以,复杂度就降为O(1)了。 而跳表主要服务范围操作,提供O(logN)的复杂度。
作者回复: 这个全局是指Redis数据库中的所有key和value,是由一个哈希表来索引的。通过在这个哈希表中查询key,就可以找到对应的value。然后根据value的具体类型(例如Hash,Set,List等),再通过value的底层数据结构来读取具体的value数据,例如List通过双向链表来读取数据。
作者回复: dict的渐进式rehash是为了避免扩容时的整体拷贝,这会给内存带来较大压力。 SDS我们后面还会再聊:)
作者回复: 我们后面的课程会涉及这个过程,再耐心等等哈
作者回复: 一个对象保存到哈希桶时,实际是要用它的hash值对哈希桶个数取模的,所以rehash时,桶个数发生了变化,那么对象的存储位置也会有所变化。 跳表的查找通过不同层的指针来跳转,指针比较多时,类似于二分查找了。
作者回复: 提个小问题哈,如果压缩列表也是随机跳着访问,对CPU缓存还友好不?
作者回复: 是的,哈希表这个结构,整个数据库空间用它来保存键值对,同时HASH类型的键值对也用它作为底层结构。所以,rehash也是两种情况下都有的。