簡體   English   中英

跨 EC Core 上下文同步大型數據庫表的最佳方法是什么?

[英]What is the best approach to synchronizing large database tables across EC Core contexts?

我的情景

我有三個倉庫數據庫(Firebird),編號為123 ,每個共享相同的方案和相同的 DbContext 類。 以下是 Products 表的模型:

public class Product
{
    public string Sku { get; }
    public string Barcode { get; }
    public int Quantity { get; }
}

我還有一個本地“倉庫緩存”數據庫 (MySQL),出於緩存原因,我想在其中定期下載所有三個倉庫的內容。 緩存產品的數據模型類似,只是增加了一個數字表示源倉庫索引。 此表應包含所有三個倉庫的所有產品信息。 如果一個產品同時出現在倉庫13 (相同的 Sku)中,那么我希望在本地 Cache 表中有兩個條目,每個條目都有對應的倉庫 ID:

public class CachedProduct
{
    public int WarehouseId { get; set; } // Can be either 1, 2 or 3
    public string Sku { get; }
    public string Barcode { get; }
    public int Quantity { get; }
}

這個問題有多種可能的解決方案,但考慮到我的數據集的大小(每個倉庫約 20k 個條目),它們似乎都不可行或有效,我希望有人能給我一個更好的解決方案。

問題

如果本地緩存數據庫是空的,那很容易。 只需從所有三個倉庫下載所有產品,並將它們轉儲到緩存數據庫中。 但是,在隨后的同步中,緩存 DB 將不再為空。 在這種情況下,我不想再次添加所有 60k 產品,因為這將極大地浪費存儲空間。 相反,我想將傳入的數據“更新”到緩存中,這樣新產品就會正常插入,但是如果緩存中已經存在產品(匹配SkuWarehouseId ),那么我只想更新相應的記錄(例如,自上次同步以來,其中一個倉庫中的數量可能已更改)。 這樣,沒有。 緩存數據庫中的記錄數總是三個倉庫的總和; 永遠不會多,永遠不會少。

到目前為止我嘗試過的事情

貪心法:這可能是最簡單的一種。 對於每個倉庫中的每個產品,檢查緩存表中是否存在匹配記錄。 如果是則update ,否則insert 明顯的問題是沒有辦法對其進行批處理/優化,這將導致在每次同步時執行數以萬計的selectinsertupdate調用。

:Clearing the Cache:每次同步前清除本地緩存DB,重新下載所有數據。 我對這個問題的看法是,它會在沒有可用緩存數據的情況下留下一小段時間,這可能會導致應用程序的其他部分出現問題。

使用 EF-Core“Upsert”庫:這似乎是FlexLabs.Upsert庫最有前途的庫,因為它似乎支持批處理操作。 不幸的是,圖書館似乎壞了,因為我什至無法讓他們自己的最小示例正常工作。 無論匹配規則如何,每個“upsert”都會插入一個新行。

完全避免 EF Core:我發現了一個名為Dotmim.Sync的庫,它似乎是一個 DB 到 DB 同步庫。 這樣做的主要問題是倉庫正在運行該庫似乎不支持的 FirebirdDB。 另外,我不確定是否可以進行數據轉換,因為我必須在將行添加到緩存數據庫之前添加WarehouseId列。


有沒有辦法在 EF Core 中盡可能高效地做到這一點?

這里有幾個選項。 哪些可行取決於您對緩存的陳舊約束。 緩存必須始終 100% 反映倉庫狀態,否則它會在一段時間內不同步。

首先,您絕對不應該為此使用 EFCore,除非可能作為客戶端庫來執行原始 SQL。 EfCore 針對許多小型交易進行了優化。 它不適用於批處理工作負載。

“最佳”選項可能是基於事件的系統。 Firebird 支持向事件監聽器發送事件,然后它會根據事件更新緩存。 這里的風險是,如果事件處理失敗,您可能會失去同步。 您可以通過使用某種事件總線(Rabbit、Kafka)來降低這種風險,但 Firebird 事件處理本身就是薄弱環節。

如果緩存可以處理某些不一致,您可以將到期時間戳附加到每個緩存條目。 您的應用程序會命中緩存,如果過期日期已過,它會重新檢查倉庫 dbs。 根據更新真實數據庫源的業務流程,您可能還可以破壞緩存條目(例如,如果有一個訂單管理系統,它可以在有人下訂單時破壞訂單項的緩存)。

如果您必須批量同步,請執行交換表。 設置一個包含實時緩存數據的表,一個加載新緩存數據的單獨表,以及應用程序中的一個標志,說明你從哪個讀取。 您在加載到 B 時從表 A 中讀取,然后在加載完成后,您切換到從表 B 中讀取。

現在,我最終選擇了一個完全在 EF Core 中的簡單而有效的解決方案。

對於每個緩存條目,我還維護一個 SyncIndex 列。 在同步期間,我從所有三個倉庫下載所有產品,將SyncIndex設置為max(cache.SyncIndex) + 1 ,並將它們轉儲到緩存數據庫中。 然后我使用舊的SyncIndex從緩存中刪除所有條目。 這樣我總是有一些可用的緩存數據,我不會浪費很多空間,而且速度也可以接受。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM