HBase操作

本文深入探讨了HBase客户端API,涵盖Put、Get、Delete操作,扫描器的使用,过滤器机制,以及行级和列族级别的数据修改。此外,还介绍了行锁、批量处理、原子性操作和自定义协处理器,展示了如何通过HTable、Scan、ResultScanner等类进行高效的数据交互。
摘要由CSDN通过智能技术生成

HBase操作

客户端API:基础知识

增删改查

put方法

单行put

void put(Put put) throws IOException

Put对象构造方法:

Put (byte[] row)
Put (byte[] row,RowLock rowLock)
Put (byte[] row,Long ts)
Put (byte[] row,Long ts,RowLock rowLock)

Put类提供的其他方法

getRow()					返回创建Put实例时所指定的行键
getRowLock()				返回当前Put实例的行RowLock实例
getLockId()					返回使用rowLock参数传递给构造函数的可选的锁ID,当为被指定时返回-1
setWriteToWAL()				允许关闭默认启动的服务器端预写日志(WAL)功能
getWriteToWAL()				返回代表是否启用了WAL值
getTimeStamp()				返回相应Put实例的时间戳
heapSize()					计算当前Put实例所需的堆大小
isEmpty()					检测FamilyMap是否含有任何KeyValue实例
numFamilies()				查询FamilyMap的大小
size() 						返回本次Put会添加的KeyValue实例的数量

KeyValue类

提供的比较器

比较器 描述描述
KeyComparator 比较两个KeyValue实例的字节数组格式的行键
KVComparator 是KeyComparator的封装,基于两个给定的KeyValue实例
RowComparator 比较两个KeyValue实例的行键
MetaKeycompartor 比较两个字节数组格式表示的.META.条目的行键
MetaCompartor 比较.META.目录表中的条目,是MetaKeyCompartor的封装
RootKeyCompartor 比较两个字节数组格式表示的-ROOT-条目的行键
RootCompartor 比较-ROOT-目录表中的条目,是RootKeyCompartor的封装

Value实例所有可能的类型值

类型 描述
Put KeyValue实例代表一个普通的Put操作
Delete KeyValue实例代表一个普通的Delete操作
DeleteColumn 与Delete相同,但是会删除一整列
DeleteFamily 与Delete相同,但是会删除整个列族,包括该列族的所有列

客户端的写缓冲区

缓冲区负责收集put操作,然后调用RPC操作一次性将put送往服务器。

void setAutoFlush(boolean autoFlush)
boolean isAutoFlush()

默认情况下,客户端缓冲区是禁用的。可以通过将自动刷写设置为false来激活缓冲区。

table.setAutoFlush(false)

当需要强制把数据写到服务端时,可以调用另外一个API函数。

void flushCommits() throws IOExcepion

用户可以通过以下调用来配置客户端写缓冲区的大小。

long getWriteBufferSize()
void setWriteBufferSize(long writeBufferSize) throws IOException

put列表

客户端API可以插入单个Put实例,同时也有批量处理操作的高级特性。

void put(List<Put> puts) throws IOException

原子性操作

有一种特别的put调用,其能保证自身操作的原子性。可用于保证服务器操作的原子性,

boolean checkAndPut (byte[] row,byte[] family,byte[] qualifier,byte[] value,
	Put put) throws IOException

get方法

单行get

从Hbase表中取一个特定的值

Result get(Get get) throws IOExpection

Get对象构造方法

Get (byte[] row)
Get (byte[] row,RowLock rowlock)

用户获取数据的方法

Get addFamily(byte[] family)					限制get请求只能取得一个指定的列族
Get addColumn(byte[] family,byte[] qualifier)	可以指定某行的数据
Get setTimeRange(long minStamp,long maxStamp)	设定一个时间段来取数据
	throws IOException
Get setTimeStamp(long timestamp)				设定一个时间戳来取数据
Get setMaxVersions()							根据最大版本来获取数据
Get setMaxVersions(int maxVersions)
	throws IOException							根据输入的版本来获取数据

Get类提供的其他方法

getRow()										返回创建Get实例时指定的行键
getRowLock()									返回当前Get实例的RowLock实例
getLockId()										返回创建时指定的rowLock的锁ID,没有则返回-1L
getTimeRange()									返回指定的Get实例的时间戳范围
setFilter()/getFilter()							用户可以根据特定的过滤器实例,来筛选列和单元格
setCacheBlocks()/getCacheBlocks()				控制当次读取的块缓存机制是否奏效
numFamilies()									快捷地获取列族FamilyMap大小的方法
hasFamilier()									检查列族或列是否存在当前的Get实例中
familySet()/getFamilyMap()						让用户直接访问addFamily()和addColumn()添加的族和列
													familySet()方法返回一个所有已存储列族的Set(只													  包含列族)

Bytes对应的把比byte[]的内容转化为Java类型的数据的方法

static String toString(byte[] b)
static booble toBooble(byte[] b)
static long toLong(byte[] b)
static float toFloat(byte[] b)
static int toInt(byte[] b)

一个获取数据的实例

public void getData() throws IOException {
    Configuration conf = HBaseConfiguration.create(); // 创建配置实例
    HTable table = new HTable(conf, "testtable"); // 初始化一个新的表应用
    Get get = new Get(Bytes.toBytes("rowl")); // 使用一个指定的行键构建一个Get实例
    get.addColumn(Bytes.toBytes("colfaml"), Bytes.toBytes("quall")); // 向Get实例中添加一个列
    Result result = table.get(get); // 从HBase中获取指定列的行数据
    byte[] val = result.getValue(Bytes.toBytes("colfaml"), Bytes.toBytes("quall")); // 从返回的结果中获取对应列的数据
    System.out.println("Value" + Bytes.toString(val)); // 将数据转化为字符串打印输出
}

Result类

用户使用get()方法获取数据时,HBase返回的结果包含所有匹配的单元格数据,封装在一个Result实例中返回给用户。

Result类提供的方法

byte[] getValue(byte[] family,byte[] qualifier)		允许用户取得一个HBase中存储的特定单元格的值
byte[] value()										返回第一个列对应的最新单元格的值
byte[] getRow()										返回创建Get类当前实例时使用的行键
int size()											返回服务器端返回值中的键值对数目
boolean isEmpty()									判断是否为空
KeyValue[] raw()									返回原始的底层KeyValue的数据结构
List<KeyValue> list()								把raw()返回的数组转化成一个List实例并返回

面向列的存取函数

List<KeyValue> getColumn(byte[] family,byte[] qualifier)	返回最新版本值
KeyValue getColumnLatest(byte[] family,byte[] qualifier)	返回最新版本值(KeyValue实例)
boolean containsColumn(byte[] family,byte[] qualifier)		检查返回值中是否有对应列

Get列表

用户创建一个列表,并把之前准备好的Get实例添加到其中,然后将这个列表传get(),会返回一个与列表大小相等的Result数组。

Result[] get(List<Get> gets) throws IOException

使用Get实例的列表从HBase中获取数据

