主頁 > 後端開發 > 一篇文章帶你入門HBase

一篇文章帶你入門HBase

2023-06-13 07:41:06 後端開發

本文已收錄至Github,推薦閱讀 ?? Java隨想錄

微信公眾號:Java隨想錄

目錄
  • HBase特性
  • Hadoop的限制
  • 基本概念
    • NameSpace
    • Table
    • RowKey
    • Column
    • TimeStamp
    • Cell
  • 存盤結構
  • HBase 資料訪問形式
  • 架構體系
  • HBase組件
  • HBase讀寫流程
    • 讀流程
    • 寫流程
  • MemStore Flush
    • 引數說明
  • StoreFile Compaction
    • 引數說明
    • 觸發程序
  • Region Split
    • 預磁區
  • HBase優化
    • 查詢優化
      • 設定Scan快取
      • 顯示指定列
      • 禁用塊快取
    • 寫入優化
      • 設定AutoFlush
    • 引數優化
      • Zookeeper 會話超時時間
      • 設定 RPC 監聽數量
      • 手動控制 Major Compaction
      • 優化 HStore 檔案大小
      • 優化 HBase 客戶端快取
      • 指定 scan.next 掃描 HBase 所獲取的行數
  • SpringBoot中使用HBase
    • Scan
  • Phoenix

HBase(Hadoop Database)是一個開源的、分布式的、面向列的NoSQL資料庫,它是構建在Hadoop之上的,HBase旨在提供可靠的、高性能的、可擴展的存盤和訪問大規模資料集的能力,

HBase特性

以下是HBase的一些關鍵特性和概念:

  1. 分布式架構:HBase是一個分布式資料庫,它可以在一個集群中運行在多個機器上,資料以水平分片的方式分布在不同的機器上,這樣可以實作資料的高可用性和橫向擴展性,
  2. 列存盤:HBase是面向列的資料庫,它將資料存盤在表中的列族中,每個列族可以包含多個列,這樣可以方便地存盤和檢索具有不同結構的資料,HBase的列存盤特性使得可以高效地讀取和寫入大量資料,
  3. 強一致性:HBase提供強一致性的讀寫操作,當資料被寫入或讀取時,HBase會確保所有相關的副本都是最新的,這使得HBase非常適合需要強一致性的應用場景,如金融、電信等領域,
  4. 高可擴展性:HBase可以輕松地擴展到大規模的資料集和集群,通過添加更多的機器和分片資料,可以線性地擴展存盤容量和吞吐量,
  5. 快速讀寫:HBase是為了高性能而設計的,它使用了記憶體和硬碟的組合來存盤資料,可以實作快速的讀寫操作,此外,HBase還支持批量寫入和異步寫入,進一步提高了寫入性能,
  6. 靈活的資料模型:HBase提供了靈活的資料模型,可以根據應用程式的需求設計表結構,它支持動態添加列,并且可以高效地執行范圍查詢和單行讀寫操作,
  7. 資料一致性:HBase通過使用ZooKeeper來管理集群的元資料和協調分布式操作,確保資料的一致性和可用性,
  8. 集成Hadoop生態系統:HBase與Hadoop生態系統緊密集成,可以與Hadoop分布式檔案系統(HDFS)和Hadoop的計算框架(如MapReduce)無縫配合使用,這使得HBase能夠處理大規模的資料存盤和分析任務,

Hadoop的限制

盡管Hadoop是一個強大的分布式計算框架,但它也存在一些不足之處,與HBase相比,以下是一些Hadoop的限制:

  1. 實時性:Hadoop主要用于批處理任務,對于實時性要求較高的應用場景,如實時資料分析和流式處理,Hadoop的延遲可能會比較高,Hadoop的MapReduce模型通常不適合處理需要即時回應的資料處理任務,
  2. 存盤效率:Hadoop在存盤效率方面存在一些問題,為了提供容錯性和可靠性,Hadoop將資料復制多次存盤在不同的節點上,這會導致存盤開銷增加,相對于HBase的列存盤模型,Hadoop的存盤效率可能較低,
  3. 復雜性:Hadoop的配置和管理相對復雜,需要專業知識和經驗,搭建和維護一個Hadoop集群需要處理許多引數和組件,對于初學者來說可能存在一定的學習曲線,
  4. 擴展性限制:雖然Hadoop具有良好的可擴展性,可以通過添加更多的節點來擴展集群的存盤和計算能力,但在某些情況下,隨著集群規模的增加,管理和調度節點可能變得更加困難,
  5. 處理復雜查詢的限制:Hadoop的主要計算模型是MapReduce,它適合處理簡單的計算任務,但對于復雜的查詢和資料分析,如復雜聚合、連接和實時查詢等,Hadoop的性能可能不如專門設計的分析資料庫,

基本概念

NameSpace

命名空間,類似于關系型資料庫的Database概念,每個命名空間下有多個表,

HBase自帶兩個命名空間,分別是hbasedefault,hbase 中存放的是HBase內置的表,default表是用戶默認使用的命名空間,這2個命名空間默認是不展示的,

Table

類似于關系型資料庫的表概念,不同的是,HBase定義表時只需要宣告列族即可,不需要宣告具體的列,因為資料存盤時稀疏的,空(null)列不占用存盤空間,所有往HBase寫入資料時,欄位可以動態、按需指定,因此,和關系型資料庫相比,HBase 能夠輕松應對欄位變更的場景

RowKey

HBase表中的每行資料都由一個RowKey和多個Column(列)組成,資料是按照RowKey的字典順序存盤的,并且查詢資料時只能根據RowKey進行檢索,所以RowKey的設計十分重要

Column

HBase中的每個列都由Colunn Family (列族)和Column Qualifier (列限定符)進行限定,例如info: name, info: age, 建表時,只需指明列族,而列限定符無需預先定義,

TimeStamp

用于標識資料的不同版本(version),每條資料寫入時,系統會自動為其加上該欄位,其值為寫入HBase的時間,

Cell

由{rowkey, column Family:column Qualifier, timestamp} 唯一確定的單元,Cell 中的資料全部是位元組碼形式存貯

一條資料有多個版本,每個版本都是一個Cell,

存盤結構

HBase存盤結構如下:

上面的這種資料會存盤為下面這樣,底層存盤為Byte:

行分為Region,列分為Store,Region可以放在其他機器上,

HBase是基于HDFS的,而HDFS是不能夠修改資料的,所以HBase其實也是不能修改資料的,HBase使用時間戳實作修改功能,取資料的時候取最新時間戳的資料,取出來的就是最新的資料

HBase 資料訪問形式

HBase資料訪問可以通過以下幾種形式進行:

  1. 單行讀寫(Get和Put):使用HBase提供的API,可以通過指定行鍵(Row Key)來讀取和寫入單行資料,Get操作可以根據行鍵從表中獲取特定行的資料,而Put操作可以將資料寫入表的指定行,
  2. 批量讀寫(Scan和Batch Put):HBase支持批量讀寫操作,可以一次性讀取或寫入多行資料,Scan操作可以按照一定的條件掃描表中的多行資料,而Batch Put操作可以一次性寫入多行資料,
  3. 全表掃描(Scan):通過Scan操作,可以遍歷整個表的資料,按照指定的條件進行過濾和篩選,可以設定起始行鍵和結束行鍵,還可以使用過濾器(Filter)進行更精確的資料查詢,
  4. 列族范圍掃描(Scan):HBase中的資料以列族(Column Family)為單位進行存盤,可以通過Scan操作對指定列族的資料進行范圍掃描,這種方式可以提高資料查詢的效率,只獲取所需列族的資料,而不必讀取整個表的資料,
  5. 過濾器(Filter):HBase支持多種過濾器來進行資料的精確查詢和過濾,可以使用行鍵過濾器(Row Filter)按照行鍵的條件進行資料過濾,還可以使用列族過濾器(Family Filter)、列限定符過濾器(Qualifier Filter)和值過濾器(Value Filter)等進行更細粒度的資料過濾,
  6. 原子性操作(Check-and-Put和Check-and-Delete):HBase支持原子性操作,例如Check-and-Put和Check-and-Delete,這些操作允許在寫入資料之前進行檢查,只有在滿足指定條件的情況下才執行寫入操作,

以上形式提供了不同的資料訪問方式,可以根據具體的需求和查詢條件選擇適合的方式來訪問和操作HBase中的資料,

架構體系

HBase的架構體系是基于分布式存盤和處理的設計,它包含了以下幾個重要的組成部分:

  1. HMaster:HMaster是HBase集群的主節點,負責管理整個集群的元資料和協調各個RegionServer的作業,它維護了表的結構資訊、分片規則、RegionServer的負載均衡等,并協調分布式操作,如Region的分裂和合并,
  2. RegionServer:RegionServer是HBase集群中的作業節點,負責存盤和處理資料,每個RegionServer管理多個Region,每個Region負責存盤表中的一部分資料,RegionServer處理客戶端的讀寫請求,負責資料的存盤、讀取和寫入操作,
  3. ZooKeeper:ZooKeeper是一個分布式協調服務,被HBase用于管理集群的元資料和協調分布式操作,HBase使用ZooKeeper來進行主節點的選舉、故障檢測、集群配置的同步等任務,
  4. HDFS(Hadoop Distributed File System):HBase使用HDFS作為底層的分布式檔案系統,用于存盤資料,HDFS將資料分割成塊并分布在不同的節點上,提供高可靠性和可擴展性的存盤,
  5. HBase客戶端:HBase客戶端是與HBase互動的應用程式或工具,用于發送讀寫請求和接收查詢結果,客戶端可以通過HBase的Java API或者命令列工具(如HBase shell)來訪問和操作HBase表,
  6. 表和列族:HBase資料模型是基于表的,表由一個或多個列族(Column Family)組成,每個列族可以包含多個列(Column),列存盤著實際的資料,表被分割成多個Region存盤在不同的RegionServer上,每個Region負責存盤一部分行資料,

這些組成部分共同構成了HBase的架構體系,實作了分布式存盤和處理大規模資料集的能力,HMaster負責管理元資料和協調作業,RegionServer存盤和處理資料,ZooKeeper提供分布式協調服務,HDFS提供底層的分布式檔案存盤,而HBase客戶端用于與HBase進行互動,表和列族的概念提供了資料的組織和存盤方式,

HBase組件

  1. MemStore:每個RegionServer都有一個MemStore,它是位于記憶體中的臨時資料存盤區域,當客戶端寫入資料時,資料首先被寫入到MemStore中,以提供快速的寫入性能
  2. WAL(Write-Ahead-Log):WAL是HBase的日志檔案,用于記錄所有的寫操作,當資料被寫入到MemStore時,相應的寫操作也會被寫入WAL中,以保證資料的持久性和故障恢復能力,
  3. StoreFile:當MemStore中的資料達到一定大小閾值后,會被重繪到磁盤上的StoreFile中,StoreFile是HBase中實際持久化存盤資料的檔案形式,它包含了已經寫入的資料和相應的索引
  4. HFile:HFile是StoreFile的底層存盤格式,采用了塊索引和時間范圍索引的方式,提供了高效的資料查找和掃描能力,HFile使用塊(Block)來組織資料,并采用壓縮和編碼技術來減小存盤空間,

MemStore提供了臨時的記憶體存盤,StoreFile提供了持久化的磁盤存盤,WAL用于保證資料的持久性,這種架構設計使得HBase能夠提供高可用性、高性能和可擴展性的分布式存盤和處理能力,

HBase讀寫流程

讀流程

  1. 客戶端發送讀取請求:客戶端向HBase集群發送讀取請求,包括所需的表名、行鍵(Row Key)以及其他可選的引數(如列族、列限定符等),
  2. 定位RegionServer和Region:HBase的客戶端會與ZooKeeper進行通信,獲取到存盤有所需資料的Region所在的RegionServer的資訊,
  3. RegionServer處理請求:客戶端發送的讀取請求到達對應的RegionServer,RegionServer會根據請求的行鍵定位到包含所需資料的Region,
  4. 資料讀取:RegionServer首先會從MemStore中查找資料,如果資料在MemStore中找到,則直接回傳給客戶端,如果資料不在MemStore中,RegionServer會在磁盤上的StoreFile中進行查找,根據索引定位到所需的資料塊,并將資料塊讀取到記憶體中進行處理
  5. 資料回傳給客戶端:RegionServer將讀取到的資料回傳給客戶端,客戶端可以根據需要對資料進行進一步的處理和分析,

