2 回答
TA贡献1847条经验 获得超11个赞
我实际上会从两个角度来解决这个问题。
使用 Envers 获得的好处之一是您可以非常快速地注释您的实体并准确告诉框架您希望如何跟踪实体模型的更改。更好的是,您可以让 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 集群不可用或过载时为用户提供审计历史数据,而不是给用户一个“服务不可用,稍后再回来”的响应。
无论您做出什么决定,性能都不是唯一令人担忧的因素。您还应该注意用户体验、可扩展性和可靠性;因此,为什么我认为最佳解决方案是将两者配对。
添加回答
举报