从缓存中查找到RegionLocations 的位置

本文介绍ConcurrentSkipListMap数据结构及其在高并发场景下的应用,特别是其在缓存查找中的优势,包括如何高效查找小于或等于目标值的最大记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

public RegionLocations getCachedLocation(final TableName tableName, final byte [] row) {

//根据tablename从缓存中查找

    ConcurrentSkipListMap<byte[], RegionLocations> tableLocations =
      getTableLocations(tableName);

// 从tableLocations中根据row获取到小于或等于row的最大row到RegionLocations映射的条目  
    Entry<byte[], RegionLocations> e = tableLocations.floorEntry(row);
    if (e == null) {
      return null;

    }

//获取到它的值

    RegionLocations possibleRegion = e.getValue();


    // make sure that the end key is greater than the row we're looking
    // for, otherwise the row actually belongs in the next region, not
    // this one. the exception case is when the endkey is
    // HConstants.EMPTY_END_ROW, signifying that the region we're

    // checking is actually the last region in the table.

//确信endkey比我们要查找到的row要大,否则row实际上属于下一个region,并不是这个的。还有一个意外情况就是当endkey值为byte [0]

//说明我们检查的region实际上是表中的最后一个region

    byte[] endKey = possibleRegion.getRegionLocation().getRegionInfo().getEndKey();
    if (Bytes.equals(endKey, HConstants.EMPTY_END_ROW) ||
        getRowComparator(tableName).compareRows(
            endKey, 0, endKey.length, row, 0, row.length) > 0) {
      return possibleRegion;
    }


    // Passed all the way through, so we got nothing - complete cache miss没有找到,返回null
    return null;

  }


首先介绍一下ConcurrentSkipListMap是线程安全的有序的哈希表,适用于高并发的场景。

ConcurrentSkipListMap和TreeMap,它们虽然都是有序的哈希表。但是,第一,它们的线程安全机制不同,TreeMap是非线程安全的,而ConcurrentSkipListMap是线程安全的。第二,ConcurrentSkipListMap是通过跳表实现的,而TreeMap是通过红黑树实现的。
关于跳表(Skip List),它是平衡树的一种替代的数据结构,但是和红黑树不相同的是,跳表对于树的平衡的实现是基于一种随机化的算法的,这样也就是说跳表的插入和删除的工作是比较简单的。

说明

先以数据“7,14,21,32,37,71,85”序列为例,来对跳表进行简单说明。

跳表分为许多层(level),每一层都可以看作是数据的索引,这些索引的意义就是加快跳表查找数据速度。每一层的数据都是有序的,上一层数据是下一层数据的子集,并且第一层(level 1)包含了全部的数据;层次越高,跳跃性越大,包含的数据越少。
跳表包含一个表头,它查找数据时,是从上往下,从左往右进行查找。现在“需要找出值为32的节点”为例,来对比说明跳表和普遍的链表。

情况1:链表中查找“32”节点
路径如下图1-02所示:

需要4步(红色部分表示路径)。

 

情况2:跳表中查找“32”节点
路径如下图1-03所示:

忽略索引垂直线路上路径的情况下,只需要2步(红色部分表示路径)。


下面说说Java中ConcurrentSkipListMap的数据结构。
(01) ConcurrentSkipListMap继承于AbstractMap类,也就意味着它是一个哈希表。
(02) Index是ConcurrentSkipListMap的内部类,它与“跳表中的索引相对应”。HeadIndex继承于Index,ConcurrentSkipListMap中含有一个HeadIndex的对象head,head是“跳表的表头”。
(03) Index是跳表中的索引,它包含“右索引的指针(right)”,“下索引的指针(down)”和“哈希表节点node”。node是Node的对象,Node也是ConcurrentSkipListMap中的内部类。


记得之前讨论过这个问题,那个时候认为缓存是针对某个值做的缓存,这个地方的巧妙之处是用了 ConcurrentSkipListMap,它可以提高性能,还有在查找的时候并不是完全匹配的,而是根据region的实际情况查找小于或者等于的最大row
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值