之前项目中曾使用一致性 Hash 路由请求至指定的缓存节点,关于 Dubbo 的一致性 Hash 实现可以参考 Dubbo 一致性Hash负载均衡实现剖析,源码参见 ConsistentHashLoadBalance.java at dubbo-3.0.0。其 hash 值与 Invoker 的映射关系采用 TreeMap 作为底层的数据结构,其根据当前调用查询调用者的源码如下:
1 | private final TreeMap<Long, Invoker<T>> virtualInvokers; |
关键点在于 selectForKey 方法中对 TreeMap 实例的 ceilingEntry 调用及 firstEntry 调用,我们知道 TreeMap 底层实现为红黑树,即自平衡的二叉搜索树。ceilingEntry 方法用于使用计算出的 hash 值查找大于等于 hash 值的节点,跟随 ceilingEntry 方法调用至 TreeMap.java at jdk8-b120:
1 | /** |
1 | 节点示例图一 节点示例图二 |
根据上方 selectForKey 的代码,我们知道,当在 TreeMap 中无法找到大于等于指定 hash 值的节点时,此时我们调用 virtualInvokers.firstEntry() 获取 TreeMap 中的最小节点,firstEntry() 方法将调用至 TreeMap.java at jdk8-b120:
1 | /** |
即一直向左子树寻找,定位至左下角的节点,即二叉搜索树中的最小值,这样就模拟出了一致性 Hash 的环。
References
Fix wrong interpretation by tianshuang · Pull Request #1686 · apache/dubbo-website · GitHub