HBase 的 MemStore 详解

一、MemStore 概述

        MemStore 是 HBase 的内存存储区域,它是一个负责缓存数据写入操作的组件。每当有写操作(如 Put 或 Delete)发生时,数据会首先被写入到 MemStore 中,而不是直接写入磁盘。MemStore 类似于数据库中的缓冲区,主要用于提升写操作的性能。当 MemStore 达到一定的容量时,数据会被刷新(flush)到磁盘上,形成 HFile 文件存储在 HDFS 中。

二、MemStore 的工作原理

        HBase 中每个 RegionServer 负责管理多个表的 Region,每个 Region 包含多个列族 (Column Family)。每个列族都拥有自己的 MemStore,这意味着一个 Region 中的每个列族都有一个独立的 MemStore 用于缓存数据写入操作。

        MemStore 的主要功能是缓存数据,以便快速响应写入操作,并在合适的时机将数据刷写到 HDFS 上的 HFile 中。

工作流程:

  1. 数据写入:当客户端执行 Put 操作时,数据会首先写入到 WAL(Write-Ahead Log)中,以确保数据的持久性,之后才写入 MemStore。
  2. 数据缓存:数据在 MemStore 中缓存,多个写操作会先在 MemStore 中进行合并,以减少频繁的磁盘 I/O。
  3. 数据刷写 (Flush):当 MemStore 的数据量达到配置的阈值(通常默认是 128MB)时,MemStore 的数据会被刷写到磁盘,形成新的 HFile。此时,MemStore 会被清空,新的数据将被写入到一个新的 MemStore 中。
  4. Compaction:刷写到磁盘的 HFile 文件在一定时间或条件下会进行合并(称为 Minor 和 Major Compaction),以减少小文件的数量并优化查询性能。

三、MemStore 的结构

        MemStore 实际上是一个多版本并发控制(MVCC)存储系统,它以一种顺序有序的方式存储数据。底层实现上,MemStore 采用的是 ConcurrentSkipListMap 数据结构,这是一种线程安全的跳表结构,具有良好的并发性能和有序性。

MemStore 的关键数据结构:

  1. ConcurrentSkipListMap:跳表是 MemStore 的核心数据结构,所有的写操作(Put 和 Delete)都会被缓存到一个跳表中。跳表是一种基于有序链表的索引结构,具有 O(log n) 的时间复杂度,可以快速查找、插入和删除元素。

  2. KeyValue:MemStore 中存储的每条数据都是一个 KeyValue 对象,KeyValue 包含了 RowKey、列族、列、时间戳和值等信息。通过这种方式,HBase 可以支持多版本数据(MVCC)。

  3. Snapshot:当 MemStore 需要刷写到磁盘时,会创建一个 MemStore 的快照 (Snapshot),这样在进行刷写时,新的写操作仍然可以写入到新的 MemStore 中,而不会阻塞写入操作。快照存储在内存中,直到数据被完全刷写到 HFile 中。

MemStore 中数据版本管理:

        HBase 使用了多版本并发控制 (MVCC) 来确保数据一致性,MemStore 通过存储多个版本的数据来支持数据的历史查询。每个 KeyValue 对象都有一个时间戳,HBase 可以根据这个时间戳来区分不同版本的同一条数据,并且在读取时可以根据查询的时间范围返回指定版本的数据。

public class MemStore {
    // 存储数据的核心结构
    private final ConcurrentSkipListMap<KeyValue, KeyValue> kvset;
    
    // MemStore 快照
    private volatile ConcurrentSkipListMap<KeyValue, KeyValue> snapshot;
    
    public void add(KeyValue kv) {
        // 将数据插入到 SkipList 中
        kvset.put(kv, kv);
    }
    
    public void snapshot() {
        // 创建 MemStore 的快照,之后会进行刷写操作
        this.snapshot = kvset;
        // 清空当前的 MemStore,准备接受新的写入
        kvset = new ConcurrentSkipListMap<>();
    }
    
    public void flush() {
        // 将 snapshot 中的数据刷写到 HFile
        for (Map.Entry<KeyValue, KeyValue> entry : snapshot.entrySet()) {
            // 写入 HFile
        }
        // 刷写完成后,清空 snapshot
        snapshot.clear();
    }
}

四、MemStore 刷写策略