寫流程

  1. 客戶端發送寫入請求:客戶端向HBase集群發送寫入請求,包括表名、行鍵、列族、列限定符和對應的值等資訊,
  2. 定位RegionServer和Region:客戶端與ZooKeeper通信,獲取存盤目標資料的Region所在的RegionServer的資訊,
  3. RegionServer處理請求:客戶端發送的寫入請求到達對應的RegionServer,RegionServer根據行鍵定位到目標Region,
  4. 寫入到MemStore:RegionServer將寫入請求中的資料寫入到目標Region對應的記憶體中的MemStore,寫入到MemStore是一個追加操作,將資料追加到記憶體中的MemStore中,并不直接寫入磁盤
  5. WAL日志記錄:同時,RegionServer將寫入請求中的操作寫入WAL(Write-Ahead-Log)日志檔案,確保資料的持久性和故障恢復能力
  6. MemStore重繪到磁盤:當MemStore中的資料達到一定的大小閾值時,RegionServer會將MemStore中的資料重繪到磁盤上的StoreFile中,重繪程序將記憶體中的資料寫入到磁盤上的StoreFile,并生成相應的索引,
  7. 資料回傳給客戶端:寫入完成后,RegionServer向客戶端發送寫入成功的回應,表示資料已成功寫入,

MemStore Flush

在HBase中,MemStore Flush是將記憶體中的資料重繪到磁盤上的StoreFile的程序,當MemStore中的資料達到一定大小閾值時,或者達到了一定的時間限制,HBase會觸發MemStore Flush操作,以將資料持久化到磁盤,確保資料的持久性和可靠性

下面是MemStore Flush的基本程序:

  1. MemStore Flush觸發:當MemStore中的資料量達到一定的閾值(由配置引數控制)或者達到了一定的時間限制時,HBase會觸發MemStore Flush操作,這個閾值和時間限制可以根據需求進行配置,以平衡寫入性能和資料持久性的要求,
  2. 寫入記憶體快照:在觸發Flush操作時,HBase會先將MemStore中的資料做一個記憶體快照(Snapshot),以保證在Flush期間繼續接收新的寫入請求,
  3. 刷寫到磁盤:記憶體快照完成后,HBase會將記憶體中的資料按照列族的維度劃分為多個KeyValue,然后將這些KeyValue寫入磁盤上的StoreFile,StoreFile采用HFile格式,用于持久化存盤資料,
  4. 更新Region元資料:完成刷寫到磁盤后,HBase會更新Region的元資料,包括最新的StoreFile串列和相應的時間戳等資訊,
  5. MemStore清空:一旦資料刷寫到磁盤上的StoreFile,HBase會清空相應的MemStore,以釋放記憶體空間用于接收新的寫入請求,

通過MemStore Flush操作,HBase可以將記憶體中的資料持久化到磁盤,以確保資料的持久性和可靠性,Flush操作的頻率和成本可以通過配置引數進行調整,以適應不同的應用場景和性能需求,頻繁的Flush操作可能會影響寫入性能,而較長的Flush間隔可能會增加資料丟失的風險,因此,根據實際情況,需要合理設定Flush操作的引數,以平衡資料的持久性和寫入性能的要求,

引數說明

MemStore Flush在HBase中由以下幾個引數進行控制,它們的含義如下:

  1. hbase.hregion.memstore.flush.size:該引數指定了MemStore的大小閾值,當MemStore中的資料量達到或超過這個閾值時,將觸發MemStore Flush操作,該引數的默認值為 128MB,這個引數在HBase 0.98版本及更高版本中生效,在舊版本中,類似的引數名為 hbase.hregion.memstore.flush.size.upper,但其含義和作用相同,
  2. hbase.hregion.memstore.block.multiplier:該引數是用來設定MemStore大小閾值的倍數,當MemStore的大小超過 hbase.hregion.memstore.flush.size 乘以 hbase.hregion.memstore.block.multiplier 時,將觸發MemStore Flush操作,默認值為2,這個引數在HBase 0.98版本及更高版本中生效,
  3. hbase.hregion.memstore.flush.size.lower.limit:該引數定義了MemStore大小的下限限制,當MemStore中的資料量小于此下限時,不會觸發MemStore Flush操作,該引數的默認值為0,在HBase 2.0版本及更高版本中生效,
  4. hbase.hregion.memstore.flush.size.upper.limit:該引數定義了MemStore大小的上限限制,當MemStore中的資料量超過此上限時,將強制觸發MemStore Flush操作,該引數的默認值為Long.MAX_VALUE,在HBase 2.0版本及更高版本中生效,

上述的1和2,滿足任一條件都會觸發MemStore Flush操作

這些引數需要根據具體的應用場景和性能要求進行合理的設定,較小的Flush閾值可以提高資料的持久性,但可能會增加Flush的頻率和寫入的開銷;較大的Flush閾值可以減少Flush的頻率和開銷,但可能會增加資料丟失的風險,因此,需要根據應用的讀寫特征和資料的重要性,選擇合適的引數值,

StoreFile Compaction

StoreFile Compaction(檔案合并)是 HBase 中的一個重要操作,它用于合并和優化存盤在磁盤上的資料檔案(StoreFile),StoreFile Compaction 可以幫助減少磁盤空間占用、提高讀取性能,并且在某些情況下可以提高寫入性能,

