2 回答

TA貢獻1847條經驗 獲得超11個贊
我實際上會從兩個角度來解決這個問題。
使用 Envers 獲得的好處之一是您可以非??焖俚刈⑨屇膶嶓w并準確告訴框架您希望如何跟蹤實體模型的更改。更好的是,您可以讓 Envers 自動為您生成 diffable 字段。
讓我們來看看這個基本實體:
@Entity
@Audited(withModifiedFlag = true)
public class Person {
@Id
@GeneratedValue
private Integer id;
private String name;
}
當您啟用該withModifiedFlag功能時,這會通知 Envers 將一些額外的元數據列添加到該實體的審計表中,因此該實體的審計表基本上如下所示:
+----+------+----------+-----+---------+
| ID | name | name_MOD | REV | REVTYPE |
+----+------+----------+-----+---------+
這樣做的好處是,如果您使用某些流程直接從表中導出和流式傳輸數據,您不再需要實際區分當前行與前一行來了解發生了什么變化;只需查看關聯的_MOD列是1(true) 還是0(false),模式就會自動告訴您這一點。
從這一點開始,您有幾個選擇。
本機查詢 ETL
您可以使用 Hibernate 本機查詢通過某個后臺應用程序線程或單獨的后臺進程來提取數據并將其轉換為 ES 的 JSON。由于該_MOD列為您提供了字段更改的指示符,因此您可以輕松讀取行并構建必要的數據,而無需在提取時執行差異操作。
我還建議配置 Envers 以將審計對象放在單獨的目錄/模式中。這最大限度地提高了數據庫同時改進跨多個數據庫的磁盤 IO 的能力。
Debezium ETL
Debezium 項目是處理數據復制的絕佳方式。它的強大優勢之一是它使用戶能夠跨完全適合您的模型的異構平臺執行此操作。
這里最大的區別是 Debezium 不直接讀取數據庫來確定更改,而是讀取數據庫事務日志文件并生成一系列事件來描述針對該數據庫發生的 DML 操作。簡而言之,您避免了您非常關心的讀取操作,因為 Debezium 直接從事務日志中重新水化狀態。
舉個例子:
休眠執行
INSERT INTO Person (?,?) VALUES (?,?)
。Hibernate Envers 執行
INSERT INTO Person_AUD (...) VALUES (....)
數據庫將該操作寫入重做/事務日志。
Debezium 注意到日志已寫入,然后讀取條目。
Debezium 為
Person_AUD
(訂閱的表)生成一個插入事件。該事件的任何注冊相關方都會收到并處理它。
在 (5) 中,您的轉換/加載代碼將存在以接收該插入事件并生成 JSON 輸出并將其發送到 ES。
包起來
通過使用 Debezium,您能夠以極其高效的方式有效地離線復制異構環境中的數據。該項目不僅非常適合您的用例,而且在當今微服務架構的現代世界中非常有價值,其中服務之間的數據共享至關重要。
通過使用 Envers,您能夠提供在線回退解決方案,在您的 ES 集群不可用或過載時為用戶提供審計歷史數據,而不是給用戶一個“服務不可用,稍后再回來”的響應。
無論您做出什么決定,性能都不是唯一令人擔憂的因素。您還應該注意用戶體驗、可擴展性和可靠性;因此,為什么我認為最佳解決方案是將兩者配對。
添加回答
舉報