public void getData2(HTable table) throws IOException {
    byte[] cf1 = Bytes.toBytes("colfam1");
    byte[] qf1 = Bytes.toBytes("qual1");
    byte[] qf2 = Bytes.toBytes("qual2"); // 准备好公用的字节数组
    byte[] row1 = Bytes.toBytes("row1");
    byte[] row2 = Bytes.toBytes("row2");
    List<Get> gets = new ArrayList<>(); // 准备好要存放Get实例的列表
    Get get1 = new Get(row1);
    get1.addColumn(cf1, qf1);
    gets.add(get1);
    Get get2 = new Get(row2);
    get2.addColumn(cf1, qf1); // 将Get实例添加到列表
    gets.add(get2);
    Get get3 = new Get(row2);
    get3.addColumn(cf1, qf2);
    gets.add(get3);
    Result[] results = table.get(gets); // 从HBase中获取这些行和选定的列
    System.out.println("First iteration...");
    for (Result result : results) {
        String row = Bytes.toString(result.getRow());
        System.out.print("Row:" + row + " ");
        byte[] val = null;
        if (result.containsColumn(cf1, qf1)) { // 遍历结果并检查哪些行中包含选定的列
            val = result.getValue(cf1, qf1);
            System.out.println("Value:" + Bytes.toString(val));
        }
        if (result.containsColumn(cf1, qf2)) {
            val = result.getValue(cf1, qf2);
            System.out.println("Value:" + Bytes.toString(val));
        }
    }
    System.out.println("Second iteration...");
    for (Result result : results) {
        for (KeyValue kv : result.raw()) {
            System.out.println("Row:" + Bytes.toString(kv.getRow()) // 再次遍历,打印所有结果
                    + " Value:" + Bytes.toString(kv.getValue()));
        }
    }
}

获取数据的相关方法

通过RPC验证请求的数据是否存在,但不会从远程服务器返回请求的数据,而是只返回一个布尔值。

boolean exists(Get get) throws IOException

用户在检索数据时可能需要查找一个特定的行。

Result getRowOrBefore(byte[] row,byte[] family) throws IOException

使用特殊检索方法

public void getData3(HTable table) throws IOException {
    Result result1 = table.getRowOrBefore(Bytes.toBytes("row1"), 
            Bytes.toBytes("colfam1")); // 尝试查找已经存在的行
    System.out.println("Found:" + Bytes.toString(result1.getRow())); // 打印查找结果
    Result result2 = table.getRowOrBefore(Bytes.toBytes("row99"), 
            Bytes.toBytes("colfam1")); // 尝试查找不存在的行
    System.out.println("Found:" + Bytes.toString(result2.getRow())); // 返回已排序表中的最后一条结果
    for (KeyValue kv : result2.raw()) {
        System.out.println(" Col:" + Bytes.toString(kv.getFamily()) // 打印返回结果
                + "/" + Bytes.toString(kv.getQualifier()) + ",Value:"
                + Bytes.toString(kv.getValue()));
    }
    Result result3 = table.getRowOrBefore(Bytes.toBytes("abc"), 
            Bytes.toBytes("colfam1")); // 尝试查找测试行之前的一行
    System.out.println("Found:" + result3); // 由于没有匹配的结果,返回null
}

删除方法

单行删除

方法

void delete(Delete delete) throws IOException

Delete类的构造函数

Delete(byte[] row)
Delete(byte[] row,long timestamp,RowLock,rowLock)

提供的方法

Delete deleteFamily(byte[] family)							删除整个列族
Delete deleteFamily(byte[] family,long timestamp)			删除和指定时间戳相匹配的整个列族
Delete deleteColumns(byte[] family,byte[] qualifier)		删除列的所有版本
Delete deleteColumns(byte[] family,byte[] qualifier,long timestamp)
                                                          	删除列的指定时间戳和之前的所有版本
  Delete deleteColumn(byte[] family,byte[] qualifier)		只删除列的最新版本
Delete deleteColumn(byte[] family,byte[] qualifier,long timestamp))		
															只删除列的指定时间戳版本
void setTimestamp(long timestamp)							删除时间戳或必给定时间戳旧的所有版本列族

delete()功能表

方法 无时间戳的删除 有时间戳的删除
none 删除整行,即所有列的版本 删除列族的所有列中与给定时间戳相同或更旧的版本
deleteColumn 只删除给定列的最新版本 只删除与时间戳匹配的版本,没有则不删除
deleteColumns 删除给定列的所有版本 从给定列删除与时间戳相等或更旧的版本
deleteFamily 删除给定列族的所有列(包括版本) 从给定列族删除与时间戳相等或更旧的版本

Delete类的其他方法

getRow()								返回创建Delete实例时指定的行键
getRowLock()							返回当前Delete实例的RowLock实例
getLockId()								返回使用raulk参数创建实例时可选参数ID的值,没有则返回-1
getTimeStamp()							检索Delete实例相关的时间戳
isTmpty()								检查FamilyMap是否含有任何条目,即用户所制定的列或列族
getFamilyMap()							通过用户获取deleteFamily()以及deleteColumn()/
											deleteColumns()添加的要删除的列和列族。返回值以列族名为												键,以列族下要删除的列限定符的列表为键

从HBase中删除数据的应用示例

public void deleteData() throws IOException {
    Delete delete = new Delete(Bytes.toBytes("row1")); // 创建针对特定行的Delete实例
    delete.setTimestamp(1); // 设置时间戳
    delete.deleteColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("qual1"), 1); // 删除一列中的特定版本
    delete.deleteColumns(Bytes.toBytes("colfam2"), Bytes.toBytes("qual1")); // 删除一列中的全部版本
    delete.deleteColumn(Bytes.toBytes("colfam2"), Bytes.toBytes("qual3"), 15); // 删除一列中的给定版本和所有更旧的版本
    delete.deleteFamily(Bytes.toBytes("colfam3")); // 删除整个列族,包括所有的列和版本
    delete.deleteFamily(Bytes.toBytes("colfam3"), 3); // 删除给定列族中所有列的给定版本和所有更旧的版本
    table.delete(delete); // 从HBase表中删除数据
    table.close();
}

Delete列表

需要创建一个包含Delete实例的列表,对其进行配置,并调用下面的方法

void delete(List<Delete> deletes) throws IOException

删除值列表的应用示例

public void deleteData2() throws IOException {
    List<Delete> deletes = new ArrayList<>(); // 创建一个列表,保存Delete实例
    Delete delete1 = new Delete(Bytes.toBytes("row1"));
    delete1.setTimestamp(4); // 为删除行的Delete实例设置时间戳
    deletes.add(delete1);
    Delete delete2 = new Delete(Bytes.toBytes("row2"));
    delete2.deleteColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("qual1")); // 删除一列的最新版本
    delete2.deleteColumns(Bytes.toBytes("colfam2"), Bytes.toBytes("qual3"), 5); // 再另一列中删除给定的版本及所有更旧的版本
    deletes.add(delete2);
    Delete delete3 = new Delete(Bytes.toBytes("row3"));
    delete2.deleteFamily(Bytes.toBytes("colfam1")); // 删除整个列族,包括所有的列和版本
    delete2.deleteFamily(Bytes.toBytes("colfam2"), 3); // 在整个列族中,删除给定的版本以及所有更旧的版本
    deletes.add(delete3);
    table.delete(deletes); // 删除HBase表中的多行
    table.close();
}

原子性操作

用户必须指定行键、列族、列限定符和值来执行删除操作之前的检查。如果检查失败,则不执行删除操作,返回false。如果检查成功,则执行删除操作,返回true。

boolean checkAndDelete(byte[] row, byte[] family, byte[] qualifier, byte[] value, Delete delete) 	throws IOException

使用原子操作compare-and-delete删除值得应用示例