StoreFile Compaction 的基本程序如下:

  1. Compact Selection(選擇合并):在進行 Compaction 之前,HBase 首先進行選擇性合并,它會根據一定的策略,如大小、時間戳等,選擇一組需要合并的 StoreFile,這樣可以限制合并的資料量,避免一次合并過多資料,
  2. Minor Compaction(小規模合并):Minor Compaction 主要合并較少數量的 StoreFile,它通過創建一個新的 StoreFile,并從多個舊的 StoreFile 中選擇合并的資料,將其合并到新的檔案中,這個程序中,舊的 StoreFile 不會被洗掉,新的 StoreFile 會被創建并寫入新的資料
  3. Major Compaction(大規模合并):Major Compaction 是一種更為綜合和耗時的合并操作,它會合并一個或多個 HBase 表的所有 StoreFile,Major Compaction 將會創建一個新的 StoreFile,并將所有舊的 StoreFile 中的資料合并到新的檔案中,與 Minor Compaction 不同,Major Compaction 還會洗掉舊的 StoreFile,從而釋放磁盤空間
  4. Compaction Policy(合并策略):HBase 提供了不同的合并策略,可以根據資料特點和應用需求進行選擇,常見的合并策略包括 SizeTieredCompactionPolicy(按大小合并)和 DateTieredCompactionPolicy(按時間戳合并)等,

通過 StoreFile Compaction,HBase 可以減少磁盤上的存盤空間占用,提高讀取性能,同時合并操作還可以優化資料布局,加速資料的訪問,合適的合并策略的選擇可以根據資料的訪問模式和應用需求,以達到最佳的性能和存盤效率,

引數說明

StoreFile Compaction 程序中涉及到的一些相關引數及其含義如下:

  1. hbase.hstore.compaction.min:指定了進行 Minor Compaction 的最小檔案數,當 StoreFile 的數量達到或超過該值時,才會觸發 Minor Compaction,默認值為 3,
  2. hbase.hstore.compaction.max:指定了進行 Major Compaction 的最大檔案數,當 StoreFile 的數量超過該值時,將觸發 Major Compaction,默認值為 10,
  3. hbase.hstore.compaction.ratio:指定了觸發 Major Compaction 的比率,當一個 Region 中的 StoreFile 的總大小超過其最大檔案大小的比率時,將觸發 Major Compaction,默認值為 1.2,
  4. hbase.hstore.compaction.min.size:指定了進行 Compaction 的最小檔案大小,當一個 StoreFile 的大小小于該值時,將不會參與 Compaction,默認值為 1 KB,
  5. hbase.hstore.compaction.max.size:指定了進行 Compaction 的最大檔案大小,當一個 StoreFile 的大小超過該值時,將不會參與 Compaction,默認值為 Long.MAX_VALUE,即無限制,
  6. hbase.hstore.compaction.enabled:指定了是否啟用 Compaction,如果設定為 false,則不會觸發任何 Compaction 操作,默認值為 true,
  7. hbase.hstore.compaction.checker.interval.multiplier:指定了進行 Compaction 檢查的時間間隔,實際檢查的時間間隔為 hbase.hstore.compaction.checker.interval.multiplier 乘以 StoreFile 的平均大小,默認值為 1.0,

這些引數可以在 HBase 的組態檔(hbase-site.xml)中進行設定,通過調整這些引數的值,可以根據資料量、存盤需求和性能要求來優化 Compaction 操作的觸發條件和行為,

觸發程序

以下是判斷是否觸發 Compaction 的程序:

  1. 判斷是否滿足進行 Minor Compaction 的條件:

    • 檢查 StoreFile 的數量是否達到或超過 hbase.hstore.compaction.min,如果是,則滿足觸發 Minor Compaction 的條件,
  2. 判斷是否滿足進行 Major Compaction 的條件:

    • 檢查 StoreFile 的數量是否超過 hbase.hstore.compaction.max,如果是,則滿足觸發 Major Compaction 的條件,

    或者

    • 計算 StoreFile 的總大小與最大檔案大小之間的比率,如果超過 hbase.hstore.compaction.ratio,即 StoreFile 的總大小超過最大檔案大小的比率,那么滿足觸發 Major Compaction 的條件,
  3. 對于即將進行 Compaction 的 StoreFile:

    • 檢查 StoreFile 的大小是否在 hbase.hstore.compaction.min.size 和 hbase.hstore.compaction.max.size 之間,如果不在這個范圍內,則該檔案將不會參與 Compaction,
  4. 檢查是否啟用 Compaction:

    • 檢查 hbase.hstore.compaction.enabled 的值是否為 true,如果為 false,則不會觸發任何 Compaction 操作,
  5. 判斷觸發 Compaction 的時間間隔:

    • 根據 hbase.hstore.compaction.checker.interval.multiplier 乘以 StoreFile 的平均大小,得出實際的檢查時間間隔,

根據以上判斷程序,HBase 在每個 RegionServer 上的每個 Store(列族)會根據配置引數進行定期的 Compaction 檢查,一旦滿足觸發 Compaction 的條件,相應的 Minor Compaction 或 Major Compaction 將被觸發,合并和優化存盤的資料檔案,這樣可以提高讀取性能、節省磁盤空間,并且在某些情況下可以提高寫入性能,

Region Split

Region Split(區域分割)是 HBase 中的一個重要操作,它用于在資料增長程序中,將一個較大的 HBase 表的 Region(區域)劃分成更小的子區域,以提高讀寫性能和負載均衡,

當一個 Region 的大小達到了預先配置的閾值時,HBase 將觸發 Region Split 操作,Region Split 的基本程序如下:

  1. Split Policy(分割策略):HBase 提供了多種分割策略,用于決定何時觸發 Region Split,常見的分割策略包括按大小分割(Size-based Split)和按行數分割(Row-count-based Split),這些策略可以根據資料特點和應用需求進行選擇,
  2. Split Selection(選擇分割點):在觸發分割之前,HBase 首先選擇一個適當的分割點,分割點是指一個 RowKey,它將成為分割后的兩個子區域的邊界,選擇分割點的策略可以是根據大小、行數或其他自定義邏輯進行選擇,
  3. Region Split(區域分割):一旦選擇了分割點,HBase 將通過創建兩個新的子區域來執行分割操作,原始的 Region 將被拆分成兩個子區域,每個子區域負責存盤分割點兩側的資料,同時,HBase 會為新的子區域生成新的 Region ID,并更新元資料資訊,

