易倉跨境Saas全球租戶,如何做到資料秒級響應?

阿里雲大資料AI技術發表於2022-05-12

前言

易倉科技 成立於 2013 年,致力於構建智慧協同的跨境網路,讓全球貿易更輕鬆。經過 9 年的積累沉澱,產業鏈 SaaS+ 生態鏈協同的服務模式,已發展成為跨境電商行業的頭部企業。目前租戶分佈全球,資料來自各大洲,彙集國外各大電商平臺各個站點銷售資料。 面對這種資料體量大,跨全球各區域的複雜場景易倉大資料團隊是如何做到秒級響應的?


問 題 QUESTION

資料分佈三大洲,如何集中統一計算?


Saas 租戶資料庫級別物理隔離,分系統分庫分表,百萬張表如何同步?
(1) A 客戶, A 系統,兩個庫總共 1000+ 張表與 B 客戶, A 系統同樣的 1000+ 張表

(2) Saas 租戶不同套餐保護不同功能系統,各系統表數量在100、200到500張不等

(3) A B 客戶在同系統在同一個資料庫例項與單客戶單資料庫例項( rds 例項, polarDB 例項)

(4)  幾百個資料庫例項分佈在不同地域,不同國家

如何在保證資料準確的基礎上達到毫秒級別同步入倉?


技術選型

針對以上問題的特殊性,複雜性,我們在技術選型上做了大量的調研以及深度測試,並與雲服務團隊深度交流做出了大量最佳化。


一、對於問題①②,資料分佈以及多租戶多庫多表,如何處理?



1.租戶資料庫分佈在阿里雲rds以及polarDB的幾百個例項,分散在國內外各大Region,dts同時支援全庫全表同步以及可選擇庫表。單個dts同步表數量沒有限制,高度匹配易倉複雜的業務場景,在實施過程的功能以及效能最佳化是問題解決關鍵。


2.dts資料同步將國內外資料集中實時同步到統一華南區域的Kafka,保證資料準確,時效在毫秒級別。


二、資料準確毫秒級別同步入倉,關鍵點在 Flink的高併發 pipeline處理資料,時延毫秒級,且兼具可靠性


3.由Flink實時消費Kafka數寫到實時數倉Hologres。


4.藉助Maxcompute(下文簡稱MC)與實時數倉Hologres的互通能力,完成複雜的分析計算。

遇到的坑

1.DTS規格預估不準導致資料同步不穩定且沒有及時的告警機制無法及時處理,無法保證資料準確性。


2.底層數倉建模不清晰,對於物理刪除的客戶資料資料中心採用邏輯刪除進行標記後利用MC進行合併計算,以至於跟資料來源無法一比一比對。無法判斷資料同步的準確性。


3.以上導致了頻繁的客戶資料重推,資料初始化,以至於Kafka資料大量堆積Flink消費不及時。


4.以上步驟環環相扣,陷入資料異常同步的死迴圈,導致資料不可用。


如何解決

1.根據資料庫例項實際RPS採用DTS對應的規格,推動DTS完善告警機制。資料同步穩定性實時性都大幅度提高。

(1) 推動DTS團隊解決百萬表級別數量的Api介面支援,開發互相支援快速迭代

(2) 定位大資料量表初始化任務頻繁重啟問題,最佳化dts任務後設資料儲存邏輯策略


2.資料貼源層跟資料庫一比一,重構底層設計方案,每個資料原表在原建表基礎上透過sharing_seq、db_seq、company_code加上原表的主鍵組成唯一索引構成資料中心的目的表。




-- 租戶源表