public void deleteData3() throws IOException {
    Delete delete1 = new Delete(Bytes.toBytes("row1"));
    delete1.deleteColumns(Bytes.toBytes("colfam1"), Bytes.toBytes("qual3")); // 创建一个Delete实例
    boolean res1 = table.checkAndDelete(Bytes.toBytes("row1"), Bytes.toBytes("colfam2"), Bytes.toBytes("qual3"), null, delete1); // 检查指定列是否不存在,依检查结果执行删除操作
    System.out.println("Delete successful:" + res1); // 打印结果,应当为”Delete successful:false“
    Delete delete2 = new Delete(Bytes.toBytes("row1"));
    delete2.deleteColumns(Bytes.toBytes("colfam2"), Bytes.toBytes("qual3")); // 手工删除已经检查过的列
    table.delete(delete2);
    boolean res2 = table.checkAndDelete(Bytes.toBytes("row1"), Bytes.toBytes("colfam2"), Bytes.toBytes("qual3"), null, delete1); // 尝试再一次删除同一个单元格
    System.out.println("Delete successful:" + res2); // 打印结果,应当为”Delete successful:true“

    Delete delete3 = new Delete(Bytes.toBytes("row2"));
    delete3.deleteFamily(Bytes.toBytes("colfam1")); // 创建另一个Delete实例,这次使用一个不同的行
    try {
        boolean res4 = table.checkAndDelete(Bytes.toBytes("row1"), Bytes.toBytes("colfam1"), Bytes.toBytes("qual1"), Bytes.toBytes("val1"), delete3); // 检查这个不同的行,并执行删除操作
        System.out.println("Delete successful:" + res4); // 执行不到这里,在此行之前有异常抛出
    } catch (IOException e) {
        System.out.println("Error:" + e);
    }
}

批处理操作

批处理操作方法

void batch(List<Row> actions,Object[] results) throws IOException,InterruptedException
Object[] batch(List<Row> actions) throws IOException,InterruptedException  

使用批处理操作的应用示例

Configuration conf = HBaseConfiguration.create(); // 创建配置实例
HTable table = new HTable(conf, "testtable"); // 初始化一个新的表应用
/**
 * 使用常量,方便重用
 */
private final static byte[] ROW1 = Bytes.toBytes("row1");
private final static byte[] ROW2 = Bytes.toBytes("row2");
private final static byte[] COLFAM1 = Bytes.toBytes("coleam1");
private final static byte[] COLFAM2 = Bytes.toBytes("coleam1");
private final static byte[] QUAL1 = Bytes.toBytes("qual1");
private final static byte[] QUAL2 = Bytes.toBytes("qual2");

public BatchProcessing() throws IOException {
}

