1.概述
Apache官方釋出HBase2已經有一段時間了,HBase2中包含了許多個Features,從官方JIRA來看,大約有4500+個ISSUES(檢視地址),從版本上來看是一個非常大的版本了。本篇部落格將為大家介紹HBase2的新特性,以及如何在實戰中與Flink、Kafka等元件進行整合。
2.內容
HBase2有哪些新特性值得我們去關注,這裡給大家列舉部分特定。
2.1 部分新特性預覽
2.1.1 Region分配優化
在HBase中遇到比較頻繁的問題就是RIT問題,而在新特性中,對於Region的管理和分配有了新的調整。AssignmentManager基於ProcedureV2實現,可以快速的分配Region,另外維護Region的State儲存不再依賴Zookeeper,能夠更好的面對Region長時間的RIT問題。
具體參考JIRA單:[HBASE-14614]、[HBASE-17844]、[HBASE-14350]
2.1.2 Offheap優化
在HBase2中減少了對Heap記憶體的使用,改為Offheap記憶體,減少垃圾的產生,以及減少GC的停頓時間。
參考JIRA單:[HBASE-11425]
2.1.3 Compaction優化
在HBase2中,引入了MemStore新的實現類CompactingMemstore,這個類和預設的DefaultMemStore類的區別在於實現了在記憶體中進行Compaction。
CompactingMemstore中,資料是通過Segment作為單位進行組織的,一個MemStore中包含多個Segment。資料最開始寫入時會進入到一個處理Active狀態的Segment中,這個Segment是可以被修改的。當該Active狀態的Segment中的資料達到閥值後,不是直接Flush到HDFS的HFile檔案中,而是先Flush到記憶體中的一個不可修改的Segment中。CompactingMemstore會在後臺將多個不可修改的Segment合併為一個更大、更緊湊的Segment。
如果RegionServer需要把MemStore中的資料Flush到磁碟,會先選擇其他型別的MemStore,然後在選擇CompactingMemstore。這是由於CompactingMemstore對記憶體的管理更加高效,所以延長CompactingMemstore的生命週期可以減少總的I/O。當CompactingMemstore被Flush到磁碟時,不可修改的Segment會被移到一個快照中進行合併,然後寫入HFile。
參考JIRA單:[HBASE-15991]
2.1.4 RegionServer Group
在引入RegionServer Group之前,HBase預設使用StochasticLoadBalancer策略將表的Region移到到RegionServer裡面。在HBase2中,可以將RegionServer劃分到多個邏輯組中,這樣可以提供多租戶的能力。
參考JIRA單:[HBASE-6721]、[HBASE-16430]、[HBASE-17589]、[HBASE-17350]、[HBASE-17349]
2.1.5 Add new AsyncRpcClient
在HBase2中,客戶端請求改為非同步RPC機制,不再是同步Wait,這樣能大大有效的提高客戶端請求的併發量,有效的提高資源利用率。
參考JIRA單:[HBASE-13784]、[HBASE-12684]
3.實戰整合
瞭解了HBase2的一些新特性之後,如何將HBase2運用到實際專案中去,下面將為大家介紹如何將HBase整合到Flink和Kafka中。資料流向如下圖所示:
3.1 基礎環境
整合環境如下所示:
- JDK1.8
- HBase-2.1.1
- Flink-1.7.1
- Kafka-2.1.0
3.1.1 依賴JAR
整合實戰專案,需要依賴的JAR資訊如下:
<dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-connector-kafka-0.11_2.12</artifactId> <version>1.7.1</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-streaming-java_2.12</artifactId> <version>1.7.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-hbase_2.12</artifactId> <version>1.7.1</version> </dependency> <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-core</artifactId> <version>1.7.1</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-common</artifactId> <version>2.7.4</version> </dependency>
建議使用Maven來管理,可以很方便的將上述依賴資訊配置到pom.xml檔案中。
3.2 資料準備
準備資料來源,將資料寫入到Kafka叢集,通過Flink進行消費,進行業務邏輯處理,然後將處理後的結果寫入到HBase進行落地。資料準備的實現程式碼如下:
public class JProducer extends Thread { public static void main(String[] args) { JProducer jproducer = new JProducer(); jproducer.start(); } @Override public void run() { producer(); } private void producer() { Properties props = config(); Producer<String, String> producer = new KafkaProducer<>(props); for (int i = 0; i < 10; i++) { String json = "{\"id\":" + i + ",\"ip\":\"192.168.0." + i + "\",\"date\":" + new Date().toString() + "}"; String k = "key" + i; producer.send(new ProducerRecord<String, String>("flink_topic", k, json)); } producer.close(); } private Properties config() { Properties props = new Properties(); props.put("bootstrap.servers", "dn1:9092,dn2:9092,dn3:9092"); props.put("acks", "1"); props.put("retries", 0); props.put("batch.size", 16384); props.put("linger.ms", 1); props.put("buffer.memory", 33554432); props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); props.put("partitioner.class", "org.smartloli.kafka.connector.flink.producer.TestSimplePartitioner"); return props; } }
通過上述應用程式,將生產的訊息資料寫入到Kafka的Topic中,準備好資料來源。
3.3 處理資料並落地到HBase
使用Flink消費Kafka叢集中剛剛準備好的資料來源,然後進行邏輯處理後,將結果寫入到HBase叢集進行儲存,具體實現程式碼如下:
public class FlinkHBase { private static String zkServer = "dn1,dn2,dn3"; private static String port = "2181"; private static TableName tableName = TableName.valueOf("testflink"); private static final String cf = "ke"; private static final String topic = "flink_topic"; public static void main(String[] args) { final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.enableCheckpointing(1000); env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime); DataStream<String> transction = env.addSource(new FlinkKafkaConsumer010<String>(topic, new SimpleStringSchema(), configByKafka())); transction.rebalance().map(new MapFunction<String, Object>() { private static final long serialVersionUID = 1L; public String map(String value) throws IOException { write2HBase(value); return value; } }).print(); try { env.execute(); } catch (Exception ex) { ex.printStackTrace(); } } public static Properties configByKafka() { Properties props = new Properties(); props.put("bootstrap.servers", "dn1:9092,dn2:9092,dn3:9092"); props.put("group.id", "kv_flink"); props.put("enable.auto.commit", "true"); props.put("auto.commit.interval.ms", "1000"); props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer"); return props; } public static void write2HBase(String value) throws IOException { Configuration config = HBaseConfiguration.create(); config.set("hbase.zookeeper.quorum", zkServer); config.set("hbase.zookeeper.property.clientPort", port); config.setInt("hbase.rpc.timeout", 30000); config.setInt("hbase.client.operation.timeout", 30000); config.setInt("hbase.client.scanner.timeout.period", 30000); Connection connect = ConnectionFactory.createConnection(config); Admin admin = connect.getAdmin(); if (!admin.tableExists(tableName)) { admin.createTable(new HTableDescriptor(tableName).addFamily(new HColumnDescriptor(cf))); } Table table = connect.getTable(tableName); TimeStamp ts = new TimeStamp(new Date()); Date date = ts.getDate(); Put put = new Put(Bytes.toBytes(date.getTime())); put.addColumn(Bytes.toBytes(cf), Bytes.toBytes("test"), Bytes.toBytes(value)); table.put(put); table.close(); connect.close(); } }
將該應用程式提交到Flink叢集,通過Flink消費Kafka叢集中的資料,成功執行該應用程式後,可以到HBase叢集進行驗證,看資料是否有寫入成功。
3.4 資料驗證
進入到HBase叢集,執行hbase shell命令進入到Console介面,然後執行如下命令檢視資料是否有寫入成功:
hbase(main):009:0> scan 'testflink',LIMIT=>2
執行上述命令,結果如下所示:
4.總結
HBase2釋出的新特性很有必要去研究和剖析,對於優化HBase叢集或多或少有些許幫助。通過研究這些新特性,來幫助我們有效的應用到實戰專案中。
5.結束語
這篇部落格就和大家分享到這裡,如果大家在研究學習的過程當中有什麼問題,可以加群進行討論或傳送郵件給我,我會盡我所能為您解答,與君共勉!
另外,博主出書了《Kafka並不難學》,喜歡的朋友或同學, 可以在公告欄那裡點選購買連結購買博主的書進行學習,在此感謝大家的支援。