hba创建表如何包含两个列族_HBa内部探险
本⽂内容略长,看的时候需要⼀些耐⼼。⽂章⾸先回顾了 HBa 的数据模型和数据层级结构,对数据的每个层级的作⽤和构架均进⾏了详细阐述;随后介绍了数据写⼊和读取的详细流程;最后介绍了⽼版本到新版本 Region 查找的演进。
⼀、数据模型
1、重要概念回顾
Namespace(表命名空间):将多个表分到⼀个组进⾏统⼀管理。
Table(表):⼀个表由⼀个或者多个列族组成;数据属性⽐如:超时时间(TTL),压缩算法(COMPRESSION)等,都在列族的定义中定义;定义完列族后表是空的,只有添加了⾏,表才有数据。
Row(⾏):⼀个⾏包含了多个列,这些列通过列族来分类;⾏中的数据所属列族只能从该表所定义的列族中选取;由于 HBa 是⼀个列式数据库,所以⼀个⾏中的数据可以分布在不同的服务器上。
Column Family(列族):列族是多个列的集合,HBa 会尽量把同⼀个列族的列放到同⼀个服务器上,这样可以提⾼存取性能,并且可以批量管理有关联的⼀堆列;所有的数据属性都是定义在列族上;在 HBa 中,建表定义的不是列,⽽是列族。
Column Qualifier(列):多个列组成⼀个⾏,列族和列经常⽤ Column Family: Column Qualifier 来⼀起表⽰,列是可以随意定义的,⼀个⾏中的列不限名字、不限数量。
Cell(单元格):⼀个列中可以存储多个版本的数据,⽽每个版本就称为⼀个单元格(Cell),所以在 HBa 中的单元格跟传统关系型数据库的单元格概念不⼀样;HBa 中的数据细粒度⽐传统数据结构更细⼀级,同⼀个位置的数据还细分成多个版本。
Timestamp(时间戳/版本号):既可以把它称为是时间戳,也可以称为是版本号,因为它是⽤来标定同⼀个列中多个单元格的版本号的。不指定版本号的时候,系统会⾃动采⽤当前的时间戳来作为版本号;当⼿动定义了⼀个数字来当作版本号的时候,这个
Timestamp 就真的是只有版本号的意义了。
美国 大学 排名2、⼏个⼩问题
HBa是否⽀持表关联?
官⽅给出的答案是⼲脆的,那就是“不⽀持”。如果想实现数据之间的关联,就必须⾃⼰去实现了,这是挑选 NoSQL 数据库必须付出的代价。
HBa 是否⽀持 ACID?
ACID 就是 Atomicity(原⼦性)、Consistency(⼀致性)、Isolation(隔离性)、Durability(持久性)的⾸字母缩写,ACID 是事务正确执⾏的保证,HBa 部分⽀持 了 ACID。
表命名空间有什么⽤?
表命名空间主要是⽤来对表分组,那么对表分组有什么⽤?命名空间可以填补 HBa ⽆法在⼀个实例上分库的缺憾,通过命名空间我们可以像关系型数据库⼀样将表分组,对于不同的组进⾏不同的环境设定,⽐如配额管理、安全管理等。
HBa 中有两个保留表空间是预先定义好的:
一先令
hba:系统表空间,⽤于组织 HBa 内部表;
default:那些没有定义表空间的表都被⾃动分配到这个表空间下。
⼆、HBa 的存储数据⽅式
1、架构回顾
⼀个 HBa 集群由⼀个 Master(也可以把两个 Master 做成 HighAvailable)和多个 RegionServer 组成。
Master:负责启动的时候分配 Region 到具体的 RegionServer,执⾏各种管理操作,⽐如 Region 的分割和合并。HBa 中的Master 的⾓⾊功能⽐其他类型集群弱很多,HBa 的 Master 很特别,因为数据的读取和写⼊都跟它没什么关系,它挂了业务系统照样运⾏。当然 Master 也不能宕机太久,有很多必要的操作,⽐如创建表、修改列族配置,以及更重要的分割和合并都需要它的操作。
RegionServer:RegionServer 上有⼀个或者多个 Region,我们读写的数据就存储在 Region 上。如果你的 HBa 是基于 HDFS 的(单机 HBa 可基于本地磁盘),那么 Region 所有数据存取操作都是调⽤了 HDFS 的客户端接⼝来实现的。
Region:表的⼀部分数据,HBa 是⼀个会⾃动分⽚的数据库,⼀个 Region 就相当于关系型数据库中分区表的⼀个分区,或者MongoDB 的⼀个分⽚。
HDFS:HBa 并不直接跟服务器的硬盘交互,⽽是跟 HDFS 交互,所以 HDFS 是真正承载数据的载体。
ZooKeeper:ZooKeeper 在 HBa 中的⽐ Master 更重要,把 Master 关掉业务系统照样跑,能读能写;但是把 ZooKeeper 关掉,就不能读取数据了,因为读取数据所需要的元数据表 hba:meata 的位置存储在 ZooKeeper 上。
HBa 的宏观架构
nameplate2、RegionServer 内部架构
⼀个 RegionServer 包含有:
⼀个 WAL:预写⽇志,WAL 是 Write-Ahead Log 的缩写,就是:预先写⼊。当操作到达 Region 的时候,HBa 先把操作写到WAL ⾥⾯去,HBa 会把数据放到基于内存实现的 Memstore ⾥,等数据达到⼀定的数量时才刷写(flush)到最终存储的 HFile 内,⽽如果在这个过程中服务器宕机或者断电了,那么数据就丢失了。WAL 是⼀个保险机制,数据在写到 Memstore 之前,先被写到WAL 了,这样当故障恢复的时候依旧可以从 WAL 中恢复数据。
多个 Region:Region 相当于⼀个数据分⽚,每⼀个 Region 都有起始 rowkey 和结束 rowkey,代表了它所存储的 row 范围。
RegionServer 内部架构
3、Region 内部架构
每⼀个 Region 内都包含有多个 Store 实例,⼀个 Store 对应⼀个列族的数据,如果⼀个表有两个列族,那么在⼀个 Region ⾥⾯就有两个 Store,Store 内部有 MemStore 和 HFile 这两个组成部分。
Region 内部架构
4、预写⽇志(WAL)
预写⽇志(Write-ahead log,WAL)就是设计来解决宕机之后的操作恢复问题的,数据到达 Region 的
岩椒
时候是先写⼊ WAL,然后再被加载到 Memstore,就算 Region 的机器宕掉了,由于 WAL 的数据是存储在 HDFS 上的,所以数据并不会丢失。
homework什么意思WAL 是默认开启的,可以通过下⾯的代码关闭 WAL。
Mutation.tDurability(Durability.SKIP_WAL);
Put、Append、Increment、Delete 都是 Mutation 的⼦类,所以他们都有 tDurability ⽅法,这样可以让该数据操作快⼀点,但是最好不要这样做,因为当服务器宕机时,数据就会丢失。
如果你实在想不惜通过关闭 WAL 来提⾼性能,可以选择异步写⼊ WAL。
Mutation.tDurability(Durability.ASYNC WAL);
这样设定后 Region 会等到条件满⾜的时候才把操作写⼊ WAL,这⾥提到的条件主要指的是时间间
隔 ionrver.optionallogflushinterval,这个时间间隔的意思是 HBa 间隔多久会把操作从内存写⼊ WAL,默认值是 1s。
如果你的系统对性能要求极⾼、对数据⼀致性要求不⾼,并且系统的性能瓶颈出现在 WAL 上的时候,你可以考虑使⽤异步写⼊WAL,否则,使⽤默认的配置即可。
剑桥英语培训
5、WAL 滚动
WAL 是⼀个环状的滚动⽇志结构,因为这种结构写⼊效果最⾼,⽽且可以保证空间不会持续变⼤。
WAL 的检查间隔由 ionrver.logroll.period 定义,默认值为 1h。检查的内容是把当前 WAL 中的操作跟实际持久化到 HDFS 上的操作⽐较,看哪些操作已经被持久化了,被持久化的操作就会被移动到 .oldlogs ⽂件夹内(这个⽂件夹也是在 HDFS 上的)。
⼀个 WAL 实例包含有多个 WAL ⽂件,WAL ⽂件的最⼤数量通过 ionrver.maxlogs(默认是 32)参数来定义。
其他的触发滚动的条件是:
当 WAL ⽂件所在的块(Block)快要满了;
当WAL所占的空间⼤于或者等于某个阀值,该阀值的计算公式是:ionrver.hlog.blocksize *中国日语
WAL ⽂件被创建出来后会放在 /hba/.log 下(这⾥说的路径都是基于 HDFS),⼀旦 WAL ⽂件被判定为要归档,则会被移动
到 /hba/.oldlogs ⽂件夹。Master 会负责定期地去清理 .oldlogs ⽂件夹,判断的条件是“没有任何引⽤指向这个 WAL ⽂件”。⽬前有两种服务可能会引⽤ WAL ⽂件:
TTL 进程:该进程会保证 WAL ⽂件⼀直存活直到达到 hba.l 定义的超时时间(默认 10 分钟)为⽌;
备份(replication)机制:如果开启了 HBa 的备份机制,那么 HBa 要保证备份集群已经完全不需要这个 WAL ⽂件了,才会删除这个 WAL ⽂件。这⾥提到的 replication 不是⽂件的备份数,⽽是 0.90 版本加⼊的特性,这个特性⽤于把⼀个集群的数据实时备份到另外⼀个集群。
6、Store 内部结构
在 Store 中有两个重要组成部分:
MemStore:每个 Store 中有⼀个 MemStore 实例,数据写⼊ WAL 之后就会被放⼊ MemStore。MemStore 是内存的存储对象,只有当 MemStore 满了的时候才会将数据刷写(flush)到 HFile 中;
HFile:在 Store 中有多个 HFile,当 MemStore 满了之后 HBa 就会在 HDFS 上⽣成⼀个新的 HFile,然后把 MemStore 中的内容写到这个 HFile 中。HFile 直接跟 HDFS 打交道,它是数据的存储实体。
Store 内部结构
WAL 是存储在 HDFS 上的,Memstore 是存储在内存中的,HFile ⼜是存储在 HDFS 上的;数据是先写⼊ WAL,再被放⼊Memstore,最后被持久化到 HFile 中。数据在进⼊ HFile 之前已经被存储到 HDFS ⼀次了,为什么还需要被放⼊ Memstore?
这是因为 HDFS 上的⽂件只能创建、追加、删除,但是不能修改。对于⼀个数据库来说,按顺序地存放数据是⾮常重要的,这是性能的保障,所以我们不能按照数据到来的顺序来写⼊硬盘。
可以使⽤内存先把数据整理成顺序存放,然后再⼀起写⼊硬盘,这就是 Memstore 存在的意义。虽然 Memstore 是存储在内存中
的,HFile 和 WAL 是存储在 HDFS 上的,但由于数据在写⼊ Memstore 之前,要先被写⼊ WAL,所以增加 Memstore 的⼤⼩并不能加速写⼊速度。Memstore 存在的意义是维持数据按照 rowkey 顺序排列,⽽不是做⼀个缓存。
7、MemStore
设计 MemStore 的原因有以下⼏点:
由于 HDFS 上的⽂件不可修改,为了让数据顺序存储从⽽提⾼读取效率,HBa 使⽤了 LSM 树结构来存储数据,数据会先在Memstore 中整理成 LSM 树,最后再刷写到 HFile 上。
优化数据的存储,⽐如⼀个数据添加后就马上删除了,这样在刷写的时候就可以直接不把这个数据写到 HDFS 上。
不过不要想当然地认为读取也是先读取 Memstore 再读取磁盘哟!读取的时候是有专门的缓存叫 BlockCache,这个 BlockCache 如果开启了,就是先读 BlockCache,读不到才是读 HFile+Memstore。
8、HFile(StoreFile)
HFile 是数据存储的实际载体,我们创建的所有表、列等数据都存储在 HFile ⾥⾯。HFile 是由⼀个⼀个的块组成的,在 HBa 中⼀个块的⼤⼩默认为 64KB,由列族上的 BLOCKSIZE 属性定义。这些块区分了不同的⾓⾊:
Data:数据块。每个 HFile 有多个 Data 块,我们存储在 HBa 表中的数据就在这⾥,Data 块其实是可选的,但是⼏乎很难看到不包含 Data 块的 HFile;
然后的英文
Meta:元数据块。Meta 块是可选的,Meta 块只有在⽂件关闭的时候才会写⼊。Meta 块存储了该 HFile ⽂件的元数据信息,在 v2之前布隆过滤器(Bloom Filter)的信息直接放在 Meta ⾥⾯存储,v2 之后分离出来单独存储;护肤要点
FileInfo:⽂件信息,其实也是⼀种数据存储块。FileInfo 是 HFile 的必要组成部分,是必选的,它只有在⽂件关闭的时候写⼊,存储的是这个⽂件的信息,⽐如最后⼀个 Key(LastKey),平均的 Key 长度(AvgKeyLen)等;
DataIndex:存储 Data 块索引信息的块⽂件。索引的信息其实也就是 Data 块的偏移值(offt),DataIndex 也是可选的,有 Data 块才有 DataIndex;
MetaIndex:存储 Meta 块索引信息的块⽂件。MetaIndex 块也是可选的,有 Meta 块才有 MetaIndex;
Trailer:必选的,它存储了 FileInfo、DataIndex、MetaIndex 块的偏移值。
HFile 组成结构
其实叫 HFile 或者 StoreFile 都没错,在物理存储上我们管 MemStore 刷写⽽成的⽂件叫 HFile,StoreFile 就是 HFile 的抽象类⽽已。
9、Data 数据块
Data 数据块的第⼀位存储的是块的类型,后⾯存储的是多个 KeyValue 键值对,也就是单元格(Cell)的实现类,Cell 是⼀个接
⼝,KeyValue 是它的实现类。
西雅图工作英语Data 数据块结构