常見的區域分割方式包括:

  1. 均勻分割(Even Split):將一個 Region 均勻地劃分為兩個子區域,分割點根據資料大小或行數進行選擇,以保持兩個子區域的大小相近,
  2. 預磁區(Pre-splitting):在創建表時,可以提前定義多個分割點,將表劃分為多個初始的子區域,這樣可以在表創建之初就實作資料的均衡分布,避免后續的動態分割
  3. 自定義分割(Custom Split):根據具體的業務需求和資料特點,可以通過自定義邏輯來選擇分割點,實作更靈活的分割方式,

通過合理地使用區域分割,可以充分利用集群資源,提高讀寫性能和負載均衡能力,不同的分割策略和分割方式可以根據資料規模、訪問模式和應用需求進行選擇,以滿足不同場景下的需求,

預磁區

在 HBase 中進行預磁區可以通過 HBase Shell 或 HBase API 進行操作,以下是使用 HBase Shell 進行預磁區的示例:

  1. 打開 HBase Shell:

    $ hbase shell
    
  2. 創建表并指定磁區:

    hbase(main):001:0> create 'my_table', 'cf', {SPLITS => ['a', 'b', 'c']}
    

    上述命令創建了一個名為 my_table 的表,并指定了三個磁區點:'a'、'b' 和 'c',這將創建四個初始的子區域,

  3. 查看表的磁區情況:

    hbase(main):002:0> describe 'my_table'
    

    這將顯示表的詳細資訊,包括磁區資訊,

通過上述步驟,你可以在創建表時預先定義磁區點,從而實作預磁區,每個磁區點將成為一個子區域的邊界,確保資料在表創建時就能分布在多個子區域中,從而實作負載均衡和性能優化,

請注意,上述示例是使用 HBase Shell 進行預磁區的簡單示例,如果需要在編程中進行預磁區,可以使用 HBase API,例如 Java API,通過在創建表時設定 SPLITS 引數來指定磁區點,

以下是使用 HBase Java API 進行預磁區的示例代碼:

import org.apache.hadoop.hbase.HBaseConfiguration;
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.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;

public class PreSplitExample {
    public static void main(String[] args) throws IOException {
        // 創建 HBase 配置
        org.apache.hadoop.conf.Configuration config = HBaseConfiguration.create();

        // 創建 HBase 連接
        try (Connection connection = ConnectionFactory.createConnection(config)) {
            // 創建 HBase 管理器
            try (Admin admin = connection.getAdmin()) {
                // 定義表名
                TableName tableName = TableName.valueOf("my_table");

                // 定義磁區點
                byte[][] splitKeys = {
                        Bytes.toBytes("a"),
                        Bytes.toBytes("b"),
                        Bytes.toBytes("c")
                };

                // 創建表并指定磁區
                admin.createTable(TableDescriptorBuilder.newBuilder(tableName)
                        .addColumnFamily(ColumnFamilyDescriptorBuilder.of("cf"))
                        .setSplitKeys(splitKeys)
                        .build());
            }
        }
    }
}

上述代碼通過 HBase Java API 創建了一個名為 my_table 的表,并指定了三個磁區點:'a'、'b' 和 'c',這將創建四個初始的子區域,

請注意,在使用 Java API 進行預磁區時,需要先建立與 HBase 的連接,并通過 HBase 管理器(Admin)執行表的創建操作,并設定 setSplitKeys(splitKeys) 方法來指定磁區點,

通過上述示例代碼,你可以在編程中使用 HBase Java API 實作預磁區功能,

HBase優化

查詢優化

設定Scan快取

在HBase中,可以通過設定Scan物件的setCaching()方法來調整Scan快取的大小,Scan快取用于指定每次掃描操作從RegionServer回傳給客戶端的行數,通過調整快取大小,可以在一定程度上控制資料的讀取性能和網路傳輸的開銷,

以下是設定Scan快取的示例代碼:

Scan scan = new Scan();
scan.setCaching(500); // 設定快取大小為500行

ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
    // 處理掃描結果
}
scanner.close();

在上述示例中,setCaching()方法將快取大小設定為500行,可以根據實際需求調整這個值,需要根據資料大小、網路帶寬和性能要求進行權衡,較大的快取大小可以減少客戶端與RegionServer之間的通信次數,提高讀取性能,但同時也會增加記憶體消耗,較小的快取大小可以減少記憶體消耗,但可能會增加通信次數和網路傳輸開銷,

需要注意的是,setCaching()方法設定的是每次掃描的快取大小,并不是全域的設定,如果需要對整個表的掃描操作生效,需要在每次掃描時都設定快取大小,

此外,還可以通過調整HBase的配置引數來全域設定快取大小,在hbase-site.xml組態檔中添加以下引數可以設定默認的快取大小:

<property>
  <name>hbase.client.scanner.caching</name>
  <value>500</value> <!-- 設定默認的快取大小為500行 -->
</property>

以上是通過代碼和組態檔來設定Scan快取大小的方法,根據具體的應用場景和需求,可以選擇適當的方式進行設定,

顯示指定列

當使用Scan或者GET獲取大量的行時,最好指定所需要的列,因為服務端通過網路傳輸到客戶端,資料量太大可能是瓶頸,如果能有效過濾部分資料,能很大程度的減少網路I/O的花費,

在HBase中,可以使用ScanGet操作來顯示指定的列,下面分別介紹兩種方式的用法:

  1. 使用Scan操作顯示指定列:
Scan scan = new Scan();
scan.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("col1")); // 指定列族(cf)和列(col1)

ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
    byte[] value = https://www.cnblogs.com/booksea/p/result.getValue(Bytes.toBytes("cf"), Bytes.toBytes("col1"));
    // 處理列(col1)的值
}
scanner.close();

在上述示例中,使用scan.addColumn()方法來指定要顯示的列族和列,在for回圈中,通過result.getValue()方法獲取指定列的值,

  1. 使用Get操作顯示指定列:
Get get = new Get(Bytes.toBytes("row1")); // 指定行鍵(row1)
get.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("col1")); // 指定列族(cf)和列(col1)

Result result = table.get(get);
byte[] value = https://www.cnblogs.com/booksea/p/result.getValue(Bytes.toBytes("cf"), Bytes.toBytes("col1"));
// 處理列(col1)的值

