本文為您介紹使用Hologres過程中關於Blink和Flink的常見問題。
基本概念
Hologres效能
寫入效能
列存表: InsertOrIgnore > InsertOrReplace > InsertOrUpdate
行存表: InsertOrReplcae = InsertOrUpdate > InsertOrIgnore
參數
說明
InsertOrIgnore
結果表有主鍵,即時寫入時如果主鍵重複,丟棄後到的資料。
InsertOrReplace
結果表有主鍵,即時寫入時如果主鍵重複,按照主鍵更新,如果寫入的一行資料不包含所有列,缺失的列的資料補Null。
InsertOrUpdate
結果表有主鍵,即時寫入時如果主鍵重複,按照主鍵更新,如果寫入的一行資料不包含所有列,缺失的列不更新。
點查效能
行存 = 行列混存 > 列存。
Blink、Flink(VVP)、開源Flink支援情況
產品形態
資料存放區類型
描述
源表
結果表
維表
Binlog
Hologres Catalog
Flink全託管
支援行儲存及列儲存。
支援行儲存及列儲存。
建議使用行儲存。
支援
支援
無
Blink獨享
支援行儲存及列儲存。
支援行儲存及列儲存。
建議使用行儲存。
Hologres V0.8版本只支援行儲存,V0.9及以上版本支援行儲存及列儲存。建議使用行儲存。
不支援
已開始逐步下線,推薦使用阿里雲Flink全託管。
開源Flink1.10
支援行儲存及列儲存。
支援行儲存及列儲存。
無
不支援
不支援
無
開源Flink1.11及以上
支援行儲存及列儲存。
支援行儲存及列儲存。
建議使用行儲存。
不支援
不支援
從開源Flink1.11版本開始,Hologres代碼已開源。詳細內容請參見GitHub。
Blink、Flink 映射Hologres的SQL樣本如下。
create table holo_source( 'hg_binlog_lsn' BIGINT HEADER, 'hg_binlog_event_type' BIGINT HEADER, 'hg_binlog_timestamp_us' BIGINT HEADER, A int, B int, C timestamp ) with ( type = 'hologres', 'endpoint' = 'xxx.hologres.aliyuncs.com:80', --Hologres執行個體的Endpoint。 'userName' = '', --當前阿里雲帳號的AccessKey ID。 'password' = '', --當前阿里雲帳號的AccessKey Secret。 'dbName' = 'binlog', --Hologres執行個體的資料庫名稱。 'tableName' ='test' --Hologres執行個體的表名稱。 'binlog' = 'true', );
Blink、VVP、Flink SQL,都是在Flink側聲明一張表,然後根據參數映射至Hologres的一張具體的物理表,所以不支援映射至外部表格。
即時寫入慢問題排查流程
確認寫入相關配置
需要確認以下配置資訊。
目標表的儲存格式,包括行存表、列存表和行列共存表。
Insert模式,包括InsertOrIgnore、InsertOrUpdate和InsertOrReplace。
目標表的Table Group及Shard Count。
查看監控指標的即時寫入延遲
如果平均寫入延遲偏高,在百毫秒甚至秒層級,通常便是後端達到了寫入瓶頸,這時候可能會存在如下問題。
使用了列存表的InsertOrUpdate,即局部更新,且流量較高,這種情況下會導致執行個體的CPU負載和寫入延遲偏高。
解決方案:建議更換表的類型,使用行存表,如果您的執行個體是V1.1及以上版本可以選擇行列混存表。
CloudMonitor查看執行個體的CPU負載,如果CPU水位接近100%,但沒有列存表的局部更新,那麼通常情況下是由於高QPS的查詢,或者本身寫入量較高導致的。
解決方案:擴容Hologres執行個體。
確認是否有不斷的
Insert into select from
命令,觸發了該表的BulkLoad寫入,當前BulkLoad寫入會阻塞即時寫入。解決方案:將BulkLoad寫入轉換成即時寫入,或者錯峰執行。
確認是否有資料扭曲
使用如下SQL命令查看是否有資料扭曲。
SELECT hg_shard_id, count(1) FROM t1 GROUP BY hg_shard_id ORDER BY hg_shard_id;
解決方案:修改Distribution Key,使資料分布更加均衡。
確認後端是否有壓力
如果以上步驟排查完沒有問題,寫入效能突然下降,一般情況是後端叢集壓力比較大,存在瓶頸。請聯絡技術支援人員確認情況,詳情請參見如何擷取更多的線上支援?。
查看Blink/Flink側的反壓情況
上述步驟排查完後,發現Hologres側沒有明顯的異常,通常情況下是用戶端慢了,也就是Blink/Flink側本身就慢了,這時候確認是否是Sink節點反壓了。如果作業只有一個節點,就無法看出是否反壓了,這時候可以將Sink節點單獨拆開再觀察。具體請聯絡Flink支援人員。
寫入資料有問題排查流程
這種情況通常是由於資料亂序引起的,比如相同主鍵的資料分布在不同的Flink Task上,寫入的時候無法保證順序。需要確認Flink SQL的邏輯,最後寫出到Hologres的時候,是否按照Hologres表的主鍵進行Shuffle了。
維表查詢問題排查流程
維表Join和雙流Join
對於讀Hologres的情境,需要首先確認使用者是否使用對了維表Join,是否錯將雙流Join當成維表Join來使用了。以下是Hologres作為維表的使用樣本,如果少了
proctime AS PROCTIME()
和hologres_dim FOR SYSTEM_TIME AS
兩處關鍵字,則會變成雙流Join。CREATE TEMPORARY TABLE datagen_source ( a INT, b BIGINT, c STRING, proctime AS PROCTIME() ) with ( 'connector' = 'datagen' ); CREATE TEMPORARY TABLE hologres_dim ( a INT, b VARCHAR, c VARCHAR ) with ( 'connector' = 'hologres', ... ); CREATE TEMPORARY TABLE blackhole_sink ( a INT, b STRING ) with ( 'connector' = 'blackhole' ); insert into blackhole_sink select T.a,H.b FROM datagen_source AS T JOIN hologres_dim FOR SYSTEM_TIME AS OF T.proctime AS H ON T.a = H.a;
維表查詢
確認維表格儲存體格式
確認維表的儲存格式是行存表、列存表還是行列共存。
維表查詢延遲高
維表的使用,最常見的問題就是Flink/Blink側使用者反饋Join節點有反壓,導致整個作業的吞吐上不去。
確認Flink維表Join的模式
當前Hologres Flink Connector的維表Join功能支援同步和非同步模式兩種,非同步模式效能要優於同步模式,具體需要看Flink SQL進行區分,以下是一個開啟非同步維表查詢功能的SQL樣本。
CREATE TABLE hologres_dim( id INT, len INT, content VARCHAR ) with ( 'connector'='hologres', 'dbname'='<yourDbname>', --Hologres的資料庫名稱。 'tablename'='<yourTablename>', --Hologres用於接收資料的表名稱。 'username'='<yourUsername>', --當前阿里雲帳號的AccessKey ID。 'password'='<yourPassword>', --當前阿里雲帳號的AccessKey Secret。 'endpoint'='<yourEndpoint>' --當前Hologres執行個體VPC網路的Endpoint。 'async' = 'true'--非同步模式 );
確認後端查詢延遲
查看監控指標的即時寫入延遲:
確認是否是列存表在做維表,列存表的維表在高QPS情境下開銷很高。
如果是行存表,且延遲高,通常情況下是執行個體整體負載較高導致的,需要進行擴容。
確認Join的Key是否是Hologres表的主鍵
自VVR 4.x (Flink 1.13) 版本開始,Hologres Connector基於Holo Client實現了Hologres表的非主鍵查詢,這種情況通常效能會比較差、執行個體負載也比較高,尤其是建表沒有特別最佳化過的情況。這時候需要引導最佳化表結構,最常見的就是將Join的key設定成Distribution Key,這樣就能實現Shard Pruning。
查看Blink側的反壓情況
如果上述步驟排查完成,發現Hologres側沒有明顯的異常,通常情況下是用戶端慢了,也就是Blink側本身就慢了,這時候可以確認是否是Sink節點反壓了。如果作業只有一個節點,就無法看出是否反壓了,這時候可以將Sink節點單獨拆開再觀察。同樣可以排查是否是Join節點導致的反壓。具體請聯絡Flink支援人員排查。
串連數使用說明
Hologres Connector預設採用JDBC相關模式。
現已支援JDBC_FIXED模式,該模式不佔用串連數,並且在消費Binlog時也不受Walsender數量上限的限制,詳情請參見即時數倉Hologres。
從Flink引擎VVR-8.0.5-Flink-1.17版本開始,預設開啟了串連複用
'connectionPoolName' = 'default'
,對大多數作業而言,這並沒有影響。如果單個作業表數量較多,可能在升級之後出現效能有所下降。這種情況下,建議為熱點表單獨配置connectionPoolName
參數以最佳化效能。JDBC模式會佔用一定數量的串連數,不同類型的表預設串連數使用方式如下表。
表類型
預設串連數(Flink作業的每個並發)
Binlog源表
0
批量源表
1
維表
3(可以通過
connectionSize
參數調整)結果表
3(可以通過
connectionSize
參數調整)串連數計算方法
預設情況
預設情況下,作業使用的最大串連數可以通過如下公式計算:
最大串連數 = ( 批量源表數 * 1 + 維表數 * connectionSize + 結果表數 * connectionSize )* 作業並發
。例如某作業有一張全增量源表、兩張維表和三張結果表,都使用預設的
connectionSize
參數值,作業並發設定為5
,則最終使用的串連數為:(1 * 1 + 2 * 3 + 3 * 3) * 5 = 80
。串連複用
Realtime Compute1.13-vvr-4.1.12及以上版本支援串連複用。一個作業的同一個並發內,相同
connectionPoolName
的維表和結果表會使用同一個串連池。預設情況樣本中,如果兩張維表和三張結果表都配置了相同的connectionPoolName
,並適當調大connectionSize
為5
,則最終使用的串連數為(1 * 1 + 5) * 5 = 30
。說明串連複用模式適用大多數情境,但部分情境比如維表數量較多、沒有啟用非同步也沒有開啟緩衝時,會非常頻繁的進行同步的點查,此時多表串連複用可能導致查詢變慢,這種情況可以只為結果表配置串連複用。
其他使用串連的情境
作業啟動過程中,需要建立串連用於表中繼資料的驗證等工作,可能會暫時使用3至6個串連,作業正常運行後會釋放。
Flink全託管支援Hologres Catalog、CTAS以及CDAS等功能,使用這些功能也會佔用串連數。預設情況下,一個使用Catalog的作業,會多佔用三個串連,用於建表等DDL操作。
串連數使用診斷
當作業的表數量較多、作業並發較高時,會佔用大量的串連數,甚至出現將Hologres總串連數佔滿的情況,通過以下方式對當前串連數的使用進行瞭解和診斷。
使用如下命令在HoloWeb中通過
pg_stat_activity
表查看當前的活躍Query,詳情請參見查詢pg_stat_activity視圖資訊。其中application_name
欄位中值為ververica-connector-hologres
的Query代表來自Realtime ComputeFlink的讀寫串連。SELECT application_name, COUNT (1) AS COUNT FROM pg_stat_activity WHERE backend_type = 'client backend' AND application_name != 'hologres' GROUP BY application_name;
有時作業並發設定的過高,在Hologres管理主控台執行個體列表對應執行個體的監控資訊頁表現如下:剛啟動時串連數很高,運行一段時間之後串連數下降。原因是很多串連處於空閑狀態而被關閉,此現象表明作業實際上不需要如此大的並發或串連數,應該合理規劃任務串連數、降低並發度或
connectionSize
參數值,或者使用串連複用模式。適當調整Hologres節點的並發度。預設情況下Flink作業的所有運算元並發相同,一些情境下那些包含複雜計算邏輯的運算元需要配置較高的並發,但這些並發對Hologres結果表來說可能是冗餘的,還可能佔用大量的串連數,此時可以參考作業資源配置,選擇專家模式,為寫入運算元單獨設定合適且較小的並發,從而降低總串連數的使用。
常見報錯
報錯:ERPC TIMEOUT
或者ERPC CONNECTION CLOSED
報錯現象:出現
com.alibaba.blink.store.core.rpc.RpcException: request xx UpsertRecordBatchRequest failed on final try 4, maxAttempts=4, errorCode=3, msg=ERPC_ERROR_TIMEOUT
報錯。可能原因:寫入時壓力過大寫入失敗或者叢集比較繁忙,可以觀察Hologres執行個體的CPU負載是否打滿。
CONNECTION CLOSED
可能是負載過大導致後端節點掛掉了,出現OOM(Out Of Memory)或者Coredump。解決方案:請先重試寫入,如果不能恢複請找Hologres技術支援人員排查原因。
報錯:BackPresure Exceed Reject Limit
可能原因:通常是Hologres後端寫入壓力過大,導致Memtable來不及刷盤導致寫入失敗。
解決方案:如偶發失敗可忽略該問題,或者Sink加上參數rpcRetries = '100' 來調大寫入重試次數。如果一直報該錯誤,請聯絡Hologres技術支援人員確認後端執行個體狀態。
報錯:The requested table name xxx mismatches the version of the table xxx from server/org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.Caused by: java.net.SocketTimeoutException: Read timed out
可能原因:通常是使用者做了Alter Table導致Blink寫入所帶表的Schema版本號碼低於Server端版本號碼導致的,並且超過了用戶端的重試次數。
解決方案:如偶發報錯可忽略該問題。如果一直報該錯誤,請聯絡Hologres技術支援人員。
報錯:Failed to query table meta for table
可能原因:一種可能是使用者讀寫了一張Hologres的外部表格,Hologres Connector不支援讀寫外部表格。如果不是,可能是Hologres執行個體 Meta出現了問題。
解決方案:請聯絡Hologres技術支援人員。
報錯:Cloud authentication failed for access id
可能原因:該報錯通常是使用者配置的AccessKey資訊不對,或者使用者沒有添加帳號至Hologres執行個體。
解決方案:
請檢查當前賬戶的AccessKey ID和AccessKey Secret填寫是否正確,一般是AccessKey Secret錯誤或者有空格。
檢查不出原因可以用當前AccessKey串連HoloWeb(使用帳號密碼方式登入),在測試聯通性時看報錯是什麼,還是一樣的報錯說明AccessKey有問題,如果報錯為
FATAL:role“ALIYUN$xxxx“does not exist
說明帳號沒有執行個體的許可權,需要管理員給該帳號授予許可權。
Hologres維表Join不到資料
可能原因:Hologres維表使用了分區表,Hologres維表暫不支援分區表。
解決方案:請將分區錶轉為普通表。
報錯:Modify record by primary key is not on this table
可能原因:即時寫入的時候選擇了更新模式,但是Hologres的結果表沒有主鍵。
解決方案:請設定主鍵。
報錯:shard columns count is no match
可能原因:寫入Hologres的時候,沒有寫入完整的Distribution Key的列(預設是主鍵)。
解決方案:請寫入完整的Distribution Key列。
報錯:Full row is required, but the column xxx is missing
可能原因:Hologres老版本的報錯資訊,通常是使用者沒有寫某列資料,而那一列是不可為空的。
解決方案:請為不可為空的列賦值。
VVP使用者讀寫Hologres導致JDBC串連數暴漲
可能原因:VVP Hologres Connector讀寫Hologres(除了Binlog),採用JDBC模式,最大佔用
讀寫Hologres表數量*並發度 * connectionSize(VVP表的參數,預設為3)
個串連。解決方案:合理規劃任務串連數,降低並發度或者connectionSize。如無法調低並發度或connectionSize,可以為表設定參數useRpcMode = 'true' 切回至Rpc模式。
Blink/VVP使用者讀寫Hologres報錯顯示無法串連Hologres
可能原因:Blink/VVP叢集預設訪問公網很慢或者無法訪問。
解決方案:需要保證和Hologres執行個體在相同Region,且使用VPC的Endpoint。
報錯:Hologres rpc mode dimension table does not support one to many join
可能原因:Blink和VVP的RPC模式維表必須是行存表,且Join的欄位必須是主鍵,報錯的原因往往是以上兩個條件不滿足
解決方案:建議使用JDBC模式,且維表使用行存表或者行列共存表。
報錯:DatahubClientException
報錯現象:出現
Caused by: com.aliyun.datahub.client.exception.DatahubClientException: [httpStatus:503, requestId:null, errorCode:null, errorMessage:{"ErrorCode":"ServiceUnavailable","ErrorMessage":"Queue Full"}]
報錯。可能原因:大量消費Binlog作業由於某種原因同時重啟導致線程池被佔滿。
解決方案:分批進行消費Binlog作業。
報錯:Error occurs when reading data from datahub
報錯現象:出現
Error occurs when reading data from datahub, msg: [httpStatus:500, requestId:xxx, errorCode:InternalServerError, errorMessage:Get binlog timeout.]
報錯。可能原因:Binlog每條資料太大,乘上攢批之後,每個RPC請求的大小超過最大限制。
解決方案:在每行資料欄位較多且有很長的字串等欄位時,可以減小攢批配置。
報錯:Caused by: java.lang.IllegalArgumentException: Column: created_time type does not match: flink row type: TIMESTAMP(6) WITH LOCAL TIME ZONE, hologres type: timestamp
可能原因:在Flink中欄位使用了TIMESTAMP(6)類型,當前不支援映射至Hologres。
解決方案:修改欄位類型為TIMESTAMP。
報錯:Caused by: org.postgresql.util.PSQLException: FATAL: Rejected by ip white list. db = xxx, usr=xxx, ip=xx.xx.xx.xx
可能原因:在Hologres中設定了IP白名單,但是白名單中未包含Flink訪問Hologres的IP地址,所以Flink訪問Hologres時被阻止。
解決方案:在Hologres的IP白名單中增加Flink的IP,詳情請參見IP白名單。
報錯:Caused by: java.lang.RuntimeException: shaded.hologres.com.aliyun.datahub.client.exception.DatahubClientException: [httpStatus:400, requestId:xx, errorCode:TableVersionExpired, errorMessage:The specified table has been modified, please refresh cursor and try again
可能原因:使用者對源表進行了DDL操作,Table Version發生變化,導致消費失敗。
解決辦法:升級Flink版本到4.0.16及以上,會對此情況進行重試。
Binlog作業啟動時拋出Shard ID不存在的異常
可能原因:所消費表的Shard數發生了變化,可能是使用者對錶進行了重新命名等操作,作業從checkpoint恢複時使用的舊錶的Shard資訊。
解決辦法:重建表等操作之後,checkpoint中儲存的Binlog消費點位資訊已經沒有意義,請無狀態重新啟動作業。
報錯:ERROR,22021,"invalid byte sequence for encoding ""UTF8"": 0x00"
可能原因:維表點查時,使用的主鍵(字串類型)中包含非UTF-8編碼的字元,導致SQL執行失敗。
解決辦法:在上遊對髒資料進行處理。
報錯:hologres.org.postgresql.util.PSQLException: ERROR: syntax error
可能原因:JDBC模式消費Binlog表時需要指定Slot,發生此報錯可能是建立的Slot名稱中有不支援的字元(只支援小寫字母、數字和底線)。
解決辦法:重新建立Slot,或者使用VVR-6.0.7版本自動建立Slot功能。
報錯:create table hologres.hg_replication_progress failed
可能原因:JDBC消費Binlog時可能需要
hg_replication_progress
表(當前資料庫中不存在此表)時,需要建立此表,但執行個體可以建立的Shard數已經達到上限,導致建立失敗報錯。解決辦法:清理無用的資料庫。
異常:作業運行時卡住,通過thread dump
等可以看到卡在JDBC Driver載入處,通常是Class.forName
等位置
可能原因:JDK 8在載入JDBC驅動程式會進行一些靜態初始化操作,而多線程同時載入時可能會發生競爭條件。
解決辦法:可以進行重試,或者使用6.0.7版本的Connector,對此類情況做了處理。
異常:使用JDBC模式消費Binlog時,拋出no table is defined in publication或者The table xxx has no slot named xxx異常
可能原因:刪除表並重建同名表時,和表綁定的Publication沒有被刪除。
解決辦法:當發生此異常時,可以在Hologres中執行
select * from pg_publication where pubname not in (select pubname from pg_publication_tables);
語句查詢未被一起清理的Publication,並執行drop publication xx;
語句刪除殘留的publication,之後重新啟動作業即可。
報錯:作業上線時拋出“permission denied for database”的異常
可能原因:Hologres V1.3和V2.0版本的JDBC模式消費Binlog,需要進行許可權配置。
解決辦法:建議升級Hologres到V2.1版本,使用VVR-8.0.5版本及以上的connector,僅需要表的唯讀許可權就可以消費Binlog。如果不方便升級,請參考使用限制的賦權操作。
報錯:table writer init failed: Fail to fetch table meta from sm
可能原因:對錶進行truncate或者rename操作之後進行寫入。
解決辦法:偶發可以忽略,作業failover之後會自行恢複。Hologres V2.1.1到V2.1.14版本FE節點增加了replay緩衝時間,導致同一個DDL後再DML,DDL replay會變慢。類似異常出現機率可能提高,建議升級到V2.1最新版本。
異常:本地使用connector依賴開發Datastream作業過程中,出現類似java.lang.ClassNotFoundException: com.alibaba.ververica.connectors.hologres.binlog.source.reader.HologresBinlogRecordEmitter的異常
可能原因:阿里雲Realtime ComputeFlink版的商業版連接器JAR包中不提供部分運行類。
解決辦法:參考本地運行和調試包含連接器的作業文檔調整依賴,可以正常調試開發。
異常:JDBC模式消費Binlog,出現Binlog Convert Failed異常,或者部分shard的資料讀取停止在某個時刻。
可能原因:Hologres執行個體的Gateway收到後端逾時的異常資訊時,將異常返回給用戶端的過程中會存在問題,導致讀取數據卡住或資料解析失敗報錯。
解決辦法:一般只有在作業反壓時會出現,如果作業存在資料讀取卡住的問題,可以選擇重啟作業並從最近的checkpoint恢複。要徹底解決該問題,需要將Hologres版本升級到2.2.21及以上版本。