

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# QLDB 在 Kinesis 中流记录
<a name="streams.records"></a>

**重要**  
终止支持通知：现有客户将能够使用 Amazon QLDB，直到 2025 年 7 月 31 日终止支持。有关更多详细信息，请参阅[将亚马逊 QLDB 账本迁移到亚马逊 Aurora PostgreSQL](https://aws.amazon.com/blogs/database/migrate-an-amazon-qldb-ledger-to-amazon-aurora-postgresql/)。

*Amazon QLDB 流向给定的 Amazon Kinesis Data Streams *资源*写入三种类型的数据记录：控件、*区块摘要*和修订详情*。所有三种记录类型均以 [Amazon Ion 格式](ion.md)的*二进制表示*形式写入。

控制记录显示您的 QLDB 流的开始和完成。每当有修订提交到您的日记账时，QLDB 流都会写入所有相关的日记账块数据，包括块摘要和修订详细信息记录。

这三种记录类型是多态的。它们都由一条通用的顶级记录组成，其中包含 QLDB 流 ARN、记录类型和记录有效载荷。此顶级记录采用以下格式。

```
{
  qldbStreamArn: string,
  recordType: string,
  payload: {
    //control | block summary | revision details record
  }
}
```

`recordType` 字段可能具有三个值：
+ `CONTROL`
+ `BLOCK_SUMMARY`
+ `REVISION_DETAILS`

以下各节描述每个单独有效载荷记录的格式和内容。

**注意**  
QLDB 以 Amazon Ion 的二进制表示形式将所有流记录写入 Kinesis Data Streams。在 Ion 的文本表示形式中提供了以下示例，以可读格式说明记录内容。

**Topics**
+ [控制层面](#streams.records.control)
+ [屏蔽摘要记录](#streams.records.block)
+ [修订详细信息记录](#streams.records.revision)
+ [处理重复和 out-of-order记录](#streams.records.ordering)

## 控制层面
<a name="streams.records.control"></a>

QLDB 流*写入*控制记录以指示其开始和完成事件。以下是每个​​ `controlRecordType` 的控制记录示例，包含样本数据：
+ `CREATED`— QLDB 流写入 Kinesis 的第一条记录，表示您新创建的流处于活动状态。

  ```
  {
    qldbStreamArn:"arn:aws:qldb:us-east-1:123456789012:stream/exampleLedger/IiPT4brpZCqCq3f4MTHbYy",
    recordType:"CONTROL",
    payload:{
      controlRecordType:"CREATED"
    }
  }
  ```
+ `COMPLETED`— QLDB 流写入 Kinesis 的最后一条记录，表示您的流已到达指定的结束日期和时间。如果您取消流，则不会写入此记录。

  ```
  {
    qldbStreamArn:"arn:aws:qldb:us-east-1:123456789012:stream/exampleLedger/IiPT4brpZCqCq3f4MTHbYy",
    recordType:"CONTROL",
    payload:{
      controlRecordType:"COMPLETED"
    }
  }
  ```

## 屏蔽摘要记录
<a name="streams.records.block"></a>

*区块摘要*记录表示提交您的文档修订的日记账区块。[区块](journal-contents.md)是在事务过程中提交到您的 QLDB 日记账的对象。

区块摘要记录的有效载荷包含提交块的块地址、时间戳和其他元数据。它还包括块中修订的摘要属性以及提交这些修订的 PartiQL 语句。以下是包含示例数据的区块摘要记录的示例。

**注意**  
此区块摘要示例仅供参考。显示的哈希值并非实际计算的哈希值。

```
{
  qldbStreamArn:"arn:aws:qldb:us-east-1:123456789012:stream/exampleLedger/IiPT4brpZCqCq3f4MTHbYy",
  recordType:"BLOCK_SUMMARY",
  payload:{
    blockAddress:{
      strandId:"ElYL30RGoqrFCbbaQn3K6m",
      sequenceNo:60807
    },
    transactionId:"9RWohCo7My4GGkxRETAJ6M",
    blockTimestamp:2019-09-18T17:00:14.601000001Z,
    blockHash:{{6Pk9KDYJd38ci09oaHxx0D2grtgh4QBBqbDS6i9quX8=}},
    entriesHash:{{r5YoH6+NXDXxgoRzPREGAWJfn73KlZE0eTfbTxZWUDU=}},
    previousBlockHash:{{K3ti0Agk7DEponywKcQCPRYVHb5RuyxdmQFTfrloptA=}},
    entriesHashList:[
      {{pbzvz6ofJC7mD2jvgfyrY/VtR01zIZHoWy8T1VcxlGo=}},
      {{k2brC23DLMercmiOWHiURaGwHu0mQtLzdNPuviE2rcs=}},
      {{hvw1EV8k4oOkIO36kblO/+UUSFUQqCanKuDGr0aP9nQ=}},
      {{ZrLbkyzDcpJ9KWsZMZqRuKUkG/czLIJ4US+K5E31b+Q=}}
    ],
    transactionInfo:{
      statements:[
        {
          statement:"SELECT * FROM Person WHERE GovId = ?",
          startTime:2019-09-18T17:00:14.587Z,
          statementDigest:{{p4Dn0DiuYD3Xm9UQQ75YLwmoMbSfJmopOmTfMnXs26M=}}
        },
        {
          statement:"INSERT INTO Person ?",
          startTime:2019-09-18T17:00:14.594Z,
          statementDigest:{{klMLkLfa5VJqk6JUPtHkQpOsDdG4HmuUaq/VaApQflU=}}
        },
        {
          statement:"INSERT INTO VehicleRegistration ?",
          startTime:2019-09-18T17:00:14.598Z,
          statementDigest:{{B0gO9BWVNrzRYFoe7t+GVLpJ6uZcLKf5t/chkfRhspI=}}
        }
      ],
      documents:{
        '7z2OpEBgVCvCtwvx4a2JGn':{
          tableName:"Person",
          tableId:"LSkFkQvkIOjCmpTZpkfpn9",
          statements:[1]
        },
        'K0FpsSLpydLDr7hi6KUzqk':{
          tableName:"VehicleRegistration",
          tableId:"Ad3A07z0ZffC7Gpso7BXyO",
          statements:[2]
        }
      }
    },
    revisionSummaries:[
      {
        hash:{{uDthuiqSy4FwjZssyCiyFd90XoPSlIwomHBdF/OrmkE=}},
        documentId:"7z2OpEBgVCvCtwvx4a2JGn"
      },
      {
        hash:{{qJID/amu0gN3dpG5Tg0FfIFTh/U5yFkfT+g/O6k5sPM=}},
        documentId:"K0FpsSLpydLDr7hi6KUzqk"
      }
    ]
  }
}
```

在 `revisionSummaries` 字段，某些修订可能没有 `documentId`。这是仅供内部使用的系统修订版，不包含用户数据。QLDB 流将这些修订包含在各自的区块摘要记录中，因为这些修订的哈希值是日记完整哈希链的一部分。加密验证需要完整的哈希链。

只有具有文档 ID 的修订才会在单独的修订详细信息记录中发布，如下节所述。

## 修订详细信息记录
<a name="streams.records.revision"></a>

*修订详细信息*记录表示提交到您的日记的文档修订。有效载荷包含修订的[提交视图](working.metadata.md)中的所有属性，以及相关的表名称和表ID。以下是带有示例数据的修订记录的示例。

```
{
  qldbStreamArn:"arn:aws:qldb:us-east-1:123456789012:stream/exampleLedger/IiPT4brpZCqCq3f4MTHbYy",
  recordType:"REVISION_DETAILS",
  payload:{
    tableInfo:{
      tableName:"VehicleRegistration",
      tableId:"Ad3A07z0ZffC7Gpso7BXyO"
    },
    revision:{
      blockAddress:{
        strandId:"ElYL30RGoqrFCbbaQn3K6m",
        sequenceNo:60807
      },
      hash:{{qJID/amu0gN3dpG5Tg0FfIFTh/U5yFkfT+g/O6k5sPM=}},
      data:{
        VIN:"1N4AL11D75C109151",
        LicensePlateNumber:"LEWISR261LL",
        State:"WA",
        City:"Seattle",
        PendingPenaltyTicketAmount:90.25,
        ValidFromDate:2017-08-21,
        ValidToDate:2020-05-11,
        Owners:{
          PrimaryOwner:{PersonId:"7z2OpEBgVCvCtwvx4a2JGn"},
          SecondaryOwners:[]
        }
      },
      metadata:{
        id:"K0FpsSLpydLDr7hi6KUzqk",
        version:0,
        txTime:2019-09-18T17:00:14.602Z,
        txId:"9RWohCo7My4GGkxRETAJ6M"
      }
    }
  }
}
```

## 处理重复和 out-of-order记录
<a name="streams.records.ordering"></a>

QLDB 直播可以向 Kinesis Data Streams 发布副本 out-of-order和记录。因此，使用者应用程序可能需要实现自己的逻辑来识别和处理此类场景。区块摘要和修订详细信息记录包括可用于此目的的字段。结合下游服务的特征，这些字段既可以表示记录的唯一身份，也可以表示严格的记录顺序。

例如，假设一个将 QLDB 与索引集成的流，以提供 OpenSearch 对文档的全文搜索功能。在此用例中，您需要避免索引文档的陈旧 (out-of-order) 修订版。要强制执行排序和重复数据删除，您可以使用中的文档 ID 和外部版本字段 OpenSearch，以及修订详细信息记录中的文档 ID 和版本字段。

[有关将 QLDB 与 OpenSearch Amazon Service 集成的示例应用程序中的重复数据删除逻辑示例， GitHub 请参阅存储库 aws-samples/-。amazon-qldb-streaming-amazon opensearch-service-sample-python](https://github.com/aws-samples/amazon-qldb-streaming-amazon-opensearch-service-sample-python)