hbase学习

2020/07/11 19:38
阅读数 202

简介

数据存储模型及关系型数据库的区别

一般都是牺牲一致性, 最终达到最终一致性

HBase 概念

区别

 

基础架构

HBASE 原理和操作

写流程

预写入会写入HLog 里面, 通过HLog 来保证数据不丢失

读流程

模块协作

shell 命令

学会用 help , 可以获取使用说明

比如: help 'status'

# HBase shell中的帮助命令非常强大,使用help获得全部命令的列表,使用help ‘command_name’获得某一个命令的详细信息
help 'status'
# 查询服务器状态
status
# 查看所有表
list
# 创建一个表
create 'FileTable','fileInfo','saveInfo'
# 获得表的描述
describe 'FileTable'
# 添加一个列族
alter 'FileTable', 'cf'
# 删除一个列族
alter 'FileTable', {NAME => 'cf', METHOD => 'delete'}
# 插入数据
put 'FileTable', 'rowkey1','fileInfo:name','file1.txt'
put 'FileTable', 'rowkey1','fileInfo:type','txt'
put 'FileTable', 'rowkey1','fileInfo:size','1024'
put 'FileTable', 'rowkey1','saveInfo:path','/home'
put 'FileTable', 'rowkey1','saveInfo:creator','tom'
put 'FileTable', 'rowkey2','fileInfo:name','file2.jpg'
put 'FileTable', 'rowkey2','fileInfo:type','jpg'
put 'FileTable', 'rowkey2','fileInfo:size','2048'
put 'FileTable', 'rowkey2','saveInfo:path','/home/pic'
put 'FileTable', 'rowkey2','saveInfo:creator','jerry'
# 查询表中有多少行
count 'FileTable'
# 获取一个rowkey的所有数据
get 'FileTable', 'rowkey1'
# 获得一个id,一个列簇(一个列)中的所有数据
get 'FileTable', 'rowkey1', 'fileInfo'
# 查询整表数据
scan 'FileTable'
# 扫描整个列簇
scan 'FileTable', {COLUMN=>'fileInfo'}
# 指定扫描其中的某个列
scan 'FileTable', {COLUMNS=> 'fileInfo:name'}
# 除了列(COLUMNS)修饰词外,HBase还支持Limit(限制查询结果行数),STARTROW(ROWKEY起始行。会先根据这个key定位到region,再向后扫描)、STOPROW(结束行)、TIMERANGE(限定时间戳范围)、VERSIONS(版本数)、和FILTER(按条件过滤行)等。比如我们从RowKey1这个rowkey开始,找下一个行的最新版本
scan 'FileTable', { STARTROW => 'rowkey1', LIMIT=>1, VERSIONS=>1}
# Filter是一个非常强大的修饰词,可以设定一系列条件来进行过滤。比如我们要限制名称为file1.txt
scan 'FileTable', FILTER=>"ValueFilter(=,'name:file1.txt’)"
# FILTER中支持多个过滤条件通过括号、AND和OR的条件组合
scan 'FileTable', FILTER=>"ColumnPrefixFilter('typ') AND ValueFilter ValueFilter(=,'substring:10')"
# 通过delete命令,我们可以删除某个字段,接下来的get就无结果
delete 'FileTable','rowkey1','fileInfo:size'
get 'FileTable','rowkey1','fileInfo:size'
# 删除整行的值
deleteall 'FileTable','rowkey1'
get 'FileTable',’rowkey1'
# 通过enable和disable来启用/禁用这个表,相应的可以通过is_enabled和is_disabled来检查表是否被禁用
is_enabled 'FileTable'
is_disabled 'FileTable'
# 使用exists来检查表是否存在
exists 'FileTable'
# 删除表需要先将表disable
disable 'FileTable'
drop 'FileTable'

 

java api 

过滤器

 

很少会用到自定义过滤器

hbase 优化

以下要注意的,可能很耗性能

cmpact 检查

服务端优化策略

以上的参数都是对调优很有参考价值

常用优化策略

rowkey 不能过长,尽量短

根据需求,设计 宽表还是高表

高表查询性能更好,而 宽表 事务更好

读写优化策略

异步提交可能会丢失数据, 去调WAL也会可能丢失数据。虽然可以提高写效率

协处理器

协处理器还是有风险,搞不好就会影响稳定性

协处理器代码加载到HBASE 中

 

容灾与监控

备份与恢复

即将 某个表的数据复制到 另一个表里面