public void batchProcessing() {
    List<Row> batch = new ArrayList<>(); // 创建列表存放所有操作
    Put put = new Put(ROW2);
    put.add(COLFAM2, QUAL1, Bytes.toBytes("val5")); // 添加一个Put实例
    batch.add(put);
    Get get1 = new Get(ROW1);
    get1.addColumn(COLFAM1, QUAL1); // 添加一个针对不同行的Get实例
    batch.add(get1);
    Delete delete = new Delete(ROW1);
    delete.deleteColumns(COLFAM1, QUAL2); // 添加一个Delete实例
    batch.add(delete);
    Get get2 = new Get(ROW2);
    get2.addFamily(Bytes.toBytes("BOGUS")); // 添加一个会失败的Get实例
    batch.add(get2);
    Object[] results = new Object[batch.size()]; // 创建一个结果数组
    try {
        table.batch(batch, results);
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (IOException e) {
        System.out.println("Error:" + e); // 打印捕获的异常
    }
    for (int i = 0; i < results.length; i++) {
        System.out.println("Result[" + i + "]:" + results[i]); // 打印所有结果
    }
}

行锁

put()、delete()这样的修改操作是独立执行的,这意味着在一个串行方式的执行中,对于每一行必须保持行级别的操作是原子性的。行锁 可以保证只有一个客户端能获取一行数据相应的锁,同时对该行进行修改。

但两个客户端同时拥有对方要请求的锁,又同时请求对方已拥有的锁时,会发生死锁。所以,非必要不使用行锁。使用时一定要节约占用锁的时间。

加解锁的方法

RowLock lockRow(byte[] row) throws IOException
void unlockRow(RowLock rl) throws IOException

扫描

概述

方法在返回扫描器实例的同时,用户也可以使用它迭代获取数据

ResultScanner getScanner(Scan scan) throws IOException
ResultScanner getScanner(byte[] family) throws IOException
ResultScanner getScanner(byte[] family,byte[] qualifier) throws IOException

Scan类构造器

Scan()
Scan(byte[] startRow,Filter filter)
Scan(byte[] startRow)
Scan(byte[] startRow,byte[] stopRow)

限制Scan实例读取的数据

Scan addFamily(byte[] family)							限制返回数据的列族
Scan addColumn(byte[] family,byte[] qualifier)			限制返回的列

其他方法

Scan setTimeRange(long minStamp,long maxStamp) throws IOException
														设置时间范围
Scan setTimeStamp(long timestamp)						设置时间戳
Scan setMaxVersions()									返回全部版本
Scan setMaxVersions(int maxVersions)					返回特定版本
Scan setStratRow(byte[] stratRow)						限制返回的数据
Scan setStopRow(byte[] stopRow)							限制返回的数据
Scan setFilter(Filter filter)							限制返回的数据
boolean hasFilter()										检查是否已设置过滤器

Scan类的其他方法概览

方法 概述
getStratRow()/getStopRow() 查询当前设定的值
getTimeRange() 检索Get实例指定的时间范围或相关时间戳
getMaxVersions() 返回当前配置下应该从表中获取的每列的版本数
getFilter() 可以使用特定的过滤器实例,通过多种规则来筛选列和单元格
setCacheBlocks()/getCacheBlocks() 能够控制本次读取的块缓存机制是否启效
numFamilies() 快捷的获取FamilyMap大小的方法,包括addFamily()和addColumn()方法添加的列族和列
hasFamilies() 检查是否有添加过列族或列
getFamilies()/setFamilyMap()/getFamilyMap() 让用户直接访问addFamily()和addColumn()添加的列族和列

ResultScanner类

ResultScanner把扫描操作转换为类似的get操作,他将每一行数据封装成一个Result实例,并将Result实例放入一个迭代器中。

ResultScanner的一些方法

Result next() throws IOException				调用单独的Result实例,这个实例代表了下一个可用的行
Result[] next(int nbRows) throws IOException	获取多行数据,数组中每个实例代表唯一的行
void close()									释放资源

使用扫描器获取表中数据

Configuration conf = HBaseConfiguration.create(); // 创建配置实例
HTable table = new HTable(conf, "testtable"); // 初始化一个新的表应用

public ScanClassTest() throws IOException {
}

public void scanTest() throws IOException {
    Scan scan1 = new Scan(); // 创建空的Scanner实例
    ResultScanner scanner1 = table.getScanner(scan1); // 获取一个迭代器访问所有的行
    for (Result res : scanner1) {
        System.out.println(res); // 打印行内容
    }
    scanner1.close(); // 关闭扫描器,释放资源
    Scan scan2 = new Scan();
    scan2.addFamily(Bytes.toBytes("comfam1")); // 只添加一个列族,这样可以禁止获取"colfam2"的数据
    ResultScanner scanner2 = table.getScanner(scan2);
    for (Result res : scanner2) {
        System.out.println(res);
    }
    scanner2.close();
    Scan scan3 = new Scan();
    scan3.addColumn(Bytes.toBytes("colfam1"), Bytes.toBytes("col-5"))
            .addColumn(Bytes.toBytes("colfam2"), Bytes.toBytes("col-33"))
            .setStartRow(Bytes.toBytes("row-10"))
            .setStopRow(Bytes.toBytes("row-20")); // 使用builder模式将详细限制条件添加到Scan中
    ResultScanner scanner3 = table.getScanner(scan3);
    for (Result res : scanner3) {
        System.out.println(res);
    }
    scanner3.close();
}

缓存与批量处理

因缓存默认关闭,所以可以在两个层面打开它

  1. 表:这个表所有扫描实例的缓存都会生效

    void setScannerCaching(int scannerCaching) 设置缓存大小
    int getScannerCaching() 返回当前缓存大小的值

  2. 扫描层面:只会影响当前的扫描实例

    void setCaching(int scannerCaching) 设置缓存大小
    int getCaching() 返回当前缓存大小的值

使用扫描器时超时

public void scannerTimeout() throws IOException {
    Scan scan = new Scan();
    ResultScanner scanner = table.getScanner(scan);
    int scannerTimeout = (int) conf.getLong(HConstants.HBASE_REGIONSERVER_LEASE_PERIOD_KEY, -1); // 得到当前配置的租约超时时间
    try {
        Thread.sleep(scannerTimeout + 5000); // 休眠的时间比租约超时时间再长一点
    } catch (InterruptedException e) {
        // ignore
    }
    while (true) {
        try {
            Result result = scanner.next();
            if (result == null) {
                break;
            }
            System.out.println(result); // 打印行的内容
        } catch (IOException e) {
            e.printStackTrace();
            break;
        }
    }
    scanner.close();
}

批量处理的方法

void setBatch(int batch)
int getBatch()

在扫描中使用缓存和批量参数

public void scan(int caching, int batch) throws IOException {
    final int[] counters = {0, 0};
    AppenderSkeleton appender = new AppenderSkeleton() {
        @Override
        public void close() {
        }

        @Override
        public boolean requiresLayout() {
            return false;
        }

        @Override
        protected void append(LoggingEvent loggingEvent) {
            String msg = loggingEvent.getMessage().toString();
            if (msg != null && msg.contains("Call:next")) {
                counters[0]++;
            }
        }
    };
    Logger log = Logger.getLogger("org.apache,hadoop");
    log.removeAllAppenders();
    log.setAdditivity(false);
    log.addAppender(appender);
    log.setLevel(Level.DEBUG);

    Scan scan = new Scan();
    scan.setCaching(caching); // 设置缓存和批量处理两个参数
    scan.setBatch(batch);
    ResultScanner scanner = table.getScanner(scan);
    for (Result result : scanner) {
        counters[1]++; // 对返回的Result实例计数
    }
    scanner.close();
    System.out.println("Caching:" + caching + ",Batch:" + batch + ",Results" + counters[1] + ",RPCs:" + counters[0]);
}

各种特性

HTable的实用方法

void close()									会刷新所有客户端缓冲的写操作(会隐式调用															flushCache()方法)
byte[] getTableName()							获取表名
Configuration getConfiguration					允许用户访问HTable中使用的配置(且配置立即生效)
HTableDescriptor getTableDescriptor()			访问表的底层结构定义
static boolean isTableEnabled(table)			可以检查表在Zookeeper中是否被调用
byte[][] getStartKeys()					
byte[][] getEndKeys()					
Pair<byte[][],byte[][]> getStartEndKeys()		可以让用户查看当前表的物理分布情况
void clearRegionCache()
HRegionLocation getRegionLocation(row)		
Map<HRegionInfo,HServerAddress> getRegionsInfo()可以帮助用户获取某一行数据的具体位置信息
void prewarmRegionCache(Map<HRegionInfo,HServerAddress> regionMap)
static void setRegionCachePrefetch(table,enable)
static boolean getRegionCachePrefetch(table)	可以先获取一个region的信息表来预热一下region缓存,														也可以把整张表的预取功能打开

Bytes类

提供的其他方法

方法 描述
toStringBinary() 与toString()方法相似
compareTo()/equals() 对两个byte[]进行比较,前者返回比较结果,后者返回布尔值
add()/head()/tail() 连接两个字节数组或者取字节数组头或尾的一部分
binarySearch() 在给定的字节数组中二分查找一个值
incrementBytes() 一个long类型数据转化成的字节数组与long的数据相加并返回字节数组

客户端API:高级特性

过滤器

简介

过滤器层次结构

最底层是Filter接口和FilterBase抽象类,他们实现了过滤器的骨架。用户定义一个所需要的过滤器实例,同时把定义好的过滤器实例传递给Get或Scan实例

setFilter(filter)

比较运算符

操作 描述
LESS 匹配小于设定值的值
LESS_OR_EQUAL 匹配小于等于设定值的值
EQUAL 匹配等于设定值的值
NOT_EQUAL 匹配不等于设定值的值
GREATER_OR_EQUAL 匹配大于等于设定值的值
GREATER 匹配大于设定值的值
NO_OP 排除一切值

比较器

HBase对基于CompareFilter的过滤器提供的比较器

比较器 描述
BinaryComparator 使用Bytes.compareTo()比较当前值与阈值
BinaryPrefixComparator 同上相似,从左端开始前缀匹配
NullComparator 不做匹配,只判断当前值是不是null
BitComparator 通过BitwiseOp类提供的按位与、或、异或操作执行位级比较
RegexStringComparator 根据一个正则表达式,在实例化这个比较器的时候去匹配表中的数据
SubstringComparator 把阈值和表中数据当作String实例,同时通过contains()操作匹配字符串

比较过滤器

用户创建实例时需要一个比较运算符和一个比较器实例。每个比较过滤器的构造方法都有一个从CompareFilter继承来的签名方法

CompareFilter(CompareOp valueCompareOp,WritableByteArrayComparable valueComparator)

类型:

  1. 行过滤器
  2. 列族过滤器
  3. 列名过滤器
  4. 值过滤器
  5. 参考列过滤器

使用过滤器来挑选特定的行

Configuration conf = HBaseConfiguration.create(); // 创建配置实例
HTable table = new HTable(conf, "testtable"); // 初始化一个新的表应用

public FilterTest() throws IOException {
}

public void selectRow() throws IOException {
    Scan scan = new Scan();
    scan.addColumn(Bytes.toBytes("colfam"), Bytes.toBytes("col-0"));
    Filter filter1 = new RowFilter(CompareFilter.CompareOp.LESS_OR_EQUAL
            , new BinaryComparator(Bytes.toBytes("row-22"))); // 创建一个过滤器,指定比较运算符和比较器
    scan.setFilter(filter1);
    ResultScanner scanner1 = table.getScanner(scan);
    for (Result res : scanner1) {
        System.out.println(res);
    }
    scanner1.close();
    Filter filter2 = new RowFilter(CompareFilter.CompareOp.EQUAL
            , new RegexStringComparator(".*-.5")); // 创建另一个过滤器,使用正则表达式来匹配行键
    scan.setFilter(filter2);
    ResultScanner scanner2 = table.getScanner(scan);
    for (Result res : scanner2) {
        System.out.println(res);
    }
    scanner2.close();
    Filter filter3 = new RowFilter(CompareFilter.CompareOp.EQUAL
            , new SubstringComparator("-5")); // 创建第三个过滤器,使用子串匹配方法
    scan.setFilter(filter3);
    ResultScanner scanner3 = table.getScanner(scan);
    for (Result res : scanner3) {
        System.out.println(res);
    }
    scanner3.close();
}

专用过滤器

适用于扫描操作,继承于FilterBase

分类及构造函数:

  1. 单列值过滤器
    SingleColumnValueFilter(byte[] family,byte[] qualifier,CompareOp compareOp,byte[] value)
    SingleColumnValueFilter(byte[] family,byte[] qualifier,CompareOp compareOp
    ,WritableByteArrayComparable comparable)

  2. 单列排除过滤器

  3. 前缀过滤器
    public PrefixFilter(byte[] prefix)

  4. 分页过滤器

  5. 行键过滤器

  6. 首次行键过滤器

  7. 包含结束的过滤器

  8. 时间戳过滤器
    TimestampsFilter(List timestamps)

  9. 列计数过滤器
    ColumnCountGetFilter(int n)

  10. 列分页过滤器
    ColumnPaginationFilter(int limit,int offset)

  11. 列前缀过滤器
    ColumnPrefixFilter(byte[] prefix)

  12. 随机行过滤器
    RandomRowFilter(float chance)

附加过滤器

HBase提供的过滤器可以提供修改、扩展和对返回结果的行为进行控制等功能。一些额外的控制不依赖于这些过滤器本身,但却可以应用在其他过滤器上。可以把自身的功能与其他过滤器加以结合,变成一个有新功能的过滤器。

跳转过滤器

根据另一个过滤器的结果使用跳转过滤器来过滤整行数据

public void skipFilterTest(Table table) throws IOException {
    Filter filter1 = new ValueFilter(CompareFilter.CompareOp.NOT_EQUAL
            , new BinaryComparator(Bytes.toBytes("val-0")));
    Scan scan = new Scan();
    scan.setFilter(filter1); // 添加ValueFilter到第一个扫描中
    ResultScanner scanner1 = table.getScanner(scan);
    for (Result result : scanner1) {
        for (KeyValue kv : result.raw()) {
            System.out.println("KV:" + kv + ",Value:" + Bytes.toString(kv.getValue()));
        }
    }
    scanner1.close();
    
    Filter filter2 = new SkipFilter(filter1);
    scan.setFilter(filter2); // 在第二个扫描中添加一个用SkipFilter装饰过的过滤器
    ResultScanner scanner2 = table.getScanner(scan);
    for (Result result : scanner2) {
        for (KeyValue kv : result.raw()) {
            System.out.println("KV:" + kv + ",Value:" + Bytes.toString(kv.getValue()));
        }
    }
    scanner2.close();
}

全匹配过滤器

与第一个功能类似,不过当一条数据被过滤掉时,他就会直接放弃这次扫描操作。

FilterList

FilterList提供多个过滤器共同限制返回到客户端的结果的功能。

构造方法

FilterList(List<Filter> rowFilters)
FilterList(Operator operator)
FilterList(Operator operator,List<Filter> rowFilters)

添加过滤器的方法

void addFilter(Filter filter)

自定义过滤器

可以通过实现Filter接口或者继承FilterBase类来自定义过滤器

Filter接口的结构如下:

public interface Filter extends Writable {
    public enum ReturnCode{
        INCLUDE,SKIP,NEXT_COL,NEXT_ROW,SEEK_NEXT_USING_HINT
    }
    public void reset();
    public boolean filterRowKey(byte[] buffer,int offset,int length);
    public boolean filterAllRemaining();
    public ReturnCode filterKeyValue(KeyValue v);
    public void filterRow(List<KeyValue> kvs);
    public boolean hasFilterRow();
    public boolean filterRow();
    public KeyValue getNextKeyHint(KeyValue currentKV);
}

其他方法

filterRowKey(byte[] buffer,int offset,int length)	// 使用Filter的实现方法检查行键,用户可以跳过整														行数据以避免以后的处理
filterKeyValue(KeyValue v)							// 如果本行数据没有被之前的方法过滤,那么框架会														调用这个方法检查行中的每个KeyValue实例
filterRow(List<KeyValue> kvs)						// 用户可以访问之前两个方法筛选出来的KeyValue实														例
filterRow()											
reset()												// 在迭代扫描中,为每个新行重置扫描器
filterAllRemaining()								// 返回true时退出操作,返回false时继续执行

计数器

简介

HBase有一种机制:可以将列当作计数器。

否则,要保证操作的原子性就得对一行数据加锁,再对其操作,才能保证原子性

增加值和对计数器产生的作用

值 作用
大于零 按给定值增加计数器中的数值
零 得到计数器当前值
小于零 减少计数器的当前值

单计数器

只能操作一个计数器:用户需要自己设定列,方法由HTable提供。

long incrementColumnValue(byte[] row,byte[] family,byte[] qualifier,long amount) 
	throws IOException
long incrementColumnValue(byte[] row,byte[] family,byte[] qualifier,long amount
	,booleanweiteToWAL) throws IOException

使用单计数器自增方法

public void singleCounter(Configuration conf) throws IOException {
    HTable table = new HTable(conf, "counters");
    long cnt1 = table.incrementColumnValue(Bytes.toBytes("20110101")
            , Bytes.toBytes("daily"), Bytes.toBytes("hits"), 1); // 计数器值加1
    long cnt2 = table.incrementColumnValue(Bytes.toBytes("20110101")
            , Bytes.toBytes("daily"), Bytes.toBytes("hits"), 1); // 第二次给计数器值加1
    long current = table.incrementColumnValue(Bytes.toBytes("20110101")
            , Bytes.toBytes("daily"), Bytes.toBytes("hits"), 0); // 得到计数器当前值
    long cnt3 = table.incrementColumnValue(Bytes.toBytes("20110101")
            , Bytes.toBytes("daily"), Bytes.toBytes("hits"), -1); // 计数器值减1
}

多计数器

使用HTable的increment()方法

Result increment(Increment increment) throws IOException

增加列的方法

Increment addColumn(byte[] family,byte[] qualifier,long amout)

添加在一个时间范围

Increment setTimeRange(long minStamp,long maxStamp) throws IOException

Increment类的其他方法

方法 描述
getRow() 返回创建Increment实例时指定的行键值
getRowLock() 返回当前Increment实例中的RowLock实例
getLockId() 返回构造器中可选参数rowLock的锁ID,默认值-1L
setWriteToWAL() 允许用户禁用本次操作服务端默认的WAL功能
getWriteToWAL() 返回是否在本次操作中启用WAL功能
getTimeRange() 返回与Increment实例相关的时间范围
numFamilies() 便捷的取回FamilyMap()的大小
numColumns() 返回将要被处理的列的条目
hasFamilies() 检查是否有列或列族被添加到这个Increment实例中
familySet()/getFamilyMap() 使用户可以访问addColumn()方法添加的列

协处理器

可以把一部分计算移动到数据的存放端:协处理器

简介

协处理器允许用户在region服务器上运行自己的代码,更准确地说是允许用户执行region级的操作,并且可以使用与RDBMS中触发器类似的功能。

协处理器框架提供了一些类,用户可以通过继承这些类来扩展自己的功能。

  1. observe
    这一类协处理器与触发器类似:回调函数在一些特定事件发生时被执行。
    observe提供了一些设计好的回调函数,每个操作在集群服务器端都可以被调用。
    提供的接口如下所示
    1. RegionObserve:用户可以用这种的处理器处理数据修改事件,它们与表的region联系紧密
    2. MasterObserve:可以被用作管理或DDL类型的操作,这些是集群级事件
    3. WALObserve:提供控制WAL的钩子函数
  2. endpoint
    将用户的自定义操作添加到服务器端。

Coprocessor

所有协处理器的类都必须实现Coprocessor接口,它定义了协处理器的基本约定,并使得框架本身的管理变得容易。

协处理器优先级:系统级协处理器优先于用户级协处理器。

在协处理器的生命周期中,它们由框架管理。Coprocessor接口提供如下两个方法:

void start(CoprocessorEnvironmnt env) throws IOException;	// 开始时调用
void stop(CoprocessorEnvironmnt env) throws IOException;	// 结束时调用

CoprocessorEnvironment接口提供的方法:

方法 说明
String getHBaseVersion() 以字符串的格式返回HBase版本
int getVersion() 返回Coprocessor接口的版本
Coprocessor getInstance() 返回加载的协处理器实例
Coprocessor.Priority getPriority() 返回协处理器的优先级
int getLoadSequence() 协处理器的序号,可以反映执行顺序
HTableInterface getTable(byte[] tableName) 返回与传入的表名参数对应的HTable实例,这允许协处理访问实际的表数据

协处理器加载

从配置中加载

用户通过添加以下配置中的一条或几条到hbase-site.xml文件中来添加协处理器。

<property>
    <name>hbase.coprocessor.region.classer</name>
    <value>coprocessor.RegionObserverExample,coprocessor.AnotherCoprocessor</value>
</property>
<property>
    <name>hbase.coprocessor.master.classer</name>
    <value>coprocessor.MasterObserverExample</value>
</property>
<property>
    <name>hbase.coprocessor.wal.classer</name>
    <value>coprocessor.WALObserverExample,bar.foo.MYWALObserver</value>
</property>

配置项以及他们的作用

属性 协处理器主机 服务类型
hbase.coprocessor.master.classes MasterCoprocessorHost master服务器
hbase.coprocessor.region.classes RegionCoprocessorHost region服务器
hbase.coprocessor.wal.classes WALCoprocessorHost region服务器

从表描述符中加载

针对特定表加载的协处理器只针对这个表的region,同时也只被这些region的region服务器使用。

由于他们是使用表的上下文加载的,所以与配置文件中加载的协处理器更具有针对性。用户需要在表描述符中利用HTableDescriptor.setValue()方法定义他们。

键以COPROCESSOR开头

值符合格式:||

例如:

'COPROCESSOR$1'=> \
	'hdfs://localhost:8020/users/leon/test.jar|coprocessor.Test|SYSTEM'
'COPROCESSOR$2'=> \
	'/Users/laura/test2.jar|coprocessor.AnotherTest|USER'

RegionObserver

RegionObserver是Coprocessor的子类,属于observer协处理器,当一个特定的region级别的操作发生时,它们的钩子函数会被触发。

其操作可以被分为两类:

处理region生命周期事件

简图:

这些observe可以与pending open、open和pending close状态通过钩子链接。每一个钩子都被框架隐式调用。

处理客户端API事件

与生命周期事件相比,所有的客户端API调用都显式地从客户端应用中传输到region服务器。用户可以在这些调用执行前或刚刚执行后拦截他们。

方法 使用
void preGet()/void postGet() 在客户端HTable.get()请求执行之前和之后调用
void prePut()/void postPut() 在客户端HTable.put()请求执行之前和之后调用
void preDelete()/void postDelete() 在客户端HTable.delete()请求执行之前和之后调用
boolean preCheckAndPut()/boolean postCheckAndPut() 在客户端HTable.checkAndPut()请求执行之前和之后调用
boolean preCheckAndDelete()/boolean postCheckAndDelete() 在客户端HTable.checkAnddelete()请求执行之前和之后调用
boolean preExists()/boolean postExists() 在客户端HTable.exists()请求执行之前和之后调用
long preIncrementColumnValue()/long postIncrementColumnValue() 在客户端HTable.incrementColumnValue()请求执行之前和之后调用
void preIncrement()/void postIncrement() 在客户端HTable.increment()请求执行之前和之后调用
void preGetClosestRowDelete()/void postGetClosestRowDelete() 在客户端HTable.getClosestRowdelete()请求执行之前和之后调用
InternalScanner preScannerOpen()/InternalScanner postScannerOpen() 在客户端HTable.getScanner()请求执行之前和之后调用
boolean preScannerNext()/boolean postScannerNext() 在客户端ResultScanner.next()请求执行之前和之后调用
void preScanneClose()/void postScanneClose() 在客户端ResultScanner.close()请求执行之前和之后调用

RegionCoprocessorEnvironment

RegionCoprocessorEnvironment实现了Coprocessor Environment接口

RegionCoprocessorEnvironment提供的方法以及子类方法

方法 描述
HRegion getRegion() 返回监听器监听的region的引用
RegionServerServices getRegionServerServices() 返回共享的RegionServerServices实例

RegionServerServices提供的方法

方法 描述
boolean isStopping() 当region服务器正在停止服务时。返回true
HLog getWAL() 提供访问WAL实例的功能
CompactionRequestor getCompactionRequester() 提供访问共享的CompactionRequestor实例的功能,可以在协处理器内部发起合并
FlushRequester getFlushRequester() 提供访问共享的FlushRequester实例功能,可以用于发起memstore刷写
RegionServerAccounting getRegionServerAccounting() 提供访问共享RegionServerAccounting实例的功能。用户可以利用它得到当前服务进程资源的占用状态
postOpenDeployTasks(Hregion r,CatalogTracker ct,final boolean daughter) 在region服务器内部使用的内部调用
HBaseRpcMetrics getRpcMetrics() 提供访问共享HBaseRpcMetrics实例的功能

ObserveContext

不仅提供访问当前系统环境的入口,同时也添加了一些关键功能用以通知协处理器框架在回调函数完成时需要做什么。

ObserveContext提供的方法

方法 描述
E getEnvironment() 返回当前协处理器环境的引用
void bypass() 使用用户提供的值调用此方法
void complete() 通知框架后续的处理可以被跳过
boolean shouldBypass() 框架内部用来检查标志位
boolean shouldComplete() 框架内部用来检查标志位
void prepare(E env) 使用特定的环境准备上下文
static ObserverContext createAndPrepare(T env,ObserverContext context) 初始化上下文的静态方法

BaseRegionObserve

实现了所有RegionObserve接口的空方法,所以在默认情况下继承这个类的协处理器没有任何功能。用户需要重载方法来实现自己的功能。

检查特殊get请求的region observe

public class RegionObserverExample extends BaseRegionObserver {
    public static final byte[] FIXED_ROW = Bytes.toBytes("@@@GETTIME@@@");

    @Override
    public void preGet(final ObserverContext<RegionCoprocessorEnvironment> e
            , final Get get, final List<KeyValue> results) {
        if (Bytes.equals(get.getRow(), FIXED_ROW)) { // 检查请求的行键是否匹配
            KeyValue kv = new KeyValue(get.getRow()
                    , FIXED_ROW, FIXED_ROW, Bytes.toBytes(System.currentTimeMillis()));
            results.add(kv); // 创建一个特殊的KeyValue实例,只包含服务器的当前时间
        }
    }
}

MasterObserve

MasterCoprocessorEnvironment

MasterCoprocessorEnvironment封装了一个MasterObserve实例,实现了CoprocessorEnvironment接口,提供getTable()之类的方法帮助用户访问数据

MasterCoprocessorEnvironment的非继承方法

方法 说明
MasterServices getMasterServices() 提供可访问的共享MasterServices实例

MasterServices提供的方法

方法 说明
AssignmentManager getAssignmentManager 使用户可以访问AssignmentManager实例
MasterFileSystem getMasterFileSystem() 提供一个与master操作相关的文件系统抽象层
ServerManager getServerManager() 返回ServerManager实例,可以访问服务器状态
ExecutorService getExectorService() 执行服务被master用来调度系统级事件
void checkTableModifiable(byte[] tableName) 检查表是否已经存在以及是否离线(是则可以修改它)

BaseMasterObserve

BaseMasterObserve为接口的每个方法完成了一个空实现。用户直接实现此类不会有任何反馈。

创建新表时创建一个单独的目录

public class MasterObserverExample extends BaseRegionObserver {
    public void postCreateTable(ObserverContext<MasterCoprocessorEnvironment> env
            , HRegionInfo[] regions, boolean sync) throws IOException {
        String tableName = regions[0].getTable().getNameAsString(); // 获取表名
        MasterServices services = env.getEnvironment().getMasterServices();
        MasterFileSystem masterFileSystem = services.getMasterFileSystem(); // 获取可用的服务,同时取得真实文件系统的引用
        FileSystem fileSystem = masterFileSystem.getFileSystem();
        Path blobPath = new Path(tableName + "-blobs"); // 创建新目录用来存储客户端应用的二进制数据
        fileSystem.mkdirs(blobPath);
    }
}

endpoint

CoprocessorProtocol

系统提供了一个实现CoprocessorProtocol协议的接口。通过这个接口可以定义协处理器希望暴露给用户的任意方法。

通过HTable提供的调用方法,使用这个协议可以和协处理器实例之间通信:

public <T extends CoprocessorProtocol> T coprocessorProxy(Class<T> protocol,byte[] row)
public <T extends CoprocessorProtocol,R> Map<byte[],R> coprocessorExec(Class<T> protocol, byte[] 	startKey, byte[] endKey, Batch.Call<T,R> callable)
public <T extends CoprocessorProtocol,R> void coprocessorExec(Class<T> protocol,byte[] startKey, 	byte[] endKey, Batch.Call<T,R> callable,Batch.Callback<R> callback)

BaseEndpointCoprocessor

实现一个endpoint涉及以下两个步骤

  1. 扩展CoprocessorProtocol接口
    设置与新endpoint的通信细节,即定义了客户端与服务端的RPC协议
  2. 扩展BaseEndpointCoprocessor类
    用户必须实现endpoint涉及的方法,包括抽象类BaseEndpointCoprocessor,以及之前定义的endpoint接口

添加一个行和KeyValue的计数方法

public interface RowCountProtocol extends CoprocessorProtocol{
    long getRowCount() thorws IOException;
    long getRowCount(Filter filter)throws IOException;
    long getKeyValueCount() throws IOException;
}

HTablePool

频繁的创建销毁HTable实例是非常耗费资源的。所以应当创建连接池,并反复利用其中的资源。

创建连接池:

HTablePool()
HTablePool(Configuration config,int maxSize)
HTablePool(Configuration config,int maxSize,HTableInterfaceFactory tableFactory)

HTableInterfaceFactory接口

用户可以创建自定义的工厂类,例如,为HTable实例使用特定的配置。

如果用户想自己扩展HTableInterfaceFactory,则必须实现下面两个方法:

HTableInterface createHTableInterface(Configuration config,byte[] tableName)// 用于创建HTable实例
void releaseHTableInterface(HTableInterface table)							// 用于释放实例

可以用如下方法来使用表实例池:

HTableInterface getTable(String tableName)				// 获取实例
HTableInterface getTable(byte[] tableName)				// 获取实例
void putTable(HTableInterface table)					// 放回实例

关闭表实例池中特定表实例的方法:

void closeTablePool(String tableName)
void closeTablePool(byte[] tableName)

连接管理

每个HTable实例都需要建立和远程主机的连接。用户需要创建一个Configuration实例,然后通过客户端API使用这些类。

以两段代码为例:

  1. HTable table1 = new HTable("table1");
    HTable table2 = new HTable("table2");
    
  2. Configuration conf = HBaseConfiguration.create();
    HTable table1 = new HTable(conf, "table1");
    HTable table2 = new HTable(conf, "table2");
    

第一段代码不如第二段代码有效。后者隐式共享HBase客户端API类提供的连接。

共享连接的缺点在于释放,如果用户不显式关闭连接,它将一直存在,直到客户端退出。这样会产生一些问题,最坏的情况是耗尽所有的连接句柄或内存,并导致IO异常。(解决方法:用户显式关闭连接)

客户端API:管理功能

如果用户开发并扩展了HBase的基础实现,则必须满足以下条件:

  1. 在RPC通信两端都必须可用,即在数据发送进程与数据接收进程均可用。
  2. 实现Writable接口,并实现write()与readFields()方法。
  3. 拥有无参的构造函数。

模式定义

在HBase中数据最终会存储在一张表或多张表中,可以控制表中所有列以达到共享表内的某些特性的目的(比如表的列族)

构造函数:

HTableDescriptor();
HTableDescriptor(String name);
HTableDescriptor(byte[] name);
HTableDescriptor(HTableDescriptor desc);

Writable接口

Writable接口有两个必须实现的方法:

void write(DataOutput out) throws IOException;
void readFields(DataInput in) throws IOException;

框架通过调用这两个方法把对象序列化成输出流,通信接收端读取字节流,并将其反序列化成对象。

框架在数据发送端调用write()方法,并序列化对象的字段,同时会在字节流中添加类名以及其他一些信息。

表属性

通过getter和setter方法来设置表的其他属性。

byte[] getName();
String getNameAsString();
void setName(byte[] name);

列族

void addFamily(HColumnDescriptor family);
boolean hasFamily(byte[] c);
HColumnDescriptor[] getColumnFamilies();
HColumnDescriptor getFamily(byte[] column);
HColumnDescriptor removeFamily(byte[] column);

文件大小限制

long getMaxFileSize();
void setMaxFileSize(long maxFileSize);

只读

boolean isReadOnly();
void setReadOnly(boolean readOnly);

memstore刷写大小

long getMenStoreFlushSize();
void setMenStoreFlushSize(long memstoreFlushSize);

延时日志刷写

synchronized boolean isDeferredLogFlush();
void setDeferredLogFlush(boolean isDeferredLogFlush);

其他选项

byte[] getValue(byte[] key);
String getValue(String key);
Map<ImmutableBytesWritable,ImmutableBytesWritable> getValue();
void setValue(byte[] key,byte[] value);
void setValue(String key,String value);
void remove(byte[] key);

列族

定义某一具体列需要列族名与列名合并在一起,以”:“分隔:

family:qualifier

用户创建列族时,可以通过不同的构造函数实现所有属性的设置。

HColumnDescriptor();
HColumnDescriptor(String familyName);
HColumnDescriptor(byte[] familyName);
HColumnDescriptor(HColumnDescriptor desc);
HColumnDescriptor(byte[] familyName,int maxVersions,String compression,boolean inMemory,boolean 	blockCacheEnabled,int timeToLive,String bloomFilter);
HColumnDescriptor(byte[] familyName,int maxVersions,String compression,boolean inMemory,boolean 	blockCacheEnabled,int timeToLive,String bloomFilter,int sc);

通过getter与setter方法设置参数

名字

byte[] getName();
String getNameAsString();

最大版本数

int getMaxVersions();
void setMaxVersions(int maxVersions);

压缩

Compression.Algorithm getCompression();
Compression.Algorithm getCompressionType();
void setCompressionTpye(Compression.Algorithm type);
Compression.Algorithm getCompressionCompression();
Compression.Algorithm getCompressionCompressionType();
void setCompactionCompressionTpye(Compression.Algorithm type);

块大小

synchronized int getBlocksize();
void setBlocksize(int s);

缓存块

boolean isBlockCacheEnabled();
void setBlockCacheEnabled(boolean blockCacheEnabled);

生存期TTL

int getTimeToLive();
void setTimeToLive(int timeToLive);

在内存中

boolean isInMemory();
void setInMemory(boolean inMemory);

布隆过滤器

StoreFile.BloomType getBloomFilterType();
void setBloomFilterType(StoreFile.BloomType bt);

复制范围

int getScope();
void setScope(int scope);

检查列族是否存在的帮助方法

static byte[] isLegalFamilyName(byte[] b);

HBaseAdmin

提供建表、创建列族、检查表是否存在、修改表结构和列族结构和删除表等功能。

基本操作

构造函数

HBaseAdmin(Configuration conf) throws MasterNotRunningException,ZooKeeperConnectionException

实现Abortable接口,实现以下方法

void abort(String why,Throwable e)

获得master的远程对象

HMasterInterface getMaster() throws MasterNotRunningException,ZooKeeperConnectionException

除此之外,还提供以下接口

boolean isMasterRunning()					// 检查master是否在运行
Hconnection getConnection()					// 返回连接实例
Configeration getConnection()				// 创建访问HBaseAdmin实例时使用到的配置实例
close()										// 关闭连接,释放资源

表操作

建表的方法:

void createTable(HtableDescriptor desc)
void createTable(HTableDescriptor desc,byte[] startKey,byte[] endKey,int numRegions)
void createTable(HTableDescriptor desc,byte[][] startKeys)
void createTableAsync(HTableDescriptor desc,byte[][] startKeys)

使用客户端API建表

Configuration conf = HBaseConfiguration.create();
HBaseAdmin admin = new HBaseAdmin(conf); // 创建HBaseAdmin实例
HTableDescriptor testable = new HTableDescriptor(Bytes.toBytes("testatble")); // 创建表描述符
HColumnDescriptor colfam1 = new HColumnDescriptor(Bytes.toBytes("colfam1")); // 添加列族描述符到	表描述符中
testable.addFamily(colfam1);
admin.createTable(testable); // 调用建表方法createTable()
boolean avail = admin.isTableAvailable(Bytes.toBytes("testtable")); // 检查表是否可用
System.out.println("Table available:" + avail);

建表后用户通过以下方法可以获取所有表的列表和已创建表的表描述,或检验该表是否存在

boolean tableExists(String tableName)					// 检查建表是否成功
boolean tableExists(byte[] tableName)					// 检查建表是否成功
HTableDescriptor[] listTables()							// 获取所有已建表描述符对象
HTableDescriptor getTableDescriptor(byte[] tableName)	// 获取某一个已建表的表描述符

删除表

void deleteTable(String tableName)
void deleteTable(byte[] tableName)

在删除表之前,用户需要判断此表是否被禁用

void disableTable(String tableName)
void disableTable(byte[] tableName)
void disableTableAsync(String tableName)
void disableTableAsync(byte[] tableName)

重新启用表

void enableTable(String tableName)
void enableTable(byte[] tableName)
void enableTableAsync(String tableName)
void enableTableAsync(byte[] tableName)

检查表状态

boolean isTableEnabled(String tableName)
boolean isTableEnabled(byte[] tableName)
boolean isTableDisabled(String tableName)
boolean isTableDisabled(byte[] tableName)		// 关心表的逻辑状态
boolean isTableAvailable(String tableName)		// 检查表的物理状态
boolean isTableAvailable(byte[] tableName)

改变表结构

void modifyTable(byte[] tableName,HTableDescriptor htd)

模式操作

与列相关的操作方法集合

void addColumn(String tableName,HColumnDescriptor column)
void addColumn(byte[] tableName,HColumnDescriptor column)
void deleteColumn(String tableName,String columnName)
void deleteColumn(byte[] tableName,byte[] columnName)
void modifyColumn(String tableName,HColumnDescriptor descriptor)
void modifyColumn(byte[] tableName,HColumnDescriptor descriptor)

通过以上的方法,用户可以创建、删除、修改列族。增加和修改操作需要一个HColumnDescriptor实例。

使用getColumnDescriptor()方法可以查询当前表结构,然后调用getColumnFamilies()方法可以查询到所有已存在的列族信息。

集群管理

集群管理允许用户查看集群当前状态,执行表级任务和管理region。

面向高级用户的操作

方法 说明
static void checkHBaseAvailable(Configuration conf) 验证客户端应用是否能与给定文件配置中的远程HBase集群进行通信。成功无返回值,失败抛出异常
ClusterStatus getClusterStatus() 可以通过查询ClusterStatus类的实例返回集群信息
void closeRegion(String regionname,String hostAndPort) 让已经在region服务器中上线的特定region下线
void closeRegion(byte[] regionname,String hostAndPort)
void flush(String tableNameOrRegionName) 将数据刷写到磁盘中
void flush(byte[] tableNameOrRegionName)
void compact(String tableNameOrRegionName) 合并表(异步方法)
void compact(byte[] tableNameOrRegionName)
void majorCompact(String tableNameOrRegionName) 执行major合并
void majorCompact(byte[] tableNameOrRegionName)
void split(String tableNameOrRegionName) 拆分一个region或者拆分整张表
void split(byte[] tableNameOrRegionName)
void split(String tableNameOrRegionName,String splitPoint)
void split(byte[] tableNameOrRegionName,byte[] splitPoint)
void assign(byte[] regionName,boolean force) 操作region上线
void unassign(byte[] regionName,boolean force) 操作region下线
void move(byte[] encodedRegionName,byte[] destServerName) 通过客户端控制某个region在哪台服务器上线
boolean balanceSwitch(boolean b) 控制region的负载均衡算法是否开启
boolean balancer() 主动运行负载均衡算法将每台region服务器上线的region进行均匀再分配
void shutdown() 关闭集群
void stopMaster() 关闭master进程
void stopRegionServer(String hostnamePort) 关闭某台region服务器

集群状态信息

调用HBaseAdmin.getClusterStatus()可以查询CluseterStatus实例,其包含master搜集到的整个集群信息。此类的setter方法修改的是本地副本的变量

CluseterStatus提供信息概览

方法 描述
int getServersSize() 当前存活的region服务器的数量
Collection getServers() 当前存活的region服务器的列表(包括服务、IP、RPC端口等)
int getDeadServers() 当前处于不可用状态的服务器数量
Collection getDeadServerNames() 当前处于不可用状态的服务器列表
double getAverageLoad() 平均每台服务器上上线了多少region
int getRegionsCount() 集群中region的总数量
int getRequestsCount() 集群的请求TPS
String getHBaseVersion() 返回当前集群的软件编译版本
byte[] getVersion() 返回CluseterStatus实例的版本号
String getClusterId() 返回集群的唯一标识
Map<String,regionStare> getRegionsInTransition() 返回当前集群正在进行处理的region的事务列表(移动操作、上下线操作等)
HServerLoad getLoad(ServerName sn) 返回给定region服务器的当前负载状况

用户通过查看集群状态可以在较高层次上看到集群的整体情况。用户查看getServers()方法返回的serverName实例能够获取所有当前处于可用状态的服务器的实际信息。

HSeverName提供信息概览

方法 描述
String getHostname() 返回服务器域名(不可用则返回IP地址)
String getHostAndPort() 返回域名与RPC端口的合并字符串(用:分隔)
long getStartcode() 服务器启动的时间,单位是毫秒
String getServerName() 获取服务器名(是、、 的组合)
int getPort() 返回服务器端的RPC端口

通过提供HSeverName实例,每台region服务器可以提供他们的负载信息。用户调用ClusterStatus实例的getLoad()方法可以获取HServerLoad实例。

HserverLoad不仅提供了服务器本身的信息,还提供了每台服务器管理的region的信息。

HserverLoad提供信息概览

方法 描述
byte getVersion() 返回HServerLoad的版本号,RPC序列化进程时会用该参数
int getLoad() 等同于getNumberOfRegions()的返回值
int getNumberOfRegions() 当前region服务器上线的region数量
int getNumberOfResuests() 返回当前region服务器这个周期内的TPS
int getUsedHeapMB() JVM已使用的内存,单位为MB
int getMaxHeapMB() JVM最大可使用内存,单位为MB
int getStorefiles() 当前region服务器的存储文件数量
int getStorefileSizeInMB() 当前region服务器的存储文件的总存储量,单位为MB
int getStorefileIndexSizeInMB() 当前region服务器的存储文件的索引大小,单位为MB
int getMemStoreSizeInMB() 当前region服务器的已用写缓存大小
Map<byte[],RegionLoad> getRegionsLoad() 当前region服务器中每个region的负载情况,键是region,值是RegionLoad实例

RegionLoad提供信息概览

方法 描述
byte[] getName() 返回region名,以原始的二进制byte数组格式返回
String getNameAsString() 将二进制region名转换为字符串并返回
int getStores() 当前的region的列族数量
int getStorefiles() 当前region的存储文件数量
int getStorefileSizeMB() 当前region的存储文件占用空间,单位为MB
int getStoreIndexfileSizeMB() 当前region的存储文件的索引信息大小,单位为MB
int getMemStoreSizeMB() 当前region使用的MemStore的大小,单位为MB
long getReguestsCount() 当前region的本次统计周期内的TPS
long getReadReguestsCount() 当前region的本次统计周期内的QPS
long getWriteReguestsCount() 当前region的本次统计周期内的WPS

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值