- 是一个高可靠性、高性能、面向列、可伸缩、实时读写的分布式数据库
- 利用Hadoop HDFS作为其文件存储系统
- 利用Zookeeper作为其分布式协同服务主要用来存储非结构化和半结构化的松散数据(列存 NoSQL 数据库)
-
容量大
- 单表可以有百亿行、百万列
-
面向列
- 数据在表中是按照某列存储的,这样在查询只需要少数几个字段的时候,能大大减少读取的数量
-
多版本
- 每一个列的数据存储有多个Version
-
稀疏性
- 为空的列并不占用存储空间,表可以设计的非常稀疏
-
拓展性
- 底层依赖HDFS,当磁盘空间不足的时候,只需要动态增加datanode节点服务(机器)就可以了
-
高可靠性
- WAL机制,保证数据写入的时候不会因为集群异常而导致写入数据丢失
- Replication机制,保证了在集群出现严重的问题时候,数据不会发生丢失或者损坏
- Hbase底层使用HDFS,本身也有备份
-
高性能
- 底层的LSM数据结构和RowKey有序排列等架构上的独特设计,使得Hbase写入性能非常高
-
数据库量要足够多
-
保证硬件资源足够
-
内部应用
- 存储业务数据
- 存储日志数据
- 存储业务附件
NameSpace
数据库
-
命名空间是类似于关系数据库系统中的数据库的概念,他其实是表的逻辑分组
-
命名空间是可以管理维护的,可以创建,删除或更改命名空间
-
Hbase有两个特殊预定义的命名空间
- default - 没有明确指定名称空间的表将自动落入此名称空间
- hbase - 系统命名空间,用于包含Hbase内部表
Table
表
- 存储相同数据的一个逻辑单元
- 表有多个行数据组成,行有很多列组成
- Hbase是一个半结构的数据库, 所以每行的列都有可能是不同
主键
- 可以理解为一行数据的主键
- Hbase按照列进行存储,所以我们查询数据的时候会看到很多RowKey相同的列
- 多可以有64K字节组成股能10-40个字节即可
- 将来设计RowKey是Hbase使用的重中之重
- RowKey存储的时候默认以字典序排序
Column Family
列
- 可以理解为多个列的集合
- 方便队列进行查找和管理
- 一个表的列族需要使用之前声明(创建表、后期维护表)
- 列隶属于列族,列族隶属于表
- 一个表中列族是固定的但列不是固定的
Column Qualifier
- 个列族中的列是不固定的
- 有可能有的数据行一个列族中有3个列,有的行相同列族有8个列
- 使用的时候必须列族:列
Timestamp
- 默认就是时间戳,解决HDFS不能随时修改数据的弊端
- 默认数据版本就是时间戳
- 查询数据的时候默认显示最新的数据
Cell
- row, column family,column qualifier,version
- 所有的数据都是字符串
-
Shell实现DDL *** 作
-
创建一个表
-
create ‘t1’,{NAME => ‘f1’, VERSIONS => 2},{NAME => ‘f2’, VERSIONS => 2}
-
标准创建
- create ‘member’,‘member_id’,‘address’,‘info’
-
-
获得表的描述
- describe
-
删除一个列族,alter,disable,enable
-
alter ‘member’,{NAME=>‘member_id’,METHOD=>‘delete’}
-
将表enable
- enable ‘member’
-
列出所有的表
- list
-
drop一个表
- create ‘temp_table’,‘member_id’,‘address’,‘info’
- hbase(main):029:0>disable ‘temp_table’
- hbase(main):030:0>drop ‘temp_table’
-
-
查询表是否存在
- hbase(main):021:0>exists ‘member’
-
-
Shell实现DML *** 作
-
插入、更新
- put’member’,‘guojing’,‘info:age’,‘24’
-
删除id为temp的值的‘info:age’字段
- delete ‘member’,‘temp’,‘info:age’
-
删除整行
- deleteall ‘member’,‘xiaofeng’
-
查询表中有多少行
- count ‘member’
-
给‘xiaofeng’这个id增加’info:age’字段,并使用counter实现递增
- incr ‘member’,‘xiaofeng’,‘info:age’
-
获取当前count的值
- get_counter ‘member’,‘xiaofeng’,‘info:age’
-
将整张表清空
- truncate ‘member’
-
使用count命令计算表的行数量
- count ‘member’
-
-
Shell实现DQL *** 作
-
获取一个id的所有数据
- get ‘member’,‘linghuchong’
-
获取一个id,一个列族的所有数据
- get ‘member’,‘linghuchong’,‘info’
-
获取一个id,一个列族中一个列的所有数据
- get ‘member’,‘linghuchong’,‘info:age’
-
通过timestamp来获取两个版本的数据
- get ‘member’,‘linghuchong’,
{COLUMN=>‘info:age’,TIMESTAMP=>1321586238965} - get ‘member’,‘linghuchong’,
{COLUMN=>‘info:age’,TIMESTAMP=>1321586571843}
- get ‘member’,‘linghuchong’,
-
全表扫描
- scan ‘member’
- 一般都和过滤器一起使用
-
-
Shell实现Region管理
-
移动region
- move ‘encodeRegionName’, ‘ServerName’
-
开启/关闭region
- balance_switch true|false
-
手动split
- split ‘regionName’, ‘splitKey’
- 删除之后当前Region并不会马上消失,需要等待Hbase检查新Region的工作状态
-
手动触发major compaction
- major_compact ‘t1’
-
-
总结
-
通用命令
- status: 提供Hbase的状态,例如,服务器的数量。
- version: 提供正在使用Hbase版本。
- table_help: 表引用命令提供帮助。
- whoami: 提供有关用户的信息。
-
数据 *** 纵语言
- put: 把指定列在指定的行中单元格的值在一个特定的表。
- get: 取行或单元格的内容。
- delete: 删除表中的单元格值。
- deleteall: 删除给定行的所有单元格。
- scan: 扫描并返回表数据。
- count: 计数并返回表中的行的数目。
- truncate: 禁用,删除和重新创建一个指定的表。
-
数据定义语言
-
create: 创建一个表。
-
list: 列出Hbase的所有表。
-
disable: 禁用表。
- 要删除表或改变其设置,首先需要使用 disable 命令关闭表。使用 enable 命令,可以重新启用它。
-
-
- Hbase的客户端,可以向Hbase服务器发送请求
- 既可以是shell,也可以是Api
- *** 作包括DDL DML DQL ,Hbase不支持多表关联查询
- 客户端必要的时候会对数据进行一些缓存
- Hbase的主节点
- 责接收客户端的请求(仅限于DDL)
- 主(有负载均衡,单点故障)
- HMaster也可以实现高可用(active–standby)
- 主备的切换由Zookeeper负责监督维护
- 但是HMaster没有联邦机制,业务承载能力还是有限的
- 一个数据库的表的结构很少会发生变化,但是绝大部分是CRUD *** 作
- 于是Hbase的Master只负责DDL,DMLDQL由其他节点承担
- 负责管理HRegionServer的健康状况
- 上下线的监督----创建表的时候分配Region
- Hbase的具体工作节点,一般一台主机就是一个Region
- 一个RegionServer中包含很多的Region,HMaster负责分配Region
- 负责接收客户端的DML和DQL请求,建立连接???
- Hbase的表数据具体存放的位置
- 一个Region只隶属于一张表,但是一张表可以有多个Region
- 一个Region只隶属于一张表,但是一张表可以有多个Region
-
一个表中一个列簇对应一个Store
-
一个Store里面分为1个MemStore和N个StoreFile
-
MemStore
- 数据最开始优先写入到MemStore当Flush的时候才会被写入到磁盘
- 默认情况下一个MemStore的大小为128M
- 当客户端向数据库插入数据的时候,当内存使用到128M的时候
- 直接重新申请128M的内存空间,数据直接写到新内存中,原来已经满的数据写出到HDFS,称为HFile
-
Storefile
- 数据存储文件的映射,对应HDFS上的HFlle
- 一个Table对应多个Region,一个Region对应多个Store,一个Store对应一个MemStore和多个StoreFlle
- 多个StoreFile内部有序,但是外部无序
- 集群会设置一些阈值,当达到阈值的时候开始将小文件合并成大文件
-
-
MemStore:基于内存存放数据,每个Store大概分配128M的空间
-
StoreFile:是文件的硬盘存储,直接存储到HDFS,存到HDFS之后被称之为HFile
- Hbase的日志机制(WAL)
- 日志也会存储到HDFS,在任何 *** 作之前先记录日志到HDFS
- 以后MemStore丢失数据或者RegionServer异常都能够通过日志进行恢复
- 一个RegionServer对应一个HLog
- Hbase协调服务
- 1.主备的选举与切换
- ⒉.记录当前集群的状态信息,当主备切换的时候集群的状态可以被新主节点直接读取到
- 3.记录当前集群的数据存放信息
- 4.存储Hbase的元数据信息
-
Hbase 0.96以前
- 首先系统维护了两张表-root-.meta.
- .meta.表中存储了表对应Region对应的RegionServer RowKey的区间
- 但是.meta.表也是一张普通的Hbase表,也需要存放到RegionServer
- 于是专门使用-root-表来记录.meta.的存放位置
- 认为ROOT表只需要一个Region即可,-ROOT-的Region信息就被记录到Zookeeper
-
Hbase 0.96以后
- -ROOT-表被移除,直接将.meta表region位置信息存放在Zookeeper中
- meta表更名为hbase:meta
-
Region 中所有 MemStore 占用的内存超过相关阈值
-
整个 RegionServer 的 MemStore 占用内存总和大于相关阈值
-
WAL数量大于相关阈值
-
定期自动刷写
-
数据更新超过一定阈值
-
手动触发刷写
-
特别注意
- 以上所有条件触发的刷写 *** 作最后都会检查对应的 HStore 包含的 StoreFiles 文件数是否超过hbase.hstore.blockingStoreFiles 参数配置的个数,默认值是16。
- 如果满足这个条件,那么当前刷写会被推迟到hbase.hstore.blockingWaitTime 参数设置的时间后再刷写。
- 在阻塞刷写的同时,Hbase 还会请求 Compaction 或者Split *** 作。
-
Hbase1.1之前
- MemStore 刷写是 Region 级别的。就是说,如果要刷写某个 MemStore ,MemStore 所在的 Region 中其他 MemStore 也是会被一起刷写的
-
Hbase2.x之后
-
FlushAllStoresPolicy
- 每次刷写都是对 Region 里面所有的 MemStore 进行的
-
FlushAllLargeStoresPolicy
- 判断 Region 中每个 MemStore 的使用内存是否大于某个阀值,大于这个阀值的MemStore 将会被刷写。
- flushSizeLowerBound = max((long)128 / 3, 16) = 42
-
FlushNonSloppyStoresFirstPolicy
-
-
prepareFlush 阶段
- 如果MEM要进行刷写
- 对内存中的数据拍摄快照,拍摄时间会非常短
- 拍摄期间内存中的数据会被锁定,保证快照期间数据的安全
-
flushCache 阶段
- 将快照的数据写成一个临时文件到硬盘
- 将临时文件更名称正式文件存储到对应的列簇中
-
Minor Compaction(小型)
- 选取一些小的、相邻的StoreFile将他们合并成一个更大的StoreFile
- 仅仅是合并不会处理被删除的或者失效的数据
- 但是会处理超过TTL的数据
- 一次Minor Compaction的结果是让小的storefile变的更少并且产生更大的StoreFile。
-
Major Compaction(大型)
- 将所有的StoreFile合并成一个StoreFile
- 清理三类无意义数据:被删除的数据、TTL过期数据、版本号超过设定版本号的数据。
- 但是对整个集群影响较大,一般手动合并
- Memstore刷盘
- 周期性检查
- 手动触发
-
线程池选择
-
合并策略选择
- minor 策略: RatiobasedCompactionPolicy (0.96.x之前)
- ExploringCompactionPolicy(当前默认)
- 最开始—个表只有—个Region
- 对于这个表的查询都会被定位到这一个RegionServer
- 当Region达到阈值的时候就会进行切分
- 单点压力读写性能合并困难
-
每次数据合并之后,发起个requestSplit
然后开始检查文件的大小是否达到阈值-
ConstantSizeRegionSplitPolicy
- 10G
-
lncreasingToUpperBound
- 256M ----2048M —.。。 。—10G
-
-
寻找切分点
- 先找最大的Store.然后再找最大的StoreFile,再找到中心点位置的RowKey
-
切分
-
注意
- 行健不能改变,唯一可以改变的方式是先删除后插入
-
长度原则
- 语短越好
- Rowkey 是一个二进制码流,最大长度是64KB,建议越短越好。10-100长度即可,不要超过 16 个字节
-
散列原则
- 尽量将连续的数据存放到更多的RegionServer
-
唯一原则
- 必须在设计上保证其唯一性。rowkey 是按照字典顺序排序存储的
- 设计 rowkey 的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问 的数据放到一块
-
数据热点
-
原因
- 热点发生在大量的 client 直接访问集群的一个或极少数个节点
- 大量访问会使热点region所在的单个机器超出自身承受能力,性能下降甚至 region 不可用
-
策略
-
RowKey反转策略
- 例:x01、x02、x03存放在同一节点
反转x10、x20、x30就会存放在不同的节点
- 例:x01、x02、x03存放在同一节点
-
加盐策略
- 在 rowkey 的前面增加随机数
-
哈希策略
- 哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的
-
-
- 追求的原则是:在合理范围内能尽量少的减少列簇就尽量减少列簇
- 列簇的名字尽可能短,优先使用首字母
-
移动通话记录
-
手机号码_时间
-
首先按照手机号码排序,手机号相同的会排在一起
-
然后按照时间排序,会按照时间先后顺序排序
-
180-20201018102345678
- 180-20201001
- 180-20201101
-
-
京东订单
-
RowKey
- uname_timestramp 将相同用户的订单全部排列到一起,查询的时候只是从里面取出一小部分
-
列族
- order
-
列
- datetime、orderid、usernamegoodimgs、title、number、money
-
versions
- 1
-
-
人员职位映射表
-
规则
- 一个人可以有多个身份
- 一个身份可以被多个人拥有
- 一个人可以指定他的主要身份
-
要求
- 通过这个人的ID可以获取身份
- 通过身份可以获取个人
- 可以修改人的身份
- 可以修改身份对应的人员
- 人员可以设置主身份
-
方案
-
构建一个列族,将和自己关联到一起的数据全部以列名的方式存放
-
身份表
-
人员表
-
-
-
微博关系处理
- 人员表(rowkey,列族(个人信息,安全,统计信息(关注数,被关注数,发帖数)))
- 关注表(rowkey,列族(关注:rowkey))
- 粉丝表(rowkey,列族(被关注:rowkey))
- 发帖表(人员rowkey_timestamp)
-
预分区 Pre-Creating Regions
- 默认情况下,在创建Hbase表的时候会自动创建一个region分区,当导入数据的时候,所有的Hbase客户端都向这一个region写数据,直到这个region足够大了才进行切分。
- 有种加快批量写入速度的方法是通过预先创建一些空的regions,这样当数据写入Hbase时,会按照region分区情况,在集群内做数据的负载均衡。
-
rowkey
-
设计row key时,将经常一起读取的数据存储到一块,将最近可能会被访问的数据放在一块
-
Rowkey规则
- 1、 越小越好
- 2、 Rowkey的设计是要根据实际业务来
- 3、定长
- 3、 散列性
- a) 取反 001 002 100 200
- b) Hash
- c) 加盐
-
-
ColumnFamily
- 不要在一张表里定义太多的column family
- Hbase并不能很好的处理超过2~3个columnfamily的表
- 某个column family在flush的时候,它邻近的column family也会因关联效应被触发flush,最终导致系统产生更多的I/O
-
Version
- 创建表的时候设置表中数据的最大版本
- 创建表的时候设置表中数据的存储生命期,过期数据将自动被删除
-
compact & Split
-
多Table并发写
- 创建多个Table客户端用于写 *** 作,提高写数据的吞吐量
-
WAL Flag
- 首先会先写WAL(WriteAhead Log)日志(即HLog,一个RegionServer上的所有Region共享一个HLog),只有当WAL日志写成功后,再接着写MemStore
- 因此,对于相对不太重要的数据,可以在Put/Delete *** 作时,通过调用Put.setWriteToWAL(false)或Delete.setWriteToWAL(false)函数,放弃写WAL日志,从而提高数据写入的性能
-
批量写
- 批量写入多行记录,这样做的好处是批量执行,只需要一次网络I/O开销
-
显示的指定列
- 当使用Scan或者GET获取大量的行时,最好指定所需要的列
-
关闭ResultScanner
- 如果在使用table.getScanner之后,忘记关闭该类,它会一直和服务端保持连接,资源无法释放,从而导致服务端的某些资源不可用
-
查询结果
- 对于频繁查询Hbase的应用场景,可以考虑在应用程序和Hbase之间做一层缓存系统,新的查询先去缓存查,缓存没有再去查Hbase
-
设置Scan缓存
- 可以有效的减少服务端与客户端的交互
-
禁用块缓存
- 批量进行全表扫描,默认是有缓存的,如果此时有缓存,会降低扫描的效率
- 对于经常读到的数据,建议使用默认值,开启块缓存
-
缓存查询结果
- 对于频繁查询Hbase的应用场景,可以考虑在应用程序和Hbase之间做一层缓存系统,新的查询先去缓存查,缓存没有再去查Hbase
- protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法
- 先编写protobuf语言代码,设置压缩的字段和范围
- 执行bin下的proto程序,将protobuf的程序编译为java程序
- 使用hbaseapi的时候(加载或者读取),使用protobuf里边的方法
- Protobuf 有如 XML,不过它更小、更快、也更简单
- 你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构
- 功能简单,无法用来表示复杂的概念
- Protobuf 只是 Google 公司内部使用的工具,在通用性上还差很多
- Phoenix是构建在Hbase上的一个SQL层,能让我们用标准的JDBC APIs而不是Hbase客户端APIs来创建表,插入数据和对Hbase数据进行查询
-
重客户端架构
-
客户端包括应用程序开发,将SQL进行解析优化生成QueryPlan,进而转化为Hbase Scans,调用Hbase API下发查询计算请求,并接收返回结果;
-
服务端主要是利用Hbase的协处理器(Phoenix-core包里面包含hbase-client,以及hbase-server包),处理二级索引、聚合及JOIN计算等
-
缺陷
- 需要引入Phoenix内核依赖,目前一个单独Phoenix重客户端集成包已达120多M
- 运维不便,Phoenix仍在不断优化和发展,一旦Phoenix版本更新,那么应用程序也需要对应升级版本并重新发布
- 仅支持Java API,其他语言开发者不能使用Phoenix
-
-
轻客户端架构
-
瘦客户端是用户最小依赖的JDBC驱动程序,与Phoenix依赖进行解耦,支持Java、Python、Go等多种语言客户端;
-
QueryServer是一个单独部署的HTTP服务,接收轻客户端的RPC请求,并将SQL转发给PhoenixCore进行解析优化执行;
- 类似hive的beeline
-
Phoenix Server与重客户端架构相同
-
-
查看所有表
- !tables
-
创建schema
- create schema school;
-
创建表
-
建完表后hbase中也会自动创建对应的表
#创建完的表名和字段名都会自动转成大写,如需小写,需在建表时给表名和字段名前后加双引号。如下:
create table school.teacher(
tno INTEGER NOT NULL PRIMARY KEY,
tname VARCHAR,
age INTEGER
);
-
-
插入/更新数据
- upsert into school.teacher (tno,tname,age) values(1,‘zhangsan’,23);
-
查询插入的数据
- select * from school.teacher;
-
删除数据
- delete from school.teacher where id =1;
-
删除表
- drop table school.teacher;
-
删除schema
- drop schema school;
-
退出
- !quit
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)