92
7
如你所见,我们所指定的参数已经列在输出中了,当然同时列出的还有默认的参
数。默认参数由于你所使用的
HBase
版本的不同可能会有不同。不过
BLLOMFILTER
DATA_BLOCK_ENCODING
COMMPRESSION
需要按照我们指定的值来配置。
既然我们的表已经准备好了,可以进一步开始着手准备数据了。
数据转换
为了实现并测试我们所描述的用例,我们需要将数据导入到系统中。因此,需要产
生一些测试数据以便后续的处理和转换操作。
生成测试数据
下一步我们的目的是产生一个具有代表性的测试数据集,使用对应用程序来处理该
数据集并检验结果。首先,我们将会创建一些带有测试值的数据文件,在此基础
上,你可以运行不同的命令和程序。
在这个例子中,你将会发现一个叫做
CSVGenerator
的类,它所产生的数据类似下面
这样:
1b87,58f67b33-5264-456e-938a-9d2e9c5f4db8,ALERT,NE-565,0-0000-000,1,ECEGYFFL ...
3244,350cee9e-55fc-409d-b389-6780a8af9e76,RETURNED,NE-382,0-0000-000,1,OOQTY ...
727d,b97df483-f0bd-4f24-8ff3-6988d8eff88c,ALERT,NE-858,0-0000-000,1,MSWOCQXM ...
53d4,d8c39bf8-6f5f-4311-8ee5-9d3bce3e18d7,RETURNED,NE-881,0-0000-000,1,PMKMW ...
1fa8,4a0bf5b3-680d-4b87-8d9e-e55f06614ae4,ALERT,NE-523,0-0000-000,1,IYIZSHKA ...
每一行包含一个随机的且是由四个字符(
0
65535
,十六进制表示)组成的
sensor
ID
,之后是一个随机的
event ID
document type
part name
part number
version
和由随机字母(
664
128
个字符长度)组成的
payload
。想要产生不同的数据集,你
可以在任何你想要的时候重新运行
CSVGenerator
代码。后续部分的示例代码将会从
~/ahae/resources/ch07
文件夹中读取文件。这个类创建文件和它在哪里运行有关系,
因此我们需要在
~/
ahae
文件夹下运行这个类。如果你想增加或者减少数据集的大
小,很简单,只需要更新下面这一行:
for (int index = 0; index < 1000000; index++) {
你可以直接在
eclipse
中运行这个数据产生器而不需要任何参数,或者在
shell
中的
~/ahae
目录下使用如下命令:
HBase -classpath
~
/ahae/target/ahae.jar com.architecting.ch07.CSVGenerator
底层存储引擎的实现
93
此命令将会在
~/ahae/resources/ch07/omneo.csv
中产生一个叫做
omneo.csv
的文件。
创建
Avro
文件格式
现在已经有了一些数据,我们需要定义一个能够映射该数据格式的
Avro
文件结构。
根据在之前章节所提供的查找模式,我们需要如下格式的
Avro
文件结构:
{ "namespace": "com.architecting.ch07",
"type": "record",
"name": "Event",
"fields": [
{"name": "id", "type": "string"},
{"name": "eventid", "type": "string"},
{"name": "docType", "type": "string"},
{"name": "partName", "type": "string"},
{"name": "partNumber", "type": "string"},
{"name": "version", "type": "long"},
{"name": "payload", "type": "string"}
]
}
你可以发现,
omneo.avsc
文件就是采用了这种结构,此文件在
resources/ch07
目录
中。因为它已经被编译并导入工程中,因此不需要重新编译。但是如果你想修改
它,你可以使用如下命令编译它:
java -jar
~
/ahae/lib/avro-tools-1.7.7.jar compile schema omneo.avsc
~
/ahae/src/
此命令将创建一个包含
Event
对象的文件,即
~/ahae/src/com/architecting/ch07/Event.
java
,它将被用来存储
Event
Avro
对象至
HBase
中。
实现
MapReduce
的转换
正如例
7-1
所示,生产处理的第一步是解析收到的
CSV
文件来产生
HBase
HFile
,这
些文件将作为下一步的输入,它们会对应之前已创建的表的格式。
我们的生产数据将是非常巨大的文件,因此将使用
MapReduce
来实现,以充分利用
并行的优势。这个
MapReduce
作业的输入将是
text file
,而输出则是
HFile
。这决定了
你配置
MapReduce
作业的方式。
7-1
:转换成
HFile
Table table = connection.getTable(tableName);
Job job = Job.getInstance(conf, "ConvertToHFiles: Convert CSV to HFiles");
HFileOutputFormat2.configureIncrementalLoad(job, table,
connection.getRegionLocator(tableName));
job.setInputFormatClass(TextInputFormat.class);
94
7
job.setJarByClass(ConvertToHFiles.class);
job.setJar("/home/cloudera/ahae/target/ahae.jar");
job.setMapperClass(ConvertToHFilesMapper.class);
job.setMapOutputKeyClass(ImmutableBytesWritable.class);
job.setMapOutputValueClass(KeyValue.class);
FileInputFormat.setInputPaths(job, inputPath);
HFileOutputFormat2.setOutputPath(job, new Path(outputPath));
❶
HBase
提供了一个帮助类来帮助你完成大多数配置。当你想配置你的
MapReduce
作业来产生
HFile
作为输出时,这是第一步需要调用的。
❷
这里我们想读取一个带有
CSV
数据的
text file
,因此将使用
TextInputFormat
❸
当从命令行运行的时候,所有需要用到的类都绑定到了一个客户端
JAR
上,它
setJarByClass
方法指定。而如果从
eclipse
运行的话,就必须手动指定
JAR
径,因为我们运行的类来自
Eclipse
环境,而
MapReduce
是不知道的。鉴于此,
我们需要向
MapReduce
提供外部文件的路径,当然此路径中的类必须是可用
的。
❹
定义你用来解析
CSV
内容并创建
Avro
输出想要使用的
mapper
❺
我们需要定义
ImmutableBytesWritable
作为
mapper
输出
key
的类。这将是我们
用来写
key
的格式。
❻
我们需要定义
KeyValue
作为
mapper
输出
value
的类。这代表着我们想要存入
HFile
的数据。
用来创建
HFile
reducer
在能够将单行数据的所有列写入
HFile
之前,需要将它
们加载至内存并排序。如果你的数据集中有非常多的列,有可能内存溢出,这
个问题将在未来的某个版本中修复,
HBASE-13897
中将会实现。
Mapper
端的操作非常简单。目的只是将一行分割成不同的部分,将它们分配给一个
Avro
对象,并将这个
Avro
对象存储在
HFile
文件中,随时加载至
HBase
框架中。
正如例
7-2
所示,首先要做的是定义一系列的变量,我们将在每个
mapper
的每一次迭
代中重用这些变量。这么做是为了减少创建对象的数量。
底层存储引擎的实现
95
7-2
:转换成
HFile
mapper
public static final ByteArrayOutputStream out = new ByteArrayOutputStream();
public static final DatumWriter<Event> writer = new SpecificDatumWriter<Event>
(Event.getClassSchema());
public static final BinaryEncoder encoder = encoderFactory.binaryEncoder(out,null);
public static final Event event = new Event();
public static final ImmutableBytesWritable rowKey = new ImmutableBytesWritable();
这些对象全部在例
7-3
中的
map
方法中被重用。
7-3
:转换成
HFile
mapper
//
从接收的行中提取不同的字段
String[] line = value.toString().split(",");
event.setId(line[0]);
event.setEventId(line[1]);
event.setDocType(line[2]);
event.setPartName(line[3]);
event.setPartNumber(line[4]);
event.setVersion(Long.parseLong(line[5]));
event.setPayload(line[6]);
//
序列化
AVRO
对象为
ByteArray
字节数组
out.reset();
writer.write(event, encoder);
encoder.flush();
byte[] rowKeyBytes = DigestUtils.md5(line[0]);
rowKey.set(rowKeyBytes);
context.getCounter("Convert", line[2]).increment(1);
KeyValue kv = new KeyValue(rowKeyBytes,
CF,
Bytes.toBytes(line[1]),
out.toByteArray());
context.write (rowKey, kv);
❶
首先,我们将一列分割成几部分,这样就能够直接地单独处理每部分。
❷
我们为所有的
map
调用重用同样的对象,只是简单的分配给它新接收的值,而
不是在每次迭代时创建一个新的
Avro
对象。
❸
这是对象重用的另一个例子。在你的
mapper
代码中创建的对象越少,你需要的
垃圾回收就越少,并且你的程序执行就越快。每个输入文件的每一行都会调用
map
方法。创建一个
ByteArrayOutputStream
并针对每个
map
迭代重用它和它的
内部缓存,将会节省数百万计的对象创建。
96
7
❹
序列化
Avro
对象,并将其转换为
HBase
可接受的字节数组,尽可能的重用已存
在的对象。
❺
利用
sensor ID
构造
HBase
key
❻
利用我们的
key
和列族构造
HBase
keyvalue
。我们将
event ID
作为列限定符,
Avro
对象作为值(
value
)。
❼
分发
keyvalue
对象,这样
reducer
就可以重组它们并写入需要的
HFile
中。行键
row key
)只被用来分割数据。当数据将被写入基础文件时,只有
KeyValue
据会被同时用作
key
value
当实现一个
MapReduce
作业时,在不必要的时候避免创建对象。如果你需要使
用一个字符串的一小部分,不推荐使用
split()
方法来提取所需部分。在一个
包含一千万字符串,每个字符串由
50
个部分组成的数据集上,使用
split()
法将会产生
5
亿个对象,它们都需要垃圾回收。相反,解析字符串来找到所需
要的那部分的位置并使用
substring()
方法。同时也可考虑使用来自
Guava
库的
com.google.common.base.Splitter
对象。
这个例子可以直接在
Eclipse
中运行,也可以在命令行中执行。无论在哪里执行,
你都需要指定输入文件,输出目录和表名称作为参数。表名称是必需的,
HBase
它来找到
region
的边界以便在输出数据中创建所需的分区。同时,也可用来查找对
应的列族参数,比如压缩算法以及编码格式等参数。
MapReduce
作业将会根据表的
region
和列族参数在输出目录中产生
HFile
接下来的命令将会在
HDFS
上创建
HFile
(假如你在
standalone
模式下运行,你需要在
本地磁盘上产生这些文件,只需更新目标文件夹即可):
HBase -classpath
~
/ahae/target/ahae.jar:`HBase classpath` \
com.architecting.ch09.ConvertToHFiles \
file:///home/cloudera/ahae/resources/ch09/omneo.csv \
hdfs://localhost/user/cloudera/ch09/hfiles/ sensors
❶
调用转换类。
❷
我们的输入文件。
❸
输出文件夹及表名称。

Get HBase应用架构 now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.