MemStore 不会一直保持数据在内存中,通常会在以下几种情况下触发刷写操作:

  1. MemStore 达到阈值:当 MemStore 中的数据量达到一定阈值时(如 128MB),MemStore 的数据会被刷写到磁盘。

  2. RegionServer 内存压力:当 RegionServer 的整体内存使用量接近系统允许的上限时,HBase 会主动触发 MemStore 的刷写,以释放内存。

  3. 手动触发:在某些运维场景下,管理员可以通过命令手动触发 MemStore 刷写操作。

刷写过程:

刷写时,MemStore 中的所有数据会被转换成 HFile 格式,并存储在 HDFS 上的磁盘中。刷写过程包括以下步骤:

  1. 创建快照:首先,MemStore 会创建一个快照来冻结当前的状态,以便在刷写期间仍然可以处理新的写请求。
  2. 数据排序:将快照中的数据按照 RowKey 进行排序。
  3. 写入 HFile:排序后的数据会写入到新的 HFile 中,并保存到 HDFS。
  4. 更新元数据:刷写完成后,更新元数据以使新的 HFile 生效,并清空 MemStore 快照。
public void flushSnapshot() {
    // 将 snapshot 中的数据刷写到 HFile
    HFile.Writer writer = ...; // HFile 写入器
    for (Map.Entry<KeyValue, KeyValue> entry : snapshot.entrySet()) {
        writer.append(entry.getKey(), entry.getValue());
    }
    writer.close(); // 完成 HFile 写入
    snapshot.clear(); // 清空 snapshot
}

刷写触发的配置项

  • hbase.hregion.memstore.flush.size:MemStore 的最大容量,当 MemStore 达到这个阈值时会触发刷写。默认值为 128MB。
hbase.hregion.memstore.flush.size=128MB

  • hbase.regionserver.global.memstore.size:RegionServer 中所有 MemStore 的总内存占用比例。当内存使用超过这个比例时,HBase 会选择最老的 MemStore 进行刷写,释放内存。默认值为 40%。
hbase.regionserver.global.memstore.size=0.4

五、MemStore 和 WAL 的关系

        每次写入 HBase 时,数据首先会写入 WAL(Write-Ahead Log),然后写入 MemStore。WAL 是一种日志机制,确保在系统崩溃时能够通过 WAL 进行数据恢复。当 RegionServer 崩溃或宕机时,HBase 可以通过 WAL 恢复 MemStore 中未刷写到磁盘的数据。因此,WAL 的存在保证了数据的可靠性。

  • WAL 和 MemStore 的同步:每次写入时,数据会首先写入 WAL 并刷盘,确保数据不会丢失,然后才会写入 MemStore。MemStore 中的数据在达到阈值时才会刷写到 HFile,而 WAL 则会在每次写操作时进行日志写入。

六、MemStore 的优化配置

MemStore 的合理配置和调优是提升 HBase 性能的重要手段之一。以下是常见的优化策略:

    1. 调整 MemStore 大小:增加 MemStore 的大小可以减少刷写的频率,从而减少磁盘 I/O。但过大的 MemStore 会占用大量内存,影响系统的整体内存使用效率。

hbase.hregion.memstore.flush.size=256MB # 增大每个列族的 MemStore 大小

    2. MemStore 压缩:HBase 支持在内存中对 MemStore 数据进行压缩,减少内存占用。可以通过 hbase.hregion.memstore.inmemory.compaction 参数来启用。

hbase.hregion.memstore.inmemory.compaction=true

    3. 调整 RegionServer 内存使用比例:根据系统内存大小和业务需求,调整 hbase.regionserver.global.memstore.size 和 hfile.block.cache.size 参数的值,合理分配 MemStore 和 BlockCache 的内存使用比例。

# 将 MemStore 总内存占用比例调整为 50% 
hbase.regionserver.global.memstore.size=0.5

七、MemStore 和 HBase 性能的关系

MemStore 的性能和配置直接影响 HBase 的整体写性能。以下是 MemStore 对性能的影响:

  1. 写性能:MemStore 的存在大大提升了写操作的性能,因为写入数据首先被缓存到内存中,减少了频繁的磁盘 I/O。
  2. 刷写性能:MemStore 的刷写操作会对系统性能产生一定的影响,特别是在高写入负载时,频繁的刷写会导致较多的磁盘操作,进而影响整体性能。
  3. 内存占用:MemStore 占用了系统的大部分内存资源,合理配置 MemStore 大小和刷写策略,可以平衡写性能和内存使用效率。

