HBase:为什么在达到 BlockCache 的最大大小之前会有被逐出的块?
HBase: Why are there evicted blocks before the max size of the BlockCache is reached?
我目前使用的是 Apache HBase 的库存配置,其中 RegionServer 堆为 4G,BlockCache 大小为 40%,因此大约为 1.6G。未配置 L2/BucketCache。
这是向 RegionServer 发出约 2K 次请求后的 BlockCache 指标。如您所见,已经有块被逐出,可能导致了一些未命中。
为什么他们在我们甚至没有接近限制时就被驱逐了?
大小 2.1 M 当前使用的块缓存大小(字节)
Free 1.5 G 当前可用于存储更多缓存条目的总空闲内存(字节)
Count 18 块缓存中的块数
Evicted 14 被驱逐的块总数
驱逐 1,645 发生驱逐的总次数
驱逐时块的平均年龄为 10,984(秒)
StdDev 5,853,922 驱逐时区块年龄的标准偏差
命中 1,861 缓存命中的请求数
命中缓存 1,854 缓存命中块请求,但只有在未命中时才将请求设置为缓存块
未命中 58 个缓存未命中但设置为缓存未命中块的块请求
未命中缓存 58 块请求是缓存未命中但只有请求设置为使用块缓存
命中率 96.98% 命中数除以总请求数
您看到的是 LRU 处理具有三个优先级的块的效果:单访问、多访问和内存中。对于默认的 L1 LruBlockCache
class 它们的缓存份额可以设置为(括号中的默认值):
hbase.lru.blockcache.single.percentage
(25%)
hbase.lru.blockcache.multi.percentage
(50%)
hbase.lru.blockcache.memory.percentage
(25%)
对于 4 GB 堆示例,并为缓存预留 40%,您有 1.6 GB 堆,根据以上内容进一步划分为每个优先级的 400 MB、800 MB 和 400 MB百分比。
当一个块从存储中加载时,它通常被标记为单次访问,除非它所属的列族已配置为 IN_MEMORY = true
,将其优先级设置为内存中(很明显)。对于单访问块,如果另一个读取访问正在请求同一块,则将其标记为多访问优先级。
LruBlockCache
有一个内部 逐出线程 每 10 秒运行一次,检查每个级别的块是否超过了允许的百分比。现在,如果您扫描一次更大的 table,并假设缓存完全为空,则所有块都被标记为单次访问。如果 table 的大小为 1 GB,则您已将 1 GB 加载到 400 MB 的缓存中 space,然后逐出线程将在适当的时候减少它。事实上,根据扫描所用的时间,驱逐线程的 10 秒在扫描过程中会失效,一旦超过 25% 阈值就会开始驱逐块。
逐出将首先从单访问区域逐出块,然后是多访问区域,最后,如果堆上仍有压力,则从内存区域。这也是为什么您应该确保内存中标记的列族的工作集不超过配置的缓存区域。
你能做什么?如果你有大部分的单访问块,你可以调整上面的百分比来给 LRU 的单访问区域更多。
我目前使用的是 Apache HBase 的库存配置,其中 RegionServer 堆为 4G,BlockCache 大小为 40%,因此大约为 1.6G。未配置 L2/BucketCache。
这是向 RegionServer 发出约 2K 次请求后的 BlockCache 指标。如您所见,已经有块被逐出,可能导致了一些未命中。
为什么他们在我们甚至没有接近限制时就被驱逐了?
大小 2.1 M 当前使用的块缓存大小(字节)
Free 1.5 G 当前可用于存储更多缓存条目的总空闲内存(字节)
Count 18 块缓存中的块数
Evicted 14 被驱逐的块总数
驱逐 1,645 发生驱逐的总次数
驱逐时块的平均年龄为 10,984(秒)
StdDev 5,853,922 驱逐时区块年龄的标准偏差
命中 1,861 缓存命中的请求数
命中缓存 1,854 缓存命中块请求,但只有在未命中时才将请求设置为缓存块
未命中 58 个缓存未命中但设置为缓存未命中块的块请求
未命中缓存 58 块请求是缓存未命中但只有请求设置为使用块缓存
命中率 96.98% 命中数除以总请求数
您看到的是 LRU 处理具有三个优先级的块的效果:单访问、多访问和内存中。对于默认的 L1 LruBlockCache
class 它们的缓存份额可以设置为(括号中的默认值):
hbase.lru.blockcache.single.percentage
(25%)hbase.lru.blockcache.multi.percentage
(50%)hbase.lru.blockcache.memory.percentage
(25%)
对于 4 GB 堆示例,并为缓存预留 40%,您有 1.6 GB 堆,根据以上内容进一步划分为每个优先级的 400 MB、800 MB 和 400 MB百分比。
当一个块从存储中加载时,它通常被标记为单次访问,除非它所属的列族已配置为 IN_MEMORY = true
,将其优先级设置为内存中(很明显)。对于单访问块,如果另一个读取访问正在请求同一块,则将其标记为多访问优先级。
LruBlockCache
有一个内部 逐出线程 每 10 秒运行一次,检查每个级别的块是否超过了允许的百分比。现在,如果您扫描一次更大的 table,并假设缓存完全为空,则所有块都被标记为单次访问。如果 table 的大小为 1 GB,则您已将 1 GB 加载到 400 MB 的缓存中 space,然后逐出线程将在适当的时候减少它。事实上,根据扫描所用的时间,驱逐线程的 10 秒在扫描过程中会失效,一旦超过 25% 阈值就会开始驱逐块。
逐出将首先从单访问区域逐出块,然后是多访问区域,最后,如果堆上仍有压力,则从内存区域。这也是为什么您应该确保内存中标记的列族的工作集不超过配置的缓存区域。
你能做什么?如果你有大部分的单访问块,你可以调整上面的百分比来给 LRU 的单访问区域更多。