目录
字典的应用场景
源码实现
hash算法的实现, hash冲突的解决
扩容缩容机制
哈希表的扩展与收缩条件
渐进式rehash
线程是否安全
Redis的dictht 和 Java(jdk1.8)的HashMap有什么区别
线程安全性
hash算法
解决hash冲突的方法
扩容机制
字典的应用场景
1.redis数据库本身的实现就是 字典,因为redis本身就是 kv存储的。
2.redis数据结构中的Set也是用了字典。
源码实现
和Java类似,也是 table ,entry等数据结构。
当字典被用作数据库的底层实现,或者哈希键的底层实现时,Redis使用MurmurHash2
算法来计算键的哈希值。
MurmurHash算法最初由Austin Appleby于2008年发明,这种算法的优点在于,即使
输人的键是有规律的,算法仍能给出一个很好的随机分布性,并且算法的计算速度也非常快。
MurmurHash算法目前的最新版本为MurmurHash3,而Redis使用的是MurmurHash.2。
说到字典,总会涉及到几个问题,比如hash算法的实现,怎么解决hash冲突的,存取的效率如何,扩容机制是怎样的。
hash算法的实现, hash冲突的解决
hash算法是MurmurHash2, 解决hash冲突的方法是链地址法,和Java的HashMap一样, 不过采用的是头插法。
扩容缩容机制
table0 是当前数据存储的表,redis中还有一个table1,就是用来进行扩容和缩容的,
如果执行的是扩展操作,那么table1的大小变为第一个大于等于table0 大小*2的n次方幂;
如果执行的是收缩操作,那么table1的大小变为第一个大于等于table0 大小的2的n次方幂。
也就是说redis的table中桶的数量总是2的n次方幂。
然后再对table0中的所有元素进行rehash,存储到table1上面,之后令table0 = table1,table1新创建一个空白的hash表。
哈希表的扩展与收缩条件
当以下条件中的任意一个被满足时,程序会自动开始对哈希表执行扩展操作:
1)服务器目前没有在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的负
载因子大于等于1.
2)服务器目前正在执行BGSAVE命令或者BGREWRITEAOF命令,并且哈希表的负载
因子大于等于5。
因为这个时候子进程使用写时复制正在进行持久化操作,希望尽可能的不要rehash,不然在rehash的时候会占用更多的内存。
渐进式rehash
为了避免大量键值对的rehash对服务器性能造成影响,服务器不是一次性将table0里面的所有
键值对全部rehash到table1,而是分多次、渐进式地将table0里面的键值对慢慢地rehash
到table1。
线程是否安全
Redis Server本身是一个线程安全的K-V数据库,Redis Server中的指令执行是原子的,也就是说在Redis Server上执行的指令,不需要任何同步机制,不会存在线程安全问题。
Redis的dictht 和 Java(jdk1.8)的HashMap有什么区别
线程安全性
Java不是线程安全的,Redis是。
hash算法
Java:
生成一个随机数作为hashcode,当然可以重写自己的hashcode方法。
java默认的hashcode方法到底得到的是什么?_hb1993的博客-CSDN博客_java 默认hashcode
Redis:
MurmurHash2
解决hash冲突的方法
都是链地址法,但Redis是头插,Java是尾插。
扩容机制
初始容量和扩容机制也不相同,比如负载因子等。