高效的审计方法

a_g*_*man 5 java performance audit spring-boot javers

我正在尝试为我的 Spring Boot 应用程序实现审计层。到目前为止,我尝试了两种方法。

1) 创建了 1 个审计表,其中包含字段 user_name、table_name、column_name、old_value、new_value、uuid、event_type。

每当保存任何更改时,填充审核实体并保存它。

优点:

  • 快的

  • 由于只有 1 个审核表,易于管理

下降:

  • 有时它涉及太多从业务实体到审计实体的映射

  • 必须从数据库获取旧值以填充审计实体

  • 手动创建审核实体
  • 检索可能很痛苦

2)使用javers进行审计

优点:

  • 自动创建和更新审计实体

  • 需要管理的表数量更少

  • 不需要旧值检索

下降:

  • 由于交易规模很大,花费的时间太多

基准

处理具有 20 列(字段)的表(实体)中的 10 行,

使用方法 1 所花费的时间:24328 ms => 24 s

使用方法 2 所花费的时间:311292 ms => 311 s(近 12 倍)


3)没有使用Hibernate envers,因为创建的表数量会很高

考虑到上述优点和缺点,有人可以提出更好的审计想法吗?我们的目标是,

  • 需要管理的表数量更少

  • 更少的响应时间

  • 模块化审计层,自动化程度高于手动程度

每个表中有 10 到 25 列。

Cod*_*ale 2

正如您所说,创建审计跟踪的常见方法是应用程序端库,例如 envers 或 Javers。这些被挂接到持久性库中,它们\xe2\x80\x99d维护数据表中的特定列(“createdBy”、“lastUpdated”等),和/或将早期记录版本复制到某种形式的历史记录中表。

\n\n

不过,这样做也有一些缺点:

\n\n
    \n
  • 作为 OLTP 事务的一部分在历史表中写入记录会增加事务中执行的语句数量 -> 可能会导致应用程序的响应时间更长

  • \n
  • 支持批量更新和删除

  • \n
  • 无法跟踪直接在数据库中进行的更改

  • \n
\n\n

只需 3 步即可更改数据捕获

\n\n
    \n
  1. 捕获变更数据
  2. \n
  3. 将更改数据转换为目标数据库支持上传的格式
  4. \n
  5. 将数据上传到目标数据库
  6. \n
\n\n

通过数据库触发器更改数据捕获

\n\n

另一种技术是数据库触发器。它们不会错过任何操作,无论是从应用程序还是数据库本身发出的。批量语句也将被处理。\n基于触发器的 CDC 的另一个优点是应用程序不会意识到您已添加整个审核层的事实。\n不利的一面是,作为 OLTP 事务的一部分执行触发器时,仍然存在延迟增加的问题。

\n\n

触发器的替代解决方案(此处为 Postgresql):\n使用逻辑复制将数据库更改(解码的 WAL 消息)从 MASTER 服务器流式传输到使用 WAL\xe2\x80\x99s 的从服务器,并启用审核触发器以捕获对复制表的更改从属服务器。

\n\n

通过基于日志的方法更改数据捕获

\n\n

当利用作为transaction log审计源并使用更改数据捕获来检索更改信息并将其发送到消息代理或基于持久日志(例如Apache Kafka. 通常被认为是更改数据捕获的最佳方法,但不是最简单的设置解决方案。

\n\n

CDC 进程异步运行,可以提取变更数据,而不会影响 OLTP 事务。

\n\n

每当有数据更改时,就会将一个条目添加到事务日志中。

\n\n

\xe2\x80\x99 将为批量操作中更新或删除的每条记录提供一个日志条目,因此可以为每条记录生成一个更改事件。

\n\n

仍然存在的问题是 CDC 如何访问元数据,例如执行数据更改的应用程序用户、他们的 IP 地址、跟踪范围 ID 或任何类型的相关 ID。

\n\n

一种方法是使用一个单独的表来存储此元数据。应用程序可以在该表中为每个事务存储一条具有特定transactionId. 数据更改事件将包含链接到更改的 transactionID,以便数据更改事件和元数据记录可以相互关联。

\n