在上述示例中,使用get.addColumn()方法來指定要顯示的列族和列,通過table.get()方法獲取行資料,并通過result.getValue()方法獲取指定列的值,

無論是使用Scan還是Get,都可以通過addColumn()方法來指定要顯示的列族和列,可以根據具體的需求,多次呼叫addColumn()方法來顯示多個列,

需要注意的是,HBase中的列是以位元組陣列(byte[])形式表示的,因此在使用addColumn()getValue()方法時,需要將列族和列名轉換為位元組陣列,

禁用塊快取

如果批量進行全表掃描,默認是有快取的,如果此時有快取,會降低掃描的效率,

在HBase中,可以通過設定Scan物件的setCacheBlocks()方法來禁用塊快取,塊快取是HBase中的一種快取機制,用于加快資料的讀取操作,然而,在某些情況下,禁用塊快取可能是有益的,例如對于某些熱點資料或者需要立即獲取最新資料的場景,

以下是禁用Scan塊快取的示例代碼:

Scan scan = new Scan();
scan.setCacheBlocks(false); // 禁用塊快取

ResultScanner scanner = table.getScanner(scan);
for (Result result : scanner) {
    // 處理掃描結果
}
scanner.close();

在上述示例中,setCacheBlocks(false)方法將禁用Scan操作的塊快取,

需要注意的是,禁用塊快取可能會增加對HBase存盤的實際磁盤讀取次數,并且在一些場景下可能導致性能下降,因此,在禁用塊快取之前,建議仔細評估應用需求和場景,確保禁用塊快取的決策是合理的,

對于經常讀到的資料,建議使用默認值,開啟塊快取,

寫入優化

設定AutoFlush

Htable有一個屬性是AutoFlush,該屬性用于支持客戶端的批量更新,默認是true,當客戶端每收到一條資料,立刻發送到服務端,如果設定為false,當客戶端提交put請求時候,先將該請求在客戶端快取,到達閾值的時候或者執行hbase.flushcommits(),才向RegionServer提交請求,

在HBase中,可以通過設定Table物件的setAutoFlush()方法來控制自動重繪(AutoFlush)行為,AutoFlush決定了在何時將資料從客戶端發送到RegionServer并寫入到存盤中,

以下是設定AutoFlush的示例代碼:

// 創建HBase配置物件
Configuration conf = HBaseConfiguration.create();

// 創建HBase連接
Connection connection = ConnectionFactory.createConnection(conf);

// 獲取表物件
TableName tableName = TableName.valueOf("your_table_name");
Table table = connection.getTable(tableName);

// 設定AutoFlush
table.setAutoFlush(false);  // 關閉AutoFlush

// 執行寫入操作
Put put = new Put(Bytes.toBytes("row1"));
put.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("col1"), Bytes.toBytes("value1"));
table.put(put);

// 手動重繪資料
table.flushCommits();  // 手動重繪資料到RegionServer

// 關閉表和連接
table.close();
connection.close();

在上述示例中,table.setAutoFlush(false)方法將關閉AutoFlush,這意味著在執行寫操作時,資料不會立即被重繪到RegionServer和存盤中,而是先快取在客戶端的記憶體中,只有當呼叫table.flushCommits()方法時,資料才會被手動重繪到RegionServer,

需要注意的是,關閉AutoFlush可以提高寫入性能,尤其是在批量寫入或者頻繁寫入的場景中,但是,關閉AutoFlush也會增加資料在客戶端記憶體中的暫存時間,并增加了資料丟失的風險,因此,在關閉AutoFlush時,需要在適當的時機手動呼叫flushCommits()方法來確保資料的持久性,

同時,還可以通過設定table.setWriteBufferSize()方法來指定客戶端寫緩沖區的大小,這可以幫助在快取中存盤更多的資料,減少重繪到RegionServer的次數,提高寫入性能,例如:

table.setWriteBufferSize(1024 * 1024); // 設定寫緩沖區大小為1MB

在上述示例中,將寫緩沖區大小設定為1MB,

總之,通過設定table.setAutoFlush(false)table.setWriteBufferSize()方法,可以控制AutoFlush行為和客戶端寫緩沖區大小,以優化寫入性能和資料重繪的策略,根據具體的應用需求和場景,可以進行適當的配置調整,

引數優化

Zookeeper 會話超時時間

屬性:zookeeper.session.timeout

解釋:默認值為 90000 毫秒(90s),當某個 RegionServer 掛掉,90s 之后 Master 才能察覺到,可適當減小此值,盡可能快地檢測 regionserver 故障,可調整至 20-30s,看你能有都能忍耐超時,同時可以調整重試時間和重試次數

hbase.client.pause(默認值 100ms)

hbase.client.retries.number(默認 15 次)

設定 RPC 監聽數量

屬性:hbase.regionserver.handler.count

解釋:默認值為 30,用于指定 RPC 監聽的數量,可以根據客戶端的請求數進行調整,讀寫請求較多時,增加此值,

手動控制 Major Compaction

屬性:hbase.hregion.majorcompaction

解釋:默認值:604800000 秒(7 天), Major Compaction 的周期,若關閉自動 Major Compaction,可將其設為 0,如果關閉一定記得自己手動合并,因為大合并非常有意義,

優化 HStore 檔案大小

屬性:hbase.hregion.max.filesize

解釋:默認值 10737418240(10GB),如果需要運行 HBase 的 MR 任務,可以減小此值,因為一個 region 對應一個 map 任務,如果單個 region 過大,會導致 map 任務執行時間,過長,該值的意思就是,如果 HFile 的大小達到這個數值,則這個 region 會被切分為兩個 Hfile,

優化 HBase 客戶端快取

屬性:hbase.client.write.buffer

解釋:默認值 2097152bytes(2M)用于指定 HBase 客戶端快取,增大該值可以減少 RPC呼叫次數,但是會消耗更多記憶體,反之則反之,一般我們需要設定一定的快取大小,以達到減少 RPC 次數的目的,

指定 scan.next 掃描 HBase 所獲取的行數

屬性:hbase.client.scanner.caching

解釋:用于指定 scan.next 方法獲取的默認行數,值越大,消耗記憶體越大,

SpringBoot中使用HBase

添加 Maven 依賴:

