hbase实践之写流程拾遗
keyvalue
KeyValue中包含了丰富的自我描述信息:

KeyValue是支撑”稀疏矩阵”设计的一个关键点:一些Key相同的任意数量的独立KeyValue就可以构成一行数据。但这种设计带来的一个显而易见的缺点:每一个KeyValue所携带的自我描述信息,会带来显著的数据膨胀。
为什么rowkey不能太长?columnfamily、qualifiter尽量短?
行级事务模型
写写并发控制
包括单行、批量多行。
- 单行:行锁
- 多行:两阶段锁协议,即:
(1) 获取所有待写入(更新)行记录的行锁
(2) 开始执行写入(更新)操作
(3) 写入完成之后再统一释放所有行记录的行锁
读写并发控制:MVCC
Mutil Version Concurrent Control。HBase中MVCC机制实现主要分为两步:
(1) 为每一个写(更新)事务分配一个Region级别自增的序列号
(2) 为每一个读请求分配一个已完成的最大写事务序列号
MVCC的精髓是写入的时候分配递增版本信息(SequenceId),读取的时候分配唯一的版本用于读取可见,比之大的版本不可见。这里需要注意版本必须递增,而且版本递增的范围一定程度上决定了事务是什么事务,比如HBase是Region级别的递增版本,那么事务就是region级别事务。
非必须情况,不要使用行锁。
sequenceId
为什么要有sequenceId?
- 先写HLog,再写memstore,两个地方的数据是一致的,两者如何一一对应?一一对应后,日志可删除(因为只能保留有限日志)。
- HLog日志如何删除?HLog只能保存一定数量的日志,如果删除日志文件,先删除谁? 先删除年龄最老的日志文件,则其sequenceId最小。如果这些数据没有落盘,就可以强制对其执行flush,之后就可以将HLog删除。
- RegionServer宕机,memsotre中数据丢失,数据从哪里开始恢复?
本质问题:mestore、Hlog中的数据是同一份,他们需要同一个标识。
- 读写并发控制
- HLog文件的基本结构

<logseq#-for-entire-txn>:<-1, 3, , , >
The -1 marker is just a special way of being backward compatible with an old HLog which would have contained a single . -1只是一个标志, 是为了对旧版本兼容.
问题一:HLog在什么时候可以过期回收?HLog在什么时候可以过期回收?
RegionServer会为每个Region维护了一个变量oldestUnflushedSequenceId(实际上是为每个Store,为了方便讲解,此处暂且认为是Region,不影响原理),表示这个Region最早的还未落盘的seqid ,即这个seqid之前的所有数据都已经落盘。
下图是flush过程中oldestUnflushedSequenceId变量变化的示意图,初始时为null,假设在某一时刻阶段二RegionA(红色方框)要执行flush,中间HLog中sequenceId为1~4对应的数据将会落盘,在执行flush之前,HBase会append一个空的Entry到HLog,仅为获取下一个sequenceId(5),并将这个sequenceId赋给OldestUnflushedSequenceId-RegionA。如图中第三阶段OldestUnflushedSequenceId-RegionA指向sequenceId为5的Entry。


场景一中右侧HLog还有未落盘的数据(sequenceid=5还未落盘),因此不能删除;而场景二中右侧HLog的所有数据都已经落盘,所以这个HLog理论上就已经可以被删除回收。
问题二:HLog数量超过阈值(maxlogs)之后删除最早HLog,应该强制刷新哪些Region?

HLog日志文件超过阈值,会删除最老的,根据OldestUnflushedSequenceId,如果该日志中有数据未写磁盘,则强制刷写磁盘,然后将该日志文件删除。
问题三:RegionServer宕机恢复replay日志时哪些WALEntry需要被回放,哪些会被skip?
理论上来说只需要回放Memstore中没有落地的数据对应的WALEntry,已经落地数据对应的WALEntry可以skip。可问题是RegionServer已经宕机了,<region, oldestUnflushedSequenceId> 对应信息肯定没有了,如何是好?想办法持久化呗,上文分析oldestUnflushedSequenceId变量是flush时产生的一个变量,这个变量完全可以以flush的时候以元数据的形式写到HFile中(代码见下图):

到目前为止,上面所有分析都基于一个事实:hbase中flush操作是region级别操作,即每次执行flush都需要整个region中的所有store全都执行flush。
Per-CF Flush
map<region, map<store, oldestUnflushedSequenceId>>
RS宕机与恢复


