本文為您介紹使用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及以上版本可以選擇行列混存表。
云監控查看實例的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
。連接復用
實時計算1.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代表來自實時計算Flink的讀寫連接。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的異常
可能原因:阿里云實時計算Flink版的商業版連接器JAR包中不提供部分運行類。
解決辦法:參考本地運行和調試包含連接器的作業文檔調整依賴,可以正常調試開發。
異常:JDBC模式消費Binlog,出現Binlog Convert Failed異常,或者部分shard的數據讀取停止在某個時刻。
可能原因:Hologres實例的Gateway收到后端超時的異常信息時,將異常返回給客戶端的過程中會存在問題,導致讀取數據卡住或數據解析失敗報錯。
解決辦法:一般只有在作業反壓時會出現,如果作業存在數據讀取卡住的問題,可以選擇重啟作業并從最近的checkpoint恢復。要徹底解決該問題,需要將Hologres版本升級到2.2.21及以上版本。