八、总结

        HBase 中的 MemStore 是一个核心的缓存机制,它通过缓存写操作来提升写性能,并在合适的时机将数据刷写到磁盘。在实现上,MemStore 使用了 ConcurrentSkipListMap 数据结构,保证了数据的有序性和高效的并发操作。通过合理配置 MemStore 的大小和刷写策略,可以在 HBase 中实现高效的写入和查询性能。在实际应用中,针对不同的业务场景和负载需求,需要对 MemStore 进行调优,以最大化系统性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/886645.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

被字节恶心到了

字节 日常逛 xhs 看到一篇吐槽贴&#xff0c;表示被公司恶心到了&#xff1a; 这位网友表示&#xff0c;最近是公司举办了 Q2 和 H1 的优秀员工表彰&#xff0c;自己的 1&#xff08;直属领导&#xff09;评上了&#xff0c;但仔细一看&#xff0c;1 获奖的所有产出都是自己的&…

Stable Diffusion绘画 | 插件-Deforum:动态视频生成(上篇)

Deforum 与 AnimateDiff 不太一样&#xff0c; AnimateDiff 是生成丝滑变化视频的&#xff0c;而 Deforum 的丝滑程度远远没有 AnimateDiff 好。 它是根据对比前面一帧的画面&#xff0c;然后不断生成新的相似图片&#xff0c;来组合成一个完整的视频。 Deforum 的优点在于可…

CSS实现磨砂玻璃效果

引言 最近看到有一种磨砂玻璃背景效果很好看&#xff0c;自己简单制作了一个美杜莎女王小卡片&#xff0c;效果如下&#xff1a; backdrop-filter: blur(10px); 通过设置背景幕布的模糊程度&#xff0c;结合背景图片&#xff0c;实现磨砂玻璃效果 案例代码 <!DOCTYPE h…

Linux之实战命令25:xargs应用实例(五十九)

简介&#xff1a; CSDN博客专家、《Android系统多媒体进阶实战》一书作者 新书发布&#xff1a;《Android系统多媒体进阶实战》&#x1f680; 优质专栏&#xff1a; Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a; 多媒体系统工程师系列【…

风格迁移项目一:如何使用

前言 由于我不太会pr&#xff0c;所以直接新建的项目&#xff0c; 原项目地址&#xff1a;https://github.com/Optimistism/Style-transfer 原项目代码的讲解地址&#xff1a;https://www.bilibili.com/video/BV1yY4y1c7Cz/ 本项目是对原项目的一点点完善。 项目地址&…

6.模拟电子技术——共集电极,共基极,多极放大电路

写在前面 这个是第六次的笔记&#xff0c;祝大家学习愉快 笔记部分 1.共集电极放大电路 首先&#xff0c;我们再复习一遍组态判断&#xff1a;基极进&#xff0c;发射极出&#xff0c;说明是共集电极放大电路。可能读者已经知道一些结论&#xff0c;先抛开这些&#xff0c;我…

Qt/C++开源控件 自定义雷达控件

使用Qt框架创建一个简单的雷达图&#xff0c;包含动态扫描、目标点生成、刻度和方向标识。代码实现使用C编写&#xff0c;适合用作学习和扩展的基础。 1. 头文件与基本设置 #include "RadarWidget.h" #include <QPainter> #include <QPen> #include &…

CMU 10423 Generative AI:lec15(Scaling Laws 大规模语言模型的扩展法则)

文章目录 一 概述1. **扩展规律的背景**2. **两种主要的扩展规律**3. **模型容量扩展规律**4. **信息论下界**5. **计算扩展规律**6. **训练高效性**7. **结论与启示** 二 2bit/parameter 概念&#xff08;模型的存储能力分析&#xff09;**1. 概念解释****2. 图表解读****3. 量…

匿名方法与Lambda表达式+泛型委托

匿名方法 和委托搭配使用&#xff0c;方便我们快速对委托进行传参&#xff0c;不需要我们定义一个新的函数&#xff0c;直接用delegate关键字代替方法名&#xff0c;后面跟上参数列表与方法体。 格式&#xff1a;delegate(参数列表){方法体} lambda表达式 是匿名方法的升级…

通信工程学习:什么是IP网际协议