将CoprocessorTest 表数据 到出到 HDFS的  coprocessorTest.db 里面

 

监控

JMX监控

查看hadoop jms   比如  http://192.168.0.205:50070/jmx

然后就可以自己写一个项目, 使用 http 请求 来 定时获取 hadoop 上面的  jmx 信息了,这样就可以获取监控信息了

package com.imooc.bigdata.hbase.monitor;

import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import com.imooc.bigdata.hbase.monitor.entity.DataNodeInfo;
import com.imooc.bigdata.hbase.monitor.entity.HdfsSummary;

/**
 * Created by jixin on 18-3-24.
 */
public class HadoopUtil {

  public static long mbLength = 1048576L;
  public static long gbLength = 1073741824L;
  public static final String hadoopJmxServerUrl = "http://localhost:50070";
  public static final String jmxServerUrlFormat = "%s/jmx?qry=%s";
  public static final String nameNodeInfo = "Hadoop:service=NameNode,name=NameNodeInfo";
  public static final String fsNameSystemState = "Hadoop:service=NameNode,"
      + "name=FSNamesystemState";

  public static HdfsSummary getHdfsSummary(StatefulHttpClient client) throws IOException {
    HdfsSummary hdfsSummary = new HdfsSummary();
    String namenodeUrl = String.format(jmxServerUrlFormat, hadoopJmxServerUrl, nameNodeInfo);
    MonitorMetrics monitorMetrics = client.get(MonitorMetrics.class, namenodeUrl, null, null);
    hdfsSummary.setTotal(doubleFormat(monitorMetrics.getMetricsValue("Total"), gbLength));
    hdfsSummary.setDfsFree(doubleFormat(monitorMetrics.getMetricsValue("Free"), gbLength));
    hdfsSummary
        .setDfsUsed(doubleFormat(monitorMetrics.getMetricsValue("Used"), gbLength));
    hdfsSummary.setPercentUsed(
        doubleFormat(monitorMetrics.getMetricsValue("PercentUsed")));
    hdfsSummary.setSafeMode(monitorMetrics.getMetricsValue("Safemode").toString());
    hdfsSummary.setNonDfsUsed(
        doubleFormat(monitorMetrics.getMetricsValue("NonDfsUsedSpace"), gbLength));
    hdfsSummary.setBlockPoolUsedSpace(
        doubleFormat(monitorMetrics.getMetricsValue("BlockPoolUsedSpace"),
            gbLength));
    hdfsSummary
        .setPercentBlockPoolUsed(
            doubleFormat(monitorMetrics.getMetricsValue("PercentBlockPoolUsed")));
    hdfsSummary.setPercentRemaining(
        doubleFormat(monitorMetrics.getMetricsValue("PercentRemaining")));
    hdfsSummary.setTotalBlocks((int) monitorMetrics.getMetricsValue("TotalBlocks"));
    hdfsSummary.setTotalFiles((int) monitorMetrics.getMetricsValue("TotalFiles"));
    hdfsSummary.setMissingBlocks((int) monitorMetrics.getMetricsValue("NumberOfMissingBlocks"));
    String liveNodesJson = monitorMetrics.getMetricsValue("LiveNodes").toString();
    String deadNodesJson = monitorMetrics.getMetricsValue("DeadNodes").toString();
    List<DataNodeInfo> liveNodes = dataNodeInfoReader(liveNodesJson);
    List<DataNodeInfo> deadNodes = dataNodeInfoReader(deadNodesJson);
    hdfsSummary.setLiveDataNodeInfos(liveNodes);
    hdfsSummary.setDeadDataNodeInfos(deadNodes);

    String fsNameSystemStateUrl = String
        .format(jmxServerUrlFormat, hadoopJmxServerUrl,
            fsNameSystemState);
    MonitorMetrics hadoopMetrics = client
        .get(MonitorMetrics.class, fsNameSystemStateUrl, null, null);
    hdfsSummary.setNumLiveDataNodes((int) hadoopMetrics.getMetricsValue("NumLiveDataNodes"));
    hdfsSummary.setNumDeadDataNodes((int) hadoopMetrics.getMetricsValue("NumDeadDataNodes"));
    hdfsSummary
        .setVolumeFailuresTotal((int) hadoopMetrics.getMetricsValue("VolumeFailuresTotal"));
    return hdfsSummary;
  }