由HMaster来管理并切分日志==>RegionServer切分日志(小文件多)==>RegionServer切分日志后,直接在Region-Buffer中回放。
Region 切分
Region切分触发策略
- ConstantSizeRegionSplitPolicy
- IncreasingToUpperBoundRegionSplitPolicy:(#regions) * (#regions) * (#regions) * flush size * 2
在大集群条件下对于很多大表来说表现很优秀,但并不完美,这种策略下很多小表会在大集群中产生大量小region,分散在整个集群中。而且在发生region迁移时也可能会触发region分裂。
- SteppingSplitPolicy:如果region个数等于1,切分阈值为flush size * 2,否则为MaxRegionFileSize。
切分本质

虽然产生2个子Region,但还是指向原来的HFile文件。只有major compaction时,父region的数据才会迁移到子region目录。
参考文献
hbase实践之写流程拾遗的更多相关文章
- hbase实践之写流程
内容提要 一.写入流程 初始化ZooKeeper Session,建立长连接,获取META Region的地址. 获取rowkey对应的Region路由信息:来自.meta. 写入region 如何快 ...
- hbase实践之flush and compaction
本文主要涉及flush流程,探讨flush流程过程中引入的问题并阐述2种解决策略,最后简要说明Flush执行策略. 对于Compaction,本文主要探讨Compaction要解决的本质问题以及由Co ...
- Raid1源代码分析--写流程
正确写流程的总体步骤是,raid1接收上层的写bio,申请一个r1_bio结构,将其中的所有bios[]指向该bio.假设盘阵中有N块盘.然后克隆N份上层的bio结构,并分别将每个bios[]指向克隆 ...
- 如何使用 CODING 实践 DevOps 全流程
你好,欢迎使用 CODING!这份最佳实践将帮助你通过 CODING 研发管理系统来更好地实践 DevOps 流程. DevOps 的本质是打破各个部门之间的隔阂,打通企业的前中后台,推进跨部门协作. ...
- HDFS写流程
HDFS client首先会与NameNode交互元数据信息,然后NameNode制定策略,分配NameNode节点,客户端先会与离自己最近的DataNode进行socket连接,已经与DataNod ...
- HBase最佳实践-写性能优化策略
本篇文章来说道说道如何诊断HBase写数据的异常问题以及优化写性能.和读相比,HBase写数据流程倒是显得很简单:数据先顺序写入HLog,再写入对应的缓存Memstore,当Memstore中数据大小 ...
- HBase实践案例:知乎 AI 用户模型服务性能优化实践
用户模型简介 知乎 AI 用户模型服务于知乎两亿多用户,主要为首页.推荐.广告.知识服务.想法.关注页等业务场景提供数据和服务, 例如首页个性化 Feed 的召回和排序.相关回答等用到的用户长期兴趣特 ...
- hbase实践之协处理器Coprocessor
HBase客户端查询存在的问题 Scan 用Get/Scan查询数据, Filter 用Filter查询特定数据 以上情况只适合几千行数据以及不是很多的列的"小数据". 当表扩展为 ...
- hbase实践(十六) BlockCache
0 引言 和其他数据库一样,优化IO也是HBase提升性能的不二法宝,而提供缓存更是优化的重中之重. 根据二八法则,80%的业务请求都集中在20%的热点数据上,因此将这部分数据缓存起就可以极大地提升系 ...
随机推荐
- docker下部署服务
一.zabbix部署 需求: 因最近项目过多,人力监控耗费时间,打算部署一个zabbix,但又不想部署在宿主机上,就想起了docker,docker快速的移植性是最大的亮点,好了,言归正传开始干. 部 ...
- 第一坑:class编译版本
这个坑是刚去公司的时候,公司项目运行环境的jdk版本是1.5,当时我编译版本是1.7,然后放上去一直报找不到class的错误,我硬是找了半天,后来才听说要用1.5版本编译.
- 整合thymeleaf
1.导入thymeleaf依赖 2.controller类 (1)模板 导入命名空间,xmlns:th="http://www.thymeleaf.org" (2)ModelAnd ...
- Python 中集合使用
集合在使用中由于自动虑重,而且效率特高,故在提取数据时用上,但是由于集合没有切片功能没有取第几个元素的功能,但是一直使用集合切片不报错,但是执行不下去,导致一直存在问题. 修改为list后正常 例如: ...
- Windows 下redis的安装和使用
1.下载 Window 下载地址:https://github.com/MSOpenTech/redis/releases 查找版本对应的一个MSI或者zip文件下载 2.安装 MSI文件需要安装 z ...
- TZOJ2882: 美食节之感恩父母
#include<stdio.h> int main() { ],b[],i,j,max,m,t1,t2,t3; while(scanf("%d",&m),m) ...
- Python中下划线的5种含义
目录 单前导下划线 _var 当涉及到变量和方法名称时,单个下划线前缀有一个约定俗成的含义. 它是对程序员的一个提示 - 意味着Python社区一致认为它应该是什么意思,但程序的行为不受影响. 单末尾 ...
- 创建新表,自动授权trigger
需求 一个用户下三个表,开发人员不定时进行rename表名称,create原表名称 as old_table 插入少量数据,另一个业务用户需要访问该表,由于表名称rename导致经常需要手工授权. 需 ...
- sit、qas、dev、pet
SIT: System Integrate Test 系统整合测试 QAS: Quality Assurance system 质量保证 DEV: Development 开发 PET: Perfor ...
- (六)Redis之数据结构之Set
一.常用方法 和List类型不同的是,Set集合中不允许出现重复的元素 添加/删除元素 获取集合中的元素 集合中的差集运算 集合中的交集运算 集合中的并集元算 扩展命令 1和2 添加/删除元素和获取集 ...