IP&#xff1a;网际协议 IP网际协议&#xff08;Internet Protocol&#xff0c;简称IP&#xff09;是整个TCP/IP协议栈中的核心协议之一&#xff0c;它负责在网络中传送数据包&#xff0c;并提供寻址和路由功能。以下是对IP网际协议的详细解释&#xff1a; 一、对IP网际协议的…

Flask-3

文章目录 ORMFlask-SQLAlchemySQLAlchemy中的session对象数据库连接设置常用的SQLAlchemy字段类型常用的SQLAlchemy列约束选项 数据库基本操作模型类定义 数据表操作创建和删除表 数据操作基本查询SQLAlchemy常用的查询过滤器SQLAlchemy常用的查询结果方法多条件查询分页器聚合…

全局安装cnpm并设置其使用淘宝镜像的仓库地址(地址最新版)

npm、cnpm和pnpm基本概念 首先介绍一下npm和cnpm是什么&#xff0c;顺便说一下pnpm。 npm npm&#xff08;Node Package Manager&#xff09;是Node.js的默认包管理器&#xff0c;用于安装、管理和分享JavaScript代码包。它是全球最大的开源库生态系统之一&#xff0c;提供了数…

共享单车轨迹数据分析:以厦门市共享单车数据为例(八)

副标题&#xff1a;基于POI数据的站点综合评价——以厦门市为例&#xff08;三&#xff09; 什么是优劣解距离法&#xff08;TOPSIS&#xff09;&#xff1f; 优劣解距离法&#xff08;Technique for Order Preference by Similarity to Ideal Solution&#xff0c;简称TOPSI…

排序算法之——归并排序,计数排序

文章目录 前言一、归并排序1. 归并排序的思想2. 归并排序时间复杂度及空间复杂度3. 归并排序代码实现1&#xff09;递归版本2&#xff09;非递归版本 二、计数排序1. 计数排序的思想2. 计数排序的时间复杂度及空间复杂度3. 计数排序代码实现 总结&#xff08;排序算法稳定性&am…

ATLAS/ICESat-2 L3B 每 3 个月网格动态海洋地形图 V001

目录 简介 摘要 代码 引用 网址推荐 0代码在线构建地图应用 机器学习 ATLAS/ICESat-2 L3B Monthly 3-Month Gridded Dynamic Ocean Topography V001 ATLAS/ICESat-2 L3B 每月 3 个月网格动态海洋地形图 V001 简介 该数据集包含中纬度、北极和南极网格上动态海洋地形&…

基于大数据的Python+Django电影票房数据可视化分析系统设计与实现

目录 1 引言 2 系统需求分析 3 技术选型 4 系统架构设计 5 关键技术实现 6 系统实现 7 总结与展望 1 引言 随着数字媒体技术的发展&#xff0c;电影产业已经成为全球经济文化不可或缺的一部分。电影不仅是艺术表达的形式&#xff0c;更是大众娱乐的重要来源。在这个背景…

C++之多线程

前言 多线程和多进程是并发编程的两个核心概念,它们在现代计算中都非常重要,尤其是在需要处理大量数据、提高程序性能和响应能力的场景中。 多线程的重要性: 资源利用率:多线程可以在单个进程中同时执行多个任务,这可以更有效地利用CPU资源,特别是在多核处理器上。 性…

【Spring基础3】- Spring的入门程序

目录 3-1 Spring的下载3-2 Spring的 jar 包3-3 第一个 Spring程序第一步&#xff1a;添加spring context的依赖&#xff0c;pom.xml配置如下第二步&#xff1a;添加junit依赖第三步&#xff1a;定义bean&#xff1a;User第四步&#xff1a;编写spring的配置文件&#xff1a;bea…

macOS终端配置自动补全功能

如何在macOS终端中配置自动补全功能 终端是一个非常强大的工具&#xff0c;它可以用来完成很多任务&#xff0c;比如创建、复制、移动、删除文件&#xff0c;执行脚本和运行程序。不过它的默认设置对用户不太友好&#xff0c;作为开发者&#xff0c;我们通常习惯代码编辑器的辅…

docker pull 超时Timeout失败的解决办法

当国内开发者docker pull遇到如下提示时&#xff0c;不要惊讶 [rootvm /]# docker pull postgres Using default tag: latest Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp 128.121.146.235:443: i/o timeout [rootvm /]# 自2024…