閱讀407 返回首頁    go 汽車大全


HBase學習筆記——基於HBase的日誌係統的性能優化

我之前參與過一個日誌係統的開發,存儲用HBase。我簡單羅列下用到的HBase優化,備忘。以後把它整理成更友好的介紹性文章。

係統簡介

  • 有一張大的日誌數據表,保存所有日誌。row key是 hash + app id + log-severity + timestamp + host等,cell保存日誌正文數據。

    • 可以看到row key的hash保證日誌散列在各個region中,寫入、查詢的負載均衡。但是無法通過它進行範圍查詢,所以為不同查詢模式,建立了多張索引表。
  • 為不同的日誌級別(DEBUG, INFO, WARN, ERROR, FATAL)分別建立了一張索引表。在每張索引表中,row key是 app id + timestamp + host等。也就是說,用於通常選擇一個應用,加上時間範圍,也可以進一步選擇一台應用服務器,來查詢日誌。

表結構相關優化

  • 多條日誌打包,壓縮保存。

    • 我們發現,如果簡單地將一條日誌保存為HBase表中的一行,會導致HBase表記錄數很大,row key數量很大,region數量很多,HBase元數據開銷很大。這會造成HBase集群不穩定。
    • 於是,我們決定將多條日誌打成一個包(chunk)。一個包作為HBase表中的一行保存,大大減少了HBase表的記錄數,減輕了HBase元數據的開銷。打包是通過寫入日誌時,在應用服務器的內存中收集日誌直到字節數超出一定閾值來實現的。
    • 除了打包,壓縮也是在應用服務器端完成的,而不是依靠HBase (column family的compression配置)完成。因為我們希望壓縮不僅能節省HBase存儲空間,還要能節省應用服務器和HBase之間的網絡流量。
    • 打包時,根據row key的語義,正確設置row key。比如開始時間是第一條日誌的開始時間,結束時間是最後一條日誌的結束時間。
    • 時間上相鄰的日誌,其正文內容往往很相似。因此,將多條日誌打包壓縮,比一條一條日誌分開壓縮,能獲得更高的壓縮率,節省網絡傳輸帶寬和存儲。
    • 打包意味著查詢時的解包。為此我們部署了coprocessor在HBase集群中,充分利用HBase集群的CPU解包。
  • fuzzy row filter

    • 通常來說,隻有查詢條件是row key的前綴,這個row key才能被用於查詢。例如如果某張表的row key是 app id + host,則它能被用於根據某個應用id 的日誌查詢, 和 根據應用id + host的查詢。
    • 如果要根據host查詢,上述row key就不行了,不符合前綴匹配。我們得遍曆整個表中所有的row key,對每個row key檢查它是否以查詢條件中給定的host結尾——十分低效。假如有10個應用,每一個應用有100個host,我們隻能遍曆10*100=1000條記錄,找到給定host的記錄。
    • 但是,應用FuzzyRowFilter後,我們仍然可以部分利用這個row key,隻根據host查詢。
      • 雖然row key的首部是app id,導致我們必須遍曆所有app id,但是在掃描一個app id下的所有row key時,通過fuzzy row filter,可以利用row key的**全局分布式索引樹(-ROOT-, .META, region )** 直接跳轉到查詢條件給定的host開始處進行掃描。因此,我們隻需要為每個app id,從查詢條件的host處開始掃描,共100次掃描。

係統配置類優化

  • HBase客戶端優化——犧牲可靠性,提高日誌寫入的吞吐量

    • 關閉WAL,直接寫入日誌。
    • 適當增加writer buffer大小。
    • 批量Put,傳入List;關閉autoFlush。
  • 壓縮算法改用snappy,犧牲壓縮率,降低CPU消耗,提高吞吐量。

  • 調整HFile data block大小。data block越大,索引粒度越粗,順序訪問吞吐量越高。

    • 在一個data block內部,通常隻能順序遍曆,看我們搜索的Key是否存在。但是,也可以啟用bloom filter,很快地告訴我們,一個Key是否一定不在這個data block中。
  • 關閉某些column family的block cache緩存。

    • 查詢時,隻有重複性的、隨機的訪問,才能命中block cache。如果某一個列隻是用於海浪數據的順序訪問,那麼對它緩存沒有意義,相反,它能衝掉block cache本應該緩存的其他列的數據。對於這樣的列, 應該關閉block cache緩存。
  • 日誌歸檔
      * 寫入HBase的日誌,TTL設為7天。HBase用於實時的web查詢,隻能看這7天的日誌。

    • 這個係統有另外一路,實時寫日誌進HDFS,供HIVE分析。這是用於離線查詢7天以前的曆史日誌的。
  • HBase默認存三個版本的cell,對日誌來說沒有必要,隻需要存一個版本。

順便提下與HBase無關的其他優化

  • 通常我們會用**先進先出**的隊列保存臨時積壓的日誌。但是,在日誌係統的場景中,當日誌積壓時,讓用戶看到最新寫入的日誌,比讓用戶看到曆史日誌更重要。因此我們用**先進後出**的棧,保存臨時積壓的日誌。

最後更新:2017-09-21 10:32:46

  上一篇:go  HBase學習筆記——高表與寬表的選擇
  下一篇:go  智能硬件的“送水者”要怎麼做?