<!-- HBase 2.4.3 依賴 -->
<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-client</artifactId>
    <version>2.4.3</version>
</dependency>

配置 HBase 連接:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;

@Configuration
public class HBaseConfig {
    @Bean
    public Connection hbaseConnection() throws IOException {
        Configuration config = HBaseConfiguration.create();
        config.set("hbase.zookeeper.quorum", "localhost");  // HBase ZooKeeper 地址
        config.set("hbase.zookeeper.property.clientPort", "2181");  // HBase ZooKeeper 埠
        return ConnectionFactory.createConnection(config);
    }
}

撰寫增刪改查代碼:

import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class HBaseService {

    @Autowired
    private Connection hbaseConnection;

    //添加資料
    public void putData(String tableName, String rowKey, String columnFamily, String column, String value) throws IOException {
        Table table = hbaseConnection.getTable(TableName.valueOf(tableName));
        Put put = new Put(Bytes.toBytes(rowKey));
        put.addColumn(Bytes.toBytes(columnFamily), Bytes.toBytes(column), Bytes.toBytes(value));
        table.put(put);
        table.close();
    }

    //洗掉資料
    public void deleteData(String tableName, String rowKey) throws IOException {
        Table table = hbaseConnection.getTable(TableName.valueOf(tableName));
        Delete delete = new Delete(Bytes.toBytes(rowKey));
        table.delete(delete);
        table.close();
    }

    //獲取資料
    public String getData(String tableName, String rowKey, String columnFamily, String column) throws IOException {
        Table table = hbaseConnection.getTable(TableName.valueOf(tableName));
        Get get = new Get(Bytes.toBytes(rowKey));
        Result result = table.get(get);
        byte[] valueBytes = result.getValue(Bytes.toBytes(columnFamily), Bytes.toBytes(column));
        table.close();
        return Bytes.toString(valueBytes);
    }
}

在上述代碼中,HBaseConfig 類配置了 HBase 連接,通過 hbaseConnection() 方法創建 HBase 連接,HBaseService 類提供了 putData()deleteData()getData() 方法,分別用于插入資料、洗掉資料和獲取資料,

Scan

以下是使用Scan 操作的示例代碼:

import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;

public class HBaseScanExample {

    public static void main(String[] args) throws IOException {
        // 創建 HBase 配置物件
        Configuration conf = HBaseConfiguration.create();

        // 創建 HBase 連接
        Connection connection = ConnectionFactory.createConnection(conf);

        // 獲取表物件
        TableName tableName = TableName.valueOf("your_table_name");
        Table table = connection.getTable(tableName);

        // 創建 Scan 物件
        Scan scan = new Scan();
        scan.addColumn(Bytes.toBytes("cf"), Bytes.toBytes("col1")); // 指定要查詢的列族和列

        // 執行 Scan 操作
        ResultScanner scanner = table.getScanner(scan);
        for (Result result : scanner) {
            // 處理每一行資料
            byte[] row = result.getRow();
            byte[] value = https://www.cnblogs.com/booksea/p/result.getValue(Bytes.toBytes("cf"), Bytes.toBytes("col1"));
            System.out.println("Row key: " + Bytes.toString(row) + ", Value: " + Bytes.toString(value));
        }

        // 關閉資源
        scanner.close();
        table.close();
        connection.close();
    }
}

在上述代碼中,首先創建 HBase 配置物件 Configuration,然后通過 ConnectionFactory 創建 HBase 連接 Connection,接下來,通過連接獲取表物件 Table,指定要進行 Scan 操作的表名,然后創建 Scan 物件,并使用 addColumn 方法指定要查詢的列族和列,最后,使用 getScanner 方法執行 Scan 操作,并遍歷 ResultScanner 獲取每一行的資料,并進行處理,

Phoenix

Phoenix是一個開源的基于Apache HBase的關系型資料庫引擎,它提供了SQL介面來訪問HBase中存盤的資料,它在HBase的基礎上添加了SQL查詢和事務功能,使得使用HBase的開發者可以使用熟悉的SQL語言進行資料操作和查詢

Phoenix在HBase中的主要用途包括:

  1. SQL查詢:Phoenix允許開發者使用標準的SQL陳述句來查詢和操作HBase中的資料,無需撰寫復雜的HBase API代碼,這簡化了開發程序,降低了使用HBase進行資料訪問的門檻,
  2. 索引支持:Phoenix提供了對HBase資料的二級索引支持,開發者可以使用SQL陳述句創建索引,從而加快查詢速度,索引在資料查詢和過濾中起到重要的作用,提高了資料的檢索效率,
  3. 事務支持:Phoenix引入了基于MVCC(多版本并發控制)的事務機制,使得在HBase中進行復雜的事務操作成為可能,開發者可以通過Phoenix的事務功能來保證資料的一致性和可靠性,
  4. SQL函式和聚合:Phoenix支持各種內置的SQL函式和聚合函式,如SUM、COUNT、MAX、MIN等,使得在HBase上進行資料統計和分析變得更加方便,

要在HBase中使用Phoenix,需要先安裝并配置好Phoenix,以下是一個在HBase中使用Phoenix的示例代碼:

  1. 添加 Maven 依賴: 在 Maven 專案的 pom.xml 檔案中添加以下依賴:
<!-- Phoenix 依賴 -->
<dependency>
    <groupId>org.apache.phoenix</groupId>
    <artifactId>phoenix-core</artifactId>
    <version>4.16.0-HBase-2.4</version>
</dependency>
  1. 創建 Phoenix 表: 在 HBase 中創建 Phoenix 表,可以使用 Phoenix 提供的 SQL 語法創建表和定義模式,例如,創建一個名為 users 的表:
CREATE TABLE users (
    id BIGINT PRIMARY KEY,
    name VARCHAR,
    age INTEGER
);
  1. 使用 Phoenix 進行操作: 在 Java 代碼中,可以使用 Phoenix 提供的 PhoenixConnectionPhoenixStatement 來執行 SQL 操作,
import java.sql.*;

public class PhoenixExample {