  public static List<DataNodeInfo> dataNodeInfoReader(String jsonData) throws IOException {
    List<DataNodeInfo> dataNodeInfos = new ArrayList<DataNodeInfo>();
    Map<String, Object> nodes = JsonUtil.fromJsonMap(String.class, Object.class, jsonData);
    for (Entry<String, Object> node : nodes.entrySet()) {
      Map<String, Object> info = (HashMap<String, Object>) node.getValue();
      String nodeName = node.getKey().split(":")[0];
      DataNodeInfo dataNodeInfo = new DataNodeInfo();
      dataNodeInfo.setNodeName(nodeName);
      dataNodeInfo.setNodeAddr(info.get("infoAddr").toString().split(":")[0]);
      dataNodeInfo.setLastContact((int) info.get("lastContact"));
      dataNodeInfo.setUsedSpace(doubleFormat(info.get("usedSpace"), gbLength));
      dataNodeInfo.setAdminState(info.get("adminState").toString());
      dataNodeInfo
          .setNonDfsUsedSpace(doubleFormat(info.get("nonDfsUsedSpace"), gbLength));
      dataNodeInfo.setCapacity(doubleFormat(info.get("capacity"), gbLength));
      dataNodeInfo.setNumBlocks((int) info.get("numBlocks"));
      dataNodeInfo.setRemaining(doubleFormat(info.get("remaining"), gbLength));
      dataNodeInfo
          .setBlockPoolUsed(doubleFormat(info.get("blockPoolUsed"), gbLength));
      dataNodeInfo.setBlockPoolUsedPerent(doubleFormat(info.get("blockPoolUsedPercent")));
      dataNodeInfos.add(dataNodeInfo);
    }
    return dataNodeInfos;
  }

  public static DecimalFormat df = new DecimalFormat("#.##");

  public static double doubleFormat(Object num, long unit) {
    double result = Double.parseDouble(String.valueOf(num)) / unit;
    return Double.parseDouble(df.format(result));
  }

  public static double doubleFormat(Object num) {
    double result = Double.parseDouble(String.valueOf(num));
    return Double.parseDouble(df.format(result));
  }
}








public class DataNodeInfo {
  //datanode的hostname
  private String nodeName;
  //datanode的ip地址
  private String nodeAddr;
  //datanode的上次链接数量
  private int lastContact;
  //datanode上hdfs的已用空间 GB
  private double usedSpace;
  //datanode的状态
  private String adminState;
  //datanode上非hdfs的空间大小 GB
  private double nonDfsUsedSpace;
  //datanode上的总空间大小
  private double capacity;
  //datanode的block
  private int numBlocks;
  private double remaining;
  private double blockPoolUsed;
  private double blockPoolUsedPerent;








public class HdfsSummary {

  //"name": "Hadoop:service=NameNode,name=NameNodeInfo"
  //总空间大小 GB
  private double total;
  //hdfs已使用的空间大小 GB
  private double dfsUsed;
  //hdfs已使用空间百分比
  private double percentUsed;
  //hdfs空闲空间 GB
  private double dfsFree;
  //hdfs是否处于safemode
  private String safeMode;
  //非hdfs空间大小 GB
  private double nonDfsUsed;
  //集群该namespace的hdfs使用容量大小
  private double blockPoolUsedSpace;
  //集群该namespace的hdfs使用容量所占百分比
  private double percentBlockPoolUsed;
  private double percentRemaining;
  //集群总的block数
  private int totalBlocks;
  //集群总的文件数
  private int totalFiles;
  //集群丢失的block数量
  private int missingBlocks;
  //处于可用状态的datanode汇总
  private List<DataNodeInfo> liveDataNodeInfos;
  //处于不可用状态的datanode汇总
  private List<DataNodeInfo> deadDataNodeInfos;
  //"name": "Hadoop:service=NameNode,name=FSNamesystemState"
  //处于可用状态的datanode数量
  private int numLiveDataNodes;
  //处于不可用状态的datanode数量
  private int numDeadDataNodes;
  //坏盘的数量
  private int volumeFailuresTotal;







Phoenix

 

安装 使用

http://phoenix.apache.org/

启动 在 phoenix 下 bin  ,  ./sqlline.py

 这样可以 在 shell 下使用或者 通过API去使用

比如 phonenix + mybatis 一起来使用

 

hbase 适合的业务需求: Object stroe on Habse

也可以 将hbase 作为 对象存储, l 类似 比如 阿里的 OSS   , Amazon S3

开源的对象存储服务 : MINIO 

hbse 的不足

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部