1.HBase简介
1.1 定义
HBase 是一种分布式、可扩展、支持海量数据存储的 NoSQL 数据库。
1.2 HBase数据模型
1.2.1逻辑结构
逻辑上,HBase 的数据模型同关系型数据库很类似,数据存储在一张表中,有行有列。但从 HBase 的底层物理存储结构(K-V)来看,HBase 更像是一个 multi-dimensional map
实际上逻辑表中的数据是稀疏的,有些cell没有值 稀疏数组参考
1.2.2 HBase物理存储结构
以上即为稀疏数据的存储
1.2.3 数据模型
➢ Name Space
命名空间,类似于关系型数据库的 DatabBase 概念,每个命名空间下有多个表。HBase 有两个自带的命名空间,分别是 hbase 和 default,hbase 中存放的是 HBase 内置的表, default 表是用户默认使用的命名空间
➢ Table
类似于关系型数据库的表概念。不同的是,HBase 定义表时只需要声明列族即可,不需 要声明具体的列。这意味着,往 HBase 写入数据时,字段可以动态、按需指定。因此,和关 系型数据库相比,HBase 能够轻松应对字段变更的场景
➢ Row
HBase 表中的每行数据都由一个 RowKey 和多个 Column(列)组成,数据是按照 RowKey 的字典顺序存储的,并且查询数据时只能根据 RowKey 进行检索,所以 RowKey 的设计十分重要
➢ Column
HBase 中的每个列都由 Column Family(列族)和 Column Qualifier(列限定符)进行限 定,例如 info:name,info:age。建表时,只需指明列族,而列限定符无需预先定义
➢ Time Stamp
用于标识数据的不同版本(version),每条数据写入时,如果不指定时间戳,系统会 自动为其加上该字段,其值为写入 HBase 的时间。
➢ Cell
由{rowkey, column Family:column Qualifier, time Stamp} 唯一确定的单元。cell 中的数 据是没有类型的,全部是字节码形式存贮
具体 参考官网
1.3 HBase 架构
1.3.1 Master
Master 是所有 Region Server 的管理者,其实现类为 HMaster(服务器上有个HMaster进程),主要作用如下: 对于表的操作:create, delete, alter对于 RegionServer 的操作:分配 regions 到每个 RegionServer,监控每个 RegionServer的状态,负载均衡和故障转移。即负责ddl操作
1.3.2 Region Server
Region Server 为 Region 的管理者,其实现类为 HRegionServer(服务器上有个HRegionServer进程),主要作用如下: 对于数据的操作:get, put, delete(负责dml操作);对于 Region 的操作:splitRegion、compactRegion。一个Region Server管理多个Region
1.3.3 Zookeeper
HBase 通过 Zookeeper 来做 Master 的高可用、RegionServer 的监控、元数据的入口以及 集群配置的维护等工作。(具体请看第5章高可用)
1.3.4 HDFS
HDFS 为 HBase 提供最终的底层数据存储服务,同时为 HBase 提供高可用的支持
2.HBase入门
2.1安装部署
2.1.1standalone
略 官网文档
2.1.2Distributed
略 官网文档
配置注意
hbase_env.sh中
//不要使用内部的zk
export HBASE_MANAGES_ZK=false
hbase-site.xml中添加如下信息
<!-- 是否分布式 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- 端口号 -->
<property>
<name>hbase.master.port</name>
<value>16000</value>
</property>
<!-- hbase文件存储地址,设置为hdfs -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://localhost:9000/HBase</value>
</property>
<!--zk地址-->
<property>
<name>hbase.zookeeper.quorum</name>
<value>localhost</value>
</property>
<!-- zk存储文件地址 -->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/usr/local/zookeeper-3.4.14/zkData</value>
</property>
2.2 HBase Shell
-- 启动关闭相关
-- 1.启动hbase
bin/start-hbase.sh
-- 2.查看启动情况,
-- 单机版只会有 HMaster 进程
jps
-- 3.关闭hbase
bin/stop-hbase.sh
-- 基础命令
-- 1.进入 HBase 客户端命令行
bin/hbase shell
-- 2.查看帮助命令
help
-- 3.查看当前数据库中有哪些表
list
-- 表空间
-- 1.创建namespace
create_namespace 'nametest'
-- 2.删除namespace
drop_namespace 'nametest'
-- 3.查看namespace
describe_namespace 'nametest'
-- 4.列出所有namespace
list_namespace
-- 5.在namespace下创建表
create 'nametest:testtable', 'fm1'
-- 6.查看namespace下的表
list_namespace_tables 'nametest'
-- 表的操作
-- 1.创建表 , student 为表名,info为列族
create 'student','info'
-- 2.插入数据到表 1001 为rowkey , info:sex 为列族和列名,male为值
put 'student','1001','info:sex','male'
put 'student','1002','info:sex','female'
-- 3.扫描查看表数据
scan 'student'
scan 'student',{LIMIT=>10}
scan 'student',{STARTROW => '1001', STOPROW => '1001'}
scan 'student',{STARTROW => '1001'}
scan 'student',{LIMIT => 10,INTERVAL => 10000,CACHE => 10000}. # 一次查询10000行,cache 为10000. https://hbase.apache.org/book.html#_commands
-- 扫描指定列数据
scan 'student',{COLUMNS => ['c:fss_days'],LIMIT => 100}
-- 4.查看表结构
describe `student`
-- 5.更新指定字段的数据
put 'student','1001','info:name','Nick'
put 'student','1001','info:age','100'
-- 6.查看“指定行”或“指定列族:列”的数据
get 'student','1001'
get 'student','1001','info:name'
get 'student','1001',{COLUMN=>'info:name',VERSIONS=>1}
-- 7.统计表数据行数
count 'student',INTERVAL => 10000
-- 8.删除数据
-- 删除某 rowkey 的全部数据:
deleteall 'student','1001'
-- 删除某 rowkey 的某一列数据:
put 'student','1001','info:sex','male'
put 'student','1001','info:age','18'
delete 'student','1002','info:sex'
-- 9.清空表数据
truncate 'student'
-- 提示:清空表的操作顺序为先 disable,然后再 truncate
-- 10.删除表
-- 首先需要先让该表为 disable 状态
disable 'student'
-- 然后才能 drop 这个表:
drop 'student'
-- 提示:如果直接 drop 表,会报错:ERROR: Table student is enabled. Disable it first.
-- 11.变更表信息
-- 将 info 列族中的数据存放 3 个版本:
alter 'student',{NAME=>'info',VERSIONS=>3}
get 'student','1001',{COLUMN=>'info:name',VERSIONS=>3}
2.3 Shell Fiter
2.3.1 介绍
scan命令我们经常会大量使用Filter,hbase shell提供的filter都可以在hbase client包中找到对应的类,它们都是Filter的子类,很多命令都是通过filter来进行实现的
{}中的语法是ruby的map的语法,FILTER必须大写,filter的参数是根据构造方法来的,也就是相当于java中的new Filter('param1','param2')等,这里只是省略了new参数而已。
当然同样可以使用ruby中new对象的方式,只是那样就必须使用全限定名称。后面会举一个全限定名称的例子
使用show_filters
命令查看shell中定义了哪些filter常量,如果想要使用shell中未定义的常量,在使用的时候必须手动import filter的全路径。各类的使用说明: org.apache.hadoop.hbase.filter
- DependentColumnFilter
- KeyOnlyFilter
- ColumnCountGetFilter
- SingleColumnValueFilter
- PrefixFilter
- SingleColumnValueExcludeFilter
- FirstKeyOnlyFilter
- ColumnRangeFilter
- TimestampsFilter
- FamilyFilter
- QualifierFilter
- ColumnPrefixFilter
- RowFilter
- MultipleColumnPrefixFilter
- InclusiveStopFilter
- PageFilter
- ValueFilter
- ColumnPaginationFilter
比较器
HBase的filter有四种比较器:
- 二进制比较器:如’binary:abc’,按字典排序跟’abc’进行比较
- 二进制前缀比较器:如’binaryprefix:abc’,按字典顺序只跟’abc’比较前3个字符
- 正则表达式比较器:如’regexstring:ab*yz’,按正则表达式匹配以ab开头,以yz结尾的值。这个比较器只能使用=、!=两个比较运算符。
- 子串比较器:如’substring:abc123’,匹配以abc123开头的值。这个比较顺也只能使用=、!=两个比较运算符。
比较运算符
HBase的filter中有7个比较运算符:
- LESS (<)
- LESS_OR_EQUAL (<=)
- EQUAL (=)
- NOT_EQUAL (!=)
- GREATER_OR_EQUAL (>=)
- GREATER (>)
- NO_OP (no operation)
2.3.2 使用
# 过滤 test 表中 cf a,列为 info,值不为 空的数据
scan 'test',{LIMIT => 10,FILTER => "SingleColumnValueFilter('a','info',=,'regexstring:\\S')"}
# 列前缀为 parent的数据
scan 'test',{LIMIT => 10,FILTER => "ColumnPrefixFilter('parent')"}
后续再补充啦。。。
还可以有如下写法
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter
import org.apache.hadoop.hbase.filter.CompareFilter
import org.apache.hadoop.hbase.filter.BinaryComparator
scan ‘tweet0’, { FILTER => SingleColumnValueFilter.new(Bytes.toBytes(‘info’), Bytes.toBytes(‘id’), CompareFilter::CompareOp.valueOf(‘EQUAL’), BinaryComparator.new(Bytes.toBytes(‘1001158684’))), COLUMNS=>[‘info:id’]}
# 注意:
# 1)如果scan中指定了COLUMNS,则FILTER中所使用的列需要包含在所指定的COLUMNS中,否则,filter不起作用。
# 2)HBase中主要的操作对象是一个个的cell,每个cell都可以有多个版本。如果使用过滤器ValueFilter,就会只有那些符合条件的cell被查出来。跟关系数据库的查询不同,关系数据库查出来的结果中各行都有相同的列。而HBase,查出来的结果中,不同的行会有不同的列。
# 3)filter不会降低服务方的IO,它会把符合条件的子集传给客户端。即,它是在对查出的结果进行过滤,而不是象原来sql中的where子句。所以,如果要查出的结果中不包含filter需要的列,则filter就不能发挥作用。
3.HBase进阶
3.1架构原理
➢ Region
table
在行的方向上分隔为多个Region
。Region
是HBase中分布式存储和负载均衡的最小单元,即不同的region
可以分别在不同的Region Server
上,但同一个Region
是不会拆分到多个server上。Region
按大小分隔,表中每一行只能属于一个region
。随着数据不断插入表,region
不断增大,当region
的某个列族达到一个阈值,时就会分成两个新的region
。
➢ Store
每一个region
有一个或多个store
组成,至少是一个store
,hbase会把一起访问的数据放在一个store
里面,即为每个ColumnFamily
建一个store
(即有几个ColumnFamily
,也就有几个Store)。一个Store
由一个memStore
和0
或多个StoreFile
组成。
➢ StoreFile
保存实际数据的物理文件,StoreFile 以 HFile 的形式存储在 HDFS 上。每个 Store 会有一个或多个 StoreFile(HFile),数据在每个 StoreFile 中都是有序的
➢ WAL(Hlog)
由于数据要经 MemStore 排序后才能刷写到 HFile,但把数据保存在内存中会有很高的 概率导致数据丢失,为了解决这个问题,数据会先写在一个叫做 Write-Ahead logfile 的文件 中,然后再写入 MemStore 中。所以在系统出现故障的时候,数据可以通过这个日志文件重 建
➢ MemStore
写缓存,由于 HFile 中的数据要求是有序的,所以数据是先存储在 MemStore 中,排好序后,等到达刷写时机才会刷写到 HFile,每次刷写都会形成一个新的 HFile
个人理解:
1.store(源码中一个类)理解为对应管理column Family,一个列族对应hdfs文件系统中一个文件夹(和hive中分区类似)
2.一个store可以多个storefile,其文件格式为hfile(类似hive中orc,parquet)
3.刷写一次产生一个hfile
4.zk分担了和客户端和hmaster的交互。即客户端进行读写请求直接查询zk,然后去操作HRegion Server。因此,如果只是读写数据,HMaster挂了也同样可以正常运转,如果是修改元数据则会报错(ddl)
5.Hlog理解为对应mysql中binlog
3.2 写流程
写流程:
- Client 先访问 zookeeper,获取 hbase:meta 表位于哪个 Region Server
- 访问对应的 Region Server,获取 hbase:meta 表,根据读请求的 namespace:table/rowkey, 查询出目标数据位于哪个 Region Server 中的哪个 Region 中。并将该 table 的 region 信息以及 meta 表的位置信息缓存在客户端的 meta cache,方便下次访问
- 与目标 Region Server 进行通讯
- 将数据顺序写入(追加)到 WAL
- 将数据写入对应的 MemStore,数据会在 MemStore 进行排序
- 向客户端发送 ack
- 等达到 MemStore 的刷写时机后,将数据刷写到 HFile
3.3 MemStore Flush
MemStore 刷写时机:
- 当某个 memstore 的大小达到了 hbase.hregion.memstore.flush.size(默认值 128M),其所在 region 的所有 memstore 都会刷写。 当 memstore 的大小达到了hbase.hregion.memstore.flush.size(默认值 128M)* hbase.hregion.memstore.block.multiplier(默认值 4)时,会阻止继续往该 memstore 写数据
- 当 region server 中 memstore 的总大小达到 java_heapsize *hbase.regionserver.global.memstore.size(默认值 0.4) *hbase.regionserver.global.memstore.size.lower.limit(默认值 0.95),region 会按照其所有 memstore 的大小顺序(由大到小)依次进行刷写。直到 region server中所有 memstore 的总大小减小到上述值以下。 当 region server 中 memstore 的总大小达到java_heapsize*hbase.regionserver.global.memstore.size(默认值 0.4) 时,会阻止继续往所有的 memstore 写数据
- 到达自动刷写的时间,也会触发memstoreflush。自动刷新的时间间隔由该属性进行 配置 hbase.regionserver.optionalcacheflushinterval(默认 1 小时)
- 当 WAL 文件的数量超过 hbase.regionserver.max.logs,region 会按照时间顺序依次进 行刷写,直到 WAL 文件数量减小到 hbase.regionserver.max.log 以下(该属性名已经废弃, 现无需手动设置,最大值为 32)
3.4读流程
读流程
- Client 先访问 zookeeper,获取 hbase:meta 表位于哪个 Region Server
- 访问对应的 Region Server,获取 hbase:meta 表,根据读请求的 namespace:table/rowkey, 查询出目标数据位于哪个 Region Server 中的哪个 Region 中。并将该 table 的 region 信息以 及 meta 表的位置信息缓存在客户端的 meta cache,方便下次访问
- 与目标 Region Server 进行通讯
- 分别在 Block Cache(读缓存),MemStore 和 Store File(HFile)中查询目标数据,并将 查到的所有数据进行合并。此处所有数据是指同一条数据的不同版本(time stamp)或者不 同的类型(Put/Delete)
- 将从文件中查询到的数据块(Block,HFile 数据存储单元,默认大小为 64KB)缓存到 Block Cache
- 将合并后的最终结果返回给客户端
3.5 StoreFile Compaction
由于 memstore 每次刷写都会生成一个新的 HFile,且同一个字段的不同版本(timestamp) 和不同类型(Put/Delete)有可能会分布在不同的 HFile 中,因此查询时需要遍历所有的 HFile为了减少 HFill的个数,以及清理掉过期和删除的数据,会进行 StoreFile Compaction
Compaction 分为两种,分别是 Minor Compaction 和 Major Compaction。Minor Compaction会将临近的若干个较小的HFile 合并成一个较大的 HFile,但不会清理过期和删除的数据。 Major Compaction 会将一个 Store 下的所有的 HFile 合并成一个大 HFile,并且会清理掉过期 和删除的数据
触发机制:
➢ 由hbase.hregion.majorcompaction参数指定,默认为7天(7天触发一次)。此操作比较耗资源,生产环境建议关掉,改手动触发
➢ hbase.hstore.compactionThreshold设置阈值,默认为3,当hfile超过3时(不包括3),自动触发合并
具体参考 compaction
3.6 Region Split
默认情况下,每个 Table 起初只有一个 Region,随着数据的不断写入,Region 会自动进 行拆分。刚拆分时,两个子 Region 都位于当前的 Region Server,但处于负载均衡的考虑, HMaster 有可能会将某个 Region 转移给其他的 Region Server。
Region Split 时机:
- 当 1 个 region 中的某个 Store 下所有 StoreFile 的总大小超过 hbase.hregion.max.filesize(10g), 该 Region 就会进行拆分(0.94 版本之前)。
- 当 1 个 region 中的某个 Store 下所有 StoreFile 的总大小超过 Min(R^2 * "hbase.hregion.memstore.flush.size",hbase.hregion.max.filesize"),该 Region 就会进行拆分,其 中 R 为当前 RegionServer 中属于该 Table 的region个数(0.94 版本之后) hbase.hregion.max.filesiz默认为10g;hbase.hregion.memstore.flush.size默认为128
4.HBaseAPI
4.1HBaseAPI
关于删除
4.2MapReduce
4.3与 Hive 的集成
4.3.1 HBase 与 Hive 的对比
1.Hive
- 数据仓库:Hive 的本质其实就相当于将 HDFS 中已经存储的文件在 Mysql 中做了一个双射关系,以 方便使用 HQL 去管理查询。
- 用于数据分析、清洗:Hive 适用于离线的数据分析和清洗,延迟较高。
- 基于 HDFS、MapReduce:Hive 存储的数据依旧在 DataNode 上,编写的 HQL 语句终将是转换为 MapReduce 代码执 行
2.HBase
- 数据库:是一种面向列族存储的非关系型数据库
- 用于存储结构化和非结构化的数据 适用于单表非关系型数据的存储,不适合做关联查询,类似 JOIN 等操作
- 基于 HDFS:数据持久化存储的体现形式是 HFile,存放于 DataNode 中,被 ResionServer 以 region 的形 式进行管理
- 延迟较低,接入在线业务使用:面对大量的企业数据,HBase 可以直线单表大量数据的存储,同时提供了高效的数据访问 速度
4.3.2案例
➢ 建立 Hive 表,关联 HBase 表,插入数据到 Hive 表的同时能够影响 HBase 表
CREATE TABLE hive_hbase_emp_table(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:co
mm,info:deptno")
TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");
1.完成之后,可以分别进入 Hive 和 HBase 查看,都生成了对应的表
2.不能将数据直接 load 进 Hive 所关联 HBase 的那张表中
➢ 在 HBase 中已经存储了某一张表 hbase_emp_table,然后在 Hive 中创建一个外部表来 关联 HBase 中的 hbase_emp_table 这张表,使之可以借助 Hive 来分析 HBase 这张表中的数 据
CREATE EXTERNAL TABLE relevance_hbase_emp( empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int)
STORED BY
'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,info:ename,info:job,info:mgr,info:hiredate,info:sal,info:co mm,info:deptno")
TBLPROPERTIES ("hbase.table.name" = "hbase_emp_table");
一般是此操作
5.HBase优化
5.1高可用
在 HBase 中 HMaster 负责监控 HRegionServer 的生命周期,均衡 RegionServer 的负载, 如果 HMaster 挂掉了,那么整个 HBase 集群将陷入不健康的状态,并且此时的工作状态并 不会维持太久。所以 HBase 支持对 HMaster 的高可用配置。只需 conf 目录下创建 backup-masters 文件,写入比用hmaster即可
HMaster和zk进行交互,当HMaster挂了后,backup-Master和zk通信升级成HMaster,如果有多个backup,则谁先到谁成HMaster
5.2 预分区
每一个 region 维护着 StartRow 与 EndRow,如果加入的数据符合某个 Region 维护的 RowKey 范围,则该数据交给这个 Region 维护。那么依照这个原则,我们可以将数据所要 投放的分区提前大致的规划好,以提高 HBase 性能
5.3 RowKey 设计
我司设计rowkey 统一采用规则:concat(substring(md5(biz_key),1,4),'_',biz_key)
5.4 内存优化
HBase 操作过程中需要大量的内存开销,毕竟 Table 是可以缓存在内存中的,一般会分 配整个可用内存的 70%给 HBase 的 Java 堆。但是不建议分配非常大的堆内存,因为 GC 过 程持续太久会导致 RegionServer 处于长期不可用状态,一般 16~48G 内存就可以了,如果因 为框架占用内存过高导致系统内存不足,框架一样会被系统服务拖死
6 Hbase数据结构&存储结果
6.1 Hbase之LSM
6.1.1 核心思想
如上图所示,LSM树有以下三个重要组成部分:
1) MemTable
MemTable是在内存中的数据结构,用于保存最近更新的数据,会按照Key有序地组织这些数据,LSM树对于具体如何组织有序地组织数据并没有明确的数据结构定义,例如Hbase使跳跃表来保证内存中key的有序。
因为数据暂时保存在内存中,内存并不是可靠存储,如果断电会丢失数据,因此通常会通过WAL(Write-ahead logging,预写式日志)的方式来保证数据的可靠性。
2) Immutable MemTable
当 MemTable达到一定大小后,会转化成Immutable MemTable。Immutable MemTable是将转MemTable变为SSTable的一种中间状态。写操作由新的MemTable处理,在转存过程中不阻塞数据更新操作。
3) SSTable(Sorted String Table)
有序键值对集合,是LSM树组在磁盘中的数据结构。为了加快SSTable的读取,可以通过建立key的索引以及布隆过滤器来加快key的查找。
这里需要关注一个重点,LSM树(Log-Structured-Merge-Tree)正如它的名字一样,LSM树会将所有的数据插入、修改、删除等操作记录(注意是操作记录)保存在内存之中,当此类操作达到一定的数据量后,再批量地顺序写入到磁盘当中。这与B+树不同,B+树数据的更新会直接在原数据所在处修改对应的值,但是LSM数的数据更新是日志式的,当一条数据更新是直接append一条更新记录完成的。这样设计的目的就是为了顺序写,不断地将Immutable MemTable flush到持久化存储即可,而不用去修改之前的SSTable中的key,保证了顺序写
6.1.2 定义
- LSM树是一个横跨内存和磁盘的,包含多颗"子树"的一个森林。
- LSM树分为Level 0,Level 1,Level 2 ... Level n 多颗子树,其中只有Level 0在内存中,其余Level 1-n在磁盘中。
- 内存中的Level 0子树一般采用排序树(红黑树/AVL树)、跳表或者TreeMap等这类有序的数据结构,方便后续顺序写磁盘。
- 磁盘中的Level 1-n子树,本质是数据排好序后顺序写到磁盘上的文件,只是叫做树而已。
- 每一层的子树都有一个阈值大小,达到阈值后会进行合并,合并结果写入下一层。
- 只有内存中数据允许原地更新,磁盘上数据的变更只允许追加写,不做原地更新
- 图中分成了左侧绿色的内存部分和右侧蓝色的磁盘部分(定义1)。
- 图左侧绿色的内存部分只包含Level 0树,右侧蓝色的磁盘部分则包含Level 1-n等多棵"树"(定义2)
- 图左侧绿色的内存部分中Level 0是一颗二叉排序树(定义3)。注意这里的有序性,该性质决定了LSM树优异的读写性能。
- 图右侧蓝色的磁盘部分所包含的Level 1到Level n多颗树,虽然叫做“树”,但本质是按数据key排好序后,顺序写在磁盘上的一个个文件(定义4) ,注意这里再次出现了有序性。
- 内存中的Level 0树在达到阈值后,会在内存中遍历排好序的Level 0树并顺序写入磁盘的Level 1。同样的,在磁盘中的Level n(n>0)达到阈值时,则会将Level n层的多个文件进行归并,写入Level n+1层。(定义5)
- 除了内存中的Level 0层做原地更新外,对已写入磁盘上的数据,都采用Append形式的磁盘顺序写,即更新和删除操作并不去修改老数据,只是简单的追加新数据。图1中右侧蓝色的磁盘部分,Level 1和Level 2均包含key为2的数据,同时图1左侧绿色内存中的Level 0树也包含key为2的数据节点。(定义6)
6.1.3 优缺点
优:增、删、改操作飞快,写吞吐量极大。
缺:读操作性能相对被弱化;不擅长区间范围的读操作; 归并操作较耗费资源
以上是对LSM树基本操作以及优缺点的分析,我们可以据此得出LSM树的设计原则:
- 先内存再磁盘
- 内存原地更新
- 磁盘追加更新
- 归并保留新值
如果说B/B+树的读写性能基本平衡的话,LSM树的设计原则通过舍弃部分读性能,换取了无与伦比的写性能。该数据结构适合用于写吞吐量远远大于读吞吐量的场景,得到了NoSQL届的喜爱和好评
常用的一下组件,如rocksdb,clickhouse、kafka 都有用到 LSM
具体可参考如下:
6.2 Hbase之跳表
HBase--内存结构之跳表数据结构浅析_Keep hunger的博客-CSDN博客
6.3 Hbase之布隆过滤器
待整理。。。