    public static void main(String[] args) throws SQLException {
        // 創建 Phoenix 連接
        String url = "jdbc:phoenix:<HBase ZooKeeper Quorum>:<HBase ZooKeeper Port>";
        Connection connection = DriverManager.getConnection(url);

        // 執行 SQL 查詢
        String query = "SELECT * FROM users";
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(query);

        // 處理查詢結果
        while (resultSet.next()) {
            long id = resultSet.getLong("ID");
            String name = resultSet.getString("NAME");
            int age = resultSet.getInt("AGE");
            System.out.println("ID: " + id + ", Name: " + name + ", Age: " + age);
        }

        // 關閉資源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

在上述代碼中,需要將 <HBase ZooKeeper Quorum><HBase ZooKeeper Port> 替換為你的 HBase ZooKeeper 地址和埠,

通過創建 PhoenixConnection 并傳遞正確的 JDBC URL,可以獲得連接物件,接下來,可以使用 createStatement() 方法創建 PhoenixStatement 物件,并使用 executeQuery() 方法執行 SQL 查詢,

然后,可以使用 ResultSet 物件遍歷查詢結果,并提取所需的欄位,在此示例中,遍歷了 users 表的結果,并列印了每行的 ID、Name 和 Age,


本篇文章就到這里,感謝閱讀,如果本篇博客有任何錯誤和建議,歡迎給我留言指正,文章持續更新,可以關注公眾號第一時間閱讀,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/554938.html

標籤:Java

上一篇:分庫分表用這個就夠了

下一篇:返回列表

標籤雲
其他(160817) Python(38219) JavaScript(25492) Java(18219) C(15237) 區塊鏈(8270) C#(7972) AI(7469) 爪哇(7425) MySQL(7247) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5873) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4589) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2435) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1984) 功能(1967) HtmlCss(1962) Web開發(1951) C++(1933) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • 一篇文章帶你入門HBase

    本文已收錄至Github,推薦閱讀 👉 [Java隨想錄](https://github.com/ZhengShuHai/JavaRecord) 微信公眾號:[Java隨想錄](https://mmbiz.qpic.cn/mmbiz_jpg/jC8rtGdWScMuzzTENRgicfnr91C5 ......

    uj5u.com 2023-06-13 07:41:06 more
  • 分庫分表用這個就夠了

    # 一、前言 2018年寫過一篇分庫分表的文章《[SpringBoot使用sharding-jdbc分庫分表](https://www.cnblogs.com/2YSP/p/9746981.html)》,但是存在很多不完美的地方比如: - sharding-jdbc的版本(1.4.2)過低,現在gi ......

    uj5u.com 2023-06-13 07:40:57 more
  • Jenkins + Docker 一鍵自動化部署 Spring Boot 專案,步驟齊全,少走

    本文章實作最簡單全面的Jenkins+docker+springboot 一鍵自動部署專案,步驟齊全,少走坑路。 **環境**:centos7+git(gitee) 簡述實作步驟:在docker安裝jenkins,配置jenkins基本資訊,利用Dockerfile和shell腳本實作專案自動拉取打 ......

    uj5u.com 2023-06-13 07:39:30 more
  • 翻車了,被讀者找出 BUG

    大家好呀,我是小樓。 本文是上篇文章[《使用增強版 singleflight 合并事件推送,效果炸裂!》](https://mp.weixin.qq.com/s/PFojA2DWJF7ry9Rdu8znyA)的續集,沒看過前文必須要先看完才能看本文,實在不想看,拉到文章末尾,給我點個贊再退出吧~Do ......

    uj5u.com 2023-06-13 07:32:11 more
  • Python生成指定大小的檔案

    轉載請注明出處?? 作者:[測驗蔡坨坨](https://www.caituotuo.top/) 原文鏈接:[caituotuo.top/400bd75c.html](https://www.caituotuo.top/400bd75c.html) 你好,我是測驗蔡坨坨。 在日常測驗作業中,我們經常 ......

    uj5u.com 2023-06-12 07:44:25 more
  • C++面試八股文:在C++中,你知道哪些運算子?

    某日二師兄參加XXX科技公司的C++工程師開發崗位第11面: > 面試官:在C++中,你都知道都哪些運算子? > > 二師兄:啥?運算子?`+-*/=`這些算嗎? > > 面試官:嗯,還有其他的嗎? > > 二師兄:當然還有,`+=,-=,*=,/=,==`,還有邏輯運算,位運算等。 > > 面試官 ......

    uj5u.com 2023-06-12 07:44:16 more
  • Xilinx GTH 簡介 ,CoaXpress FPGA PHY 部分

    ## 什么是GTH GTH 是Xilinx UltraScale系列FPGA上高速收發器的一種型別,本質上和其它名稱如GTP, GTX等只是器件型別不同、速率有差異;GTH 最低速率在500Mbps,最高在16Gbps ![](https://img2023.cnblogs.com/blog/274 ......

    uj5u.com 2023-06-12 07:43:55 more
  • 【技識訓累】Java中的泛型【一】

    博客推行版本更新,成果積累制度,已經寫過的博客還會再次更新,不斷地琢磨,高質量高數量都是要追求的,工匠精神是學習必不可少的精神。因此,大家有何建議歡迎在評論區踴躍發言,你們的支持是我最大的動力,你們敢投,我就敢肝 ......

    uj5u.com 2023-06-12 07:43:40 more
  • List 介面及其常用方法

    List 介面是 Collection 介面的子介面。List 中元素有序,是按照元素的插入順序進行排序的。每個元素都有一個與之關聯的整數型索引(索引從 0 開始),可以根據索引來訪問和操作元素,可以使用普通 for 回圈遍歷。List 中可以包含重復的元素。 ......

    uj5u.com 2023-06-12 07:43:36 more
  • Go 語言實作 MySQL 資料庫事務

    # Go 實作 MySQL 資料庫事務 ## 一、MySQL事務 MySQL事務是指一組資料庫操作,它們被視為一個邏輯單元,并且要么全部成功執行,要么全部回滾(撤銷)。事務是資料庫管理系統提供的一種機制,用于確保資料的一致性和完整性。 事務具有以下特性(通常由ACID原則定義): 1. 原子性(At ......

    uj5u.com 2023-06-12 07:43:32 more