使用Avro處理不相容的架構變動 - Elliot

banq發表於2022-03-22

Apache Avro有資料結構模式相容性的概念,它允許我們確定一個資料結構是否與一個或多個較早或較新的資料結構在某些相容性約束方面相容。我們可以有相容的變化,這必然意味著我們也可以有不相容的變化。
在這種情況下,我們可以做什麼來實現這些破壞性的變化,同時儘量減少對消費者的干擾,不管是流媒體還是批處理。
 
假設我們有一個業務需求,我們需要把一個包含複合全名的字串欄位,變成一個有記錄封裝的獨立名字元素的欄位。從字串到記錄的轉變顯然是一個狀態的變化。
當前狀態:

record Person {
   string name; // example: "Joan Smith"
}


最終的變化狀態:

record Person {
   Name name;
}
record Name {
   string first_name; // example: "Joan"
   string last_name;  // example: "Smith"
}


第1步 - 新增一個預設值
你可以刪除有預設值的欄位,所以我們現在新增一個預設值,以便以後可以刪除該欄位。選擇一個預設值,這個預設值在消費者系統中沒有任何意義,以後可以用來識別這個欄位是廢棄的。繼續為你的消費者用資料填充該欄位。

record Person {
   string name = "<DEPRECATED>"; // example: "Joan Smith"
}

 

第2步 - 引入新的欄位(可能有一個預設值)
我們正在引入我們在最終狀態下想要的欄位。但是我們還不能使用所需的欄位名,因為它將被過載。
此外,對於FORWARDS或FORWARDS_TRANSITIVE以外的相容模式,我們必須提供一個預設值。
生產者應該用有效的資料來填充這兩個欄位--現有的和新的。現在向所有消費者傳達他們應該開始使用新欄位。

record Person {
   string name        = "<DEPRECATED>"; // example: "Joan Smith"
   Name   person_name = {"first_name":"<NOT_IN_USE>","last_name":"<NOT_IN_USE>"};
}
record Name {
   string first_name; // example: "Joan"
   string last_name;  // example: "Smith"
}

 

第3步 - 刪除舊欄位
因為我們的舊欄位有一個預設值,而且現在沒有消費者在使用它--我們現在可以刪除它。

record Person {
   Name person_name = {"first_name":"<NOT_IN_USE>","last_name":"<NOT_IN_USE>"};
}
record Name {
   string first_name; // example: "Joan"
   string last_name;  // example: "Smith"
}

 

第4步 - 刪除預設值
現在我們可以從新欄位中刪除預設值。請注意,這不適用於FORWARDS,因為該欄位可以在步驟2中宣告,而沒有預設值。

record Person {
   Name person_name;
}
record Name {
   string first_name; // example: "Joan"
   string last_name;  // example: "Smith"
}

 
 

第5步 - 重新命名欄位
最後,我們可以通過提供一個帶有所需名稱的別名來有效地重新命名它。

record Person {
   @aliases(["name"])
   Name person_name;
}
record Name {
   string first_name; // example: "Joan"
   string last_name;  // example: "Smith"
}


 

相關文章