大数据学习之路47-hbase的客户端api-DDL操作

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37050372/article/details/81987895

1.hbase的正常运行需要一些什么样的服务?

hdfs,zookeeper。

没有依赖yarn,也没有依赖mapreduce。

不过mapreduce可以访问hbase,mapreduce可以读任何数据。我们写mapreduce就是为了数据分析,我们也可以把hbase当成数据存储。

2.查看命名空间

list_namespace

3.创建命名空间(我们创建列族中的值的时候为列族名:key,所以这里创建命名空间的时候也一样)

命名空间就是表名的前缀

create_namespace 'db1'

4.在命名空间中创建表

create 'db1:t_1','f1'

5.清空一张表

truncate 't_user_info'

6.下面我们来写代码:

注意在获取连接的时候如果我们如果使用new Configuration()则他只会读取classpath下的core-site.xml,core-default.xml,hdfs-site.xml,hdfs-default.xml.而hbase中有hbase-site.xml,这个文件不会被读。所以我们选择HbaseConfiguration().

接下来我们需要让java知道hbase在哪,我们需要配置参数,这个参数就是我们在hbase-site中配置的有关zookeeper的配置。

其他参数可以不配。为什么呢?

因为有了这个参数,他就可以知道zookeeper在哪,知道zookeeper在哪,就可以知道region server在哪。因为所有的region server都在zookeeper上注册了信息。知道region server在哪,就能知道我们对数据进行操作该找谁。因为数据是分配在region server上。

接下来我们尝试创建表,创建表我们需要先拿到表管理器Admin,admin用于进行DDL操作。什么是DDL操作呢?

DDL就是数据定义,比如建表,修改表名,修改表定义。

表管理器在创建表的时候会传表描述器进去。那么什么是表描述器呢?我们如果定义了一个表,表中有很多定义,那么它不会让我们一条一条去写,而是让我们全部封装成一个表描述器对象。

我们new 一个表描述器对象HTableDescriptor还需要传表名进去,但是注意这里传递的表名应该是TableName类型的而不是String.因为这个方法已经被废弃了,被封装成了TableName.我们传值的时候可以通过TableName.valueOf("")的方式传递表名。

此时我们的表描述器只有表名,但是我们建表不仅需要表名还需要列族。 表描述器如果要添加列族,还需要传递列描述器。

为什么这里不直接让我们传递列族的名字,而是让我们传一个列描述器,因为列中还有许多参数可以传。我们可以在建表的时候就设置好。

f1.setMinVersions(1);
f1.setMaxVersions(3);

上面这两个语句的意思是,hbase中可以对一个k,v数据保存最近的N个版本。

比如说uname第一次为zhangsan

第二次我们更新了这条数据uname改为lisi

这些值hbase都会为我们记住。而上面的两条语句的意思就是设置最小能记住多少个,最多能记住多少个。hbase1.2.1默认能记住1个。

下面贴出建表代码:

package com.test.hbase;

import java.io.IOException;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.junit.Before;
import org.junit.Test;

public class HbaseClientDemo {
	 Connection conn=null;
	  @Before
       //获取连接
	   public void init() throws IOException{
		Configuration conf = HBaseConfiguration.create();
		conf.set("hbase.zookeeper.quorum", "marshal:2181,marshal01:2181,marshal02:2181,marshal03:2181,marshal04:2181,marshal05:2181");
		   conn = ConnectionFactory.createConnection(conf);
	   }
	   /**
	    * 建表
	 * @throws IOException 
	    */
	   @Test
	   public void testCreateTable() throws IOException{
		   Admin admin = conn.getAdmin();
		   HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf("t_1"));
		   HColumnDescriptor f1 = new HColumnDescriptor("f1");
		   f1.setMinVersions(1);
		   f1.setMaxVersions(3);
		   hTableDescriptor.addFamily(f1);   
		   admin.createTable(hTableDescriptor);
		   admin.close();
		   conn.close();
	   }
}

注意:这里运行如果junit报错的话,我们可以重新添加library,添加junit环境。

删除表:

我们如果直接使用admin.deleteTable(Table.valueOf("t_1"));的话会报错如下:

org.apache.hadoop.hbase.TableNotDisabledException: t_1

这个错误告诉我们在删除一个表之前需要先将那个表禁用。

贴出代码如下:

 /**
	    * 删除表
	    * @throws IOException
	    */
	   @Test
	   public void testDropTable() throws IOException{
		     Admin admin = conn.getAdmin();
		     admin.disableTable(TableName.valueOf("t_1"));
		     admin.deleteTable(TableName.valueOf("t_1"));
		     admin.close();
		     conn.close();
	   }

修改表:

我们正常的修改思路应该是先查出来再修改。

我们可以修改块的大小,还可以修改布隆过滤器

什么是布隆过滤器?

当集合里面的元素数量足够大,如果有500万条记录甚至1亿条记录呢?这个时候常规的数据结构的问题就凸显出来了。一旦数据量过大,消耗的内存也会呈现线性增长,最终达到瓶颈。普通计算机是无法提供如此大的内存。这个时候,布隆过滤器(Bloom Filter)就应运而生。布隆过滤器原理很简单:就是把一个字符串哈希成一个整数key,然后选取一个很长的比特序列,开始都是0,在key把此位置的0变为1;下次进来一个字符串,哈希之后的值key,如果在此比特位上的值也是1,那么就说明这个字符串存在了。

以上图为例,具体的操作流程:假设集合里面有3个元素{x, y, z},哈希函数的个数为3。首先将位数组进行初始化,将里面每个位都设置位0。对于集合里面的每一个元素,将元素依次通过3个哈希函数进行映射,每次映射都会产生一个哈希值,这个值对应位数组上面的一个点,然后将位数组对应的位置标记为1。查询W元素是否存在集合中的时候,同样的方法将W通过哈希映射到位数组上的3个点。如果3个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。反之,如果3个点都为1,则该元素可能存在集合中。注意:此处不能判断该元素是否一定存在集合中,可能存在一定的误判率。可以从图中可以看到:假设某个元素通过映射对应下标为4,5,6这3个点。虽然这3个点都为1,但是很明显这3个点是不同元素经过哈希得到的位置,因此这种情况说明元素虽然不在集合中,也可能对应的都是1,这是误判率存在的原因。

在计算机这个领域里,我们常常碰到时间换空间或空间换时间的情况,为了达到某一方面的性能,牺牲另外一方面。BloomFilter在时间和空间着两者之间引入了另外一个概念——错误率。也就是前文提到的布隆过滤不能准确判断一个元素是否在集合内(类似的设计还有基数统计法)。引入错误率后,极大的节省了存储空间。

下面贴出代码:

@Test
	   public void testModifyTable() throws IOException{
		      Admin admin = conn.getAdmin();
		      HTableDescriptor tableDescriptor = admin.getTableDescriptor(TableName.valueOf("t_1"));
		     HColumnDescriptor f2 = new  HColumnDescriptor("f2");
		     //块的大小默认为65536也就是64M
		     f2.setBlocksize(131072);
		     f2.setBloomFilterType(BloomType.ROWCOL);
		     tableDescriptor.addFamily(f2);
		     admin.modifyTable(TableName.valueOf("t_1"), tableDescriptor);
		     admin.close();
		     conn.close();
	   }

成功截图:

猜你喜欢

转载自blog.csdn.net/qq_37050372/article/details/81987895