HBase 是建立在 HDFS 之上的分布式、面向列的開源 NoSQL 資料庫,適合海量非結構化/半結構化資料存儲,支援單行事務、RowKey 範圍掃描,橫向擴展能力強。
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>0.96.2-hadoop2</version>
</dependency>
<configuration>
<property><name>hbase.zookeeper.quorum</name><value>zk1,zk2,zk3</value></property>
<property><name>hbase.zookeeper.property.clientPort</name><value>2181</value></property>
<!-- 其他調優參數略 -->
</configuration>
<beans xmlns:hdp="https://www.springframework.org/schema/hadoop" ...>
<hdp:configuration id="hadoopConfiguration" resources="classpath:spring/hbase-site.xml" />
<hdp:hbase-configuration id="hbaseConfiguration" configuration-ref="hadoopConfiguration" />
<bean id="htemplate" class="org.springframework.data.hadoop.hbase.HbaseTemplate">
<property name="configuration" ref="hbaseConfiguration" />
</bean>
<bean id="hbaseDao" class="com.example.HbaseDaoImpl">
<constructor-arg ref="htemplate" />
</bean>
</beans>
作者建議優先使用原生 HConnection/HTable,因 HbaseTemplate 每次操作可能重新連接 ZooKeeper,效能較差。下方同時展示兩種寫法。
public void writeDataOrderinfo(OrderInfo orderInfo) {
HTableInterface table = null;
try {
table = hconnection.getTable(Bytes.toBytes("prism:orderInfo"));
Put put = new Put(Bytes.toBytes(orderInfo.getHistoryId()));
put.add(Bytes.toBytes("f"), Bytes.toBytes("id"), Bytes.toBytes(orderInfo.getId()));
// ... 其他欄位
table.put(put);
} catch (IOException e) { throw new RuntimeException(e); }
finally { closeQuietly(table); }
}
public OrderInfo getOrderInfoByRowkey(String rowKey) {
Get get = new Get(Bytes.toBytes(rowKey));
Scan scan = new Scan(get);
List<OrderInfo> list = hbaseTemplate.find("prism:orderInfo", scan, (result, rowNum) -> {
OrderInfo o = new OrderInfo();
o.setId(Bytes.toString(result.getValue(Bytes.toBytes("f"), Bytes.toBytes("id"))));
// ...
return o;
});
return list.isEmpty() ? null : list.get(0);
}
public List<OrderInfo> getOrderInfoByRange(String start, String stop) {
Scan scan = new Scan();
scan.setStartRow(Bytes.toBytes(start));
scan.setStopRow(Bytes.toBytes(stop));
// 使用原生 Scanner 避免模板限制
try (ResultScanner rs = hconnection.getTable(Bytes.toBytes("prism:orderInfo")).getScanner(scan)) {
return rs.stream().map(this::mapRow).collect(Collectors.toList());
} catch (IOException e) { throw new RuntimeException(e); }
}
HConnection 為線程安全、重量級物件,應用程式應建立單例並共用。HTableInterface 非線程安全,每次操作獲取後用完關閉。ConnectionFactory.createConnection(config) (HBase 1.0+ API) 替代已棄用的 HConnectionManager。Spring 整合 HBase 核心在於配置 HbaseTemplate 與 HConnection。實務上推薦直接操作原生 API 以獲得更好效能與控制力。