CREATE 
TABLE 
`erp_test` (

  
`id` 
int(
11NOT 
NULL AUTO_INCREMENT,

  
`d_key` 
varchar(
50NOT 
NULL 
DEFAULT 
'' 
COMMENT 
'字典key',

  
`d_val` 
varchar(
100NOT 
NULL 
DEFAULT 
'' 
COMMENT 
'字典val',

  
`d_desc` 
varchar(
100NOT 
NULL 
DEFAULT 
'' 
COMMENT 
'字典描述',

  
`ec_update_time` datetime 
NOT 
NULL 
DEFAULT 
CURRENT_TIMESTAMP 
ON 
UPDATE


CURRENT_TIMESTAMP 
COMMENT 
'更新時間',

  
`ec_create_time` datetime 
NOT 
NULL 
DEFAULT 
CURRENT_TIMESTAMP 
COMMENT 
'建立時


間',

  PRIMARY 
KEY (
`id`),

  
KEY 
`idxx_ec_update_time` (
`ec_update_time`),

  
KEY 
`idxx_ec_create_time` (
`ec_create_time`)

ENGINE=
InnoDB AUTO_INCREMENT=
3 
DEFAULT 
CHARSET=utf8 
COMMENT=
"erp_test表';



-- 資料中心目的表 CREATE TABLE `erp_test` (  `sharing_seq` text,  `db_seq` text,  `company_code` text,  `id` bigint NOT NULL,  `d_desc` text,   `d_key` text,   `d_val` text,   `ec_create_time` timestamptz,   `ec_update_time` timestamptz ,PRIMARY KEY (`sharing_seq`, `db_seq`, `company_code`, `id`) );


3 . Flink 核心程式碼邏輯最佳化,達到資料一比一還原資料庫大量的新增、更新以及物理刪除操作。資料可對比,有跡可循。透過大量資料對比,資料準確可靠並且實時性達到秒級


    
    
    
    class 
    DtsToDataworksHoloStream(fromSource: TSource[JSONObject], toSink: TSink[JSONObject]) extends TStream[JSONObject, JSONObject] {
    
      
    override 
    val source: TSource[JSONObject] = fromSource
    
      
    override 
    val sink: TSink[JSONObject] = toSink
    
    
    
      override protected def transform(dataStream: DataStream[JSONObject], others: DataStream[_]*): DataStream[JSONObject] = {     val parallelism: Int = AppUtil.env.getParallelism     val confStream: DataStream[mutable.Map[String, DbInfo2DataworksHoloBean]] = others.head.asInstanceOf[DataStream[mutable.Map[String, DbInfo2DataworksHoloBean]]]     //獲取各租戶廣播配置資訊     val confStreamDescriptor = new MapStateDescriptor[String, DbInfo2DataworksHoloBean]( "DtsConfig", classOf[String], classOf[DbInfo2DataworksHoloBean])     val confBroadcast: BroadcastStream[mutable.Map[String, DbInfo2DataworksHoloBean]] = confStream.broadcast(confStreamDescriptor)     //Dts推送kafka的canalJson與租戶廣播配置connect     val result: DataStream[JSONObject] = dataStream.connect(confBroadcast).process(new Dts2DataworksHoloTransformFunction)    .keyBy(_.getString( "table").hashCode % parallelism).map(s => s)    result  } }
    //還原資料庫增刪改 def upsertOrDelTable(tableName: String, data: Array[(String, Any)], opType: String): Unit = {     val put = new Put(holoclient.getTableSchema(tableName))     if (opType == "DELETE") {      put.getRecord.setType(SqlCommandType.DELETE)    }     for (kv <- data) {      put.setObject(kv._1.toLowerCase, kv._2)    }    holoclient.put(put)  }


    億萬資料量級的業務訂單表,實現了從資料來源端到資料中心的業務延遲控制在毫秒級別,基於此資料中心秒級別的業務響應更是不在話下。


    後 記

    DTS 團隊針對易倉複雜的單例項多租戶場景最佳化:


    1 .單例項多租戶數 10 萬張表初始化, DTS 提供的 API 介面完全無法滿足需求!

    問題排查:表數量太大,介面引數體超過 nginx 閘道器限制, tomcat 限制。限制調整後仍然無法滿足。

    最後解決:開發新 Api 介面,經過與 dts 開發反覆聯調,最終採用 oss 檔案中轉方式繞過閘道器,實現 10 萬級別表的初始化推送。

    2 . DTS 例項單次初始化表資料了限制以及 DTS 後設資料策略最佳化

    問題排查:單次初始化表達到一定限制, dts 對應的 reader 模組記憶體溢位。任務無限重啟,延遲逐步增大。

    最後解決: dts 開發日夜堅守,出現問題快速響應,臨時調大 reader 模組記憶體並排查根本原因,最後專門針對 SaaS 這種多表的場景在後設資料儲存策略方面進行了大量最佳化並徹底解決問題。


    注:

    Flink :一個批處理和流處理結合的統一計算框架

    Hologres :一站式實時數倉引擎( Real-Time Data Warehouse

    Maxcompute :大資料計算服務,快速、完全託管的 PB 級資料倉儲解決方案



    來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70004426/viewspace-2893711/,如需轉載,請註明出處,否則將追究法律責任。

    相關文章