繁体   English   中英

AWS dynamo db 中的 BatchWrite 跳过一些项目

[英]BatchWrite in AWS dynamo db skipping some items

我正在尝试使用节点 SDK 将项目写入 AWS dynamo 数据库。 我面临的问题是,当我使用线程将批处理项目并行写入 AWS 时,某些项目没有写入数据库。 写入的项目数量是随机的。 例如,如果我运行我的代码 3 次,一次是 150,接下来是 200,第三次可能是 135。此外,当我在没有线程的情况下按顺序编写项目时,即使这样,有些项目没有写。然而,在这种情况下,项目较少丢失。 例如,如果项目总数为 300,则写入的项目为 298。我调查了问题以查看是否有任何未处理的项目,但 batchWrite 方法没有返回任何内容。 这意味着所有项目都被正确处理。 请注意,我为各自的数据库提供OnDemand 配置,因此我预计不会出现任何限制问题。 所以这是我的代码。

 exports.run = async function() {

  **This is the function which runs first !!!!!**

  const data = await getArrayOfObjects();
  console.log("TOTAL PRICE CHANGES")  
  console.log(data.length)
  const batchesOfData = makeBatches(data)
  const threads = new Set();
  console.log("**********")
  console.log(batchesOfData.length)
  console.log("**********")
  for(let i = 0; i < batchesOfData.length; i++) {
    console.log("BATCH!!!!!")
    console.log(i)
    console.log(batchesOfData[i].length)  
    // Sequential Approach
    const response = await compensationHelper.createItems(batchesOfData[i])
    console.log("RESPONSE")
    console.log(response)

    Parallel approach
    // const workerResult = await runService(batchesOfData[i])
    // console.log("WORKER RESUULT!!!!")
    // console.log(workerResult);

  }
}

exports.updateItemsInBatch = async function(data, tableName) {
  console.log("WRITING DATA")
  console.log(data.length)
  const batchItems = {
    RequestItems: {},
  };

  batchItems.RequestItems[tableName] = data;
  try {
    const result = await documentClient.batchWrite(batchItems).promise();
    console.log("UNPROCESSED ITEMS")
    console.log(result)
    if (result instanceof Error) {
      console.log(`[Error]: ${JSON.stringify(Error)}`);
      throw new Error(result);
    }
    return Promise.resolve(true);
  } catch (err) {
    console.error(`[Error]: ${JSON.stringify(err.message)}`);
    return Promise.reject(new Error(err));
  }
};

exports.convertToAWSCompatibleFormat = function(data) {
  const awsCompatibleData = [];
  data.forEach(record => awsCompatibleData.push({ PutRequest: { Item: record } }));
  return awsCompatibleData;
};

const createItems = async function(itemList) {
  try {
    const objectsList = [];
    for (let index = 0; index < itemList.length; index++) {
      try {
        const itemListObj = itemList[index];
        const ObjToBeInserted = {
          // some data assignments here
        };

        objectsList.push(ObjToBeInserted);
        if (
          objectsList.length >= AWS_BATCH_SIZE ||
          index === itemList.length - 1
        ) {
            const awsCompatiableFormat = convertToAWSCompatibleFormat(
              objectsList
            );
            await updateItemsInBatch(
              awsCompatiableFormat,
              process.env.myTableName
            );
        }
      } catch (error) {
        console.log(`[Error]: ${JSON.stringify(error)}`);
      }
    }

    return Promise.resolve(true);
  } catch (err) {
    return Promise.reject(new Error(err));
  }
};

const makeBatches = products => {
  const productBatches = [];
  let countr = -1;
  for (let index = 0; index < products.length; index++) {
    if (index % AWS_BATCH_SIZE === 0) {
      countr++;
      productBatches[countr] = [];
      if (countr === MAX_BATCHES) {
        break;
      }
    }
    try {
      productBatches[countr].push(products[index]);
    } catch (error) {
      continue;
    }
  }
  return productBatches;
};

async function runService(workerData) {
  return new Promise((resolve, reject) => {
    const worker = new Worker(path.join(__dirname, './worker.js'), { workerData });
    worker.on('message', resolve);
    worker.on('error', reject);
    worker.on('exit', (code) => {
      if (code !== 0)
        reject(new Error(`Worker stopped with exit code ${code}`));
    })
  })
}

// My worker file
'use strict';

const { workerData, parentPort } = require('worker_threads')
const creatItems = require('myscripts')
// You can do any heavy stuff here, in a synchronous way
// without blocking the "main thread"
console.log("I AM A NEW THREAD")
createItems(workerData)
// console.log('Going to write tons of content on file '+workerData);
parentPort.postMessage({ fileName: workerData, status: 'Done' })

boto3 文档

如果以下一项或多项为真,DynamoDB 将拒绝整个批量写入操作:

One or more tables specified in the BatchWriteItem request does not exist.
Primary key attributes specified on an item in the request do not match those in the corresponding table's primary key schema.
You try to perform multiple operations on the same item in the same BatchWriteItem request. For example, you cannot put and delete the same item in the same BatchWriteItem request.
Your request contains at least two items with identical hash and range keys (which essentially is two put operations).
There are more than 25 requests in the batch.
Any individual item in a batch exceeds 400 KB.
The total request size exceeds 16 MB.

对我来说,这看起来有些是真的。 在我的工作中,我们还遇到了一个问题,即一批中包含 2 个相同的主键和辅助键,因此整批都被丢弃了。 我知道它不是 node.js,但我们用来解决这个问题。

它是batch_writer(overwrite_by_pkeys) ,用于覆盖批处理中相同主键和最后一个键的最后一次出现。 如果您的数据中只有一小部分是重复数据并且您不需要保存它,您可以使用它。 但是如果您需要保存所有数据,我不建议您使用此功能。

我没有看到您在哪里检查UnprocessedItems的响应。 批处理操作通常会返回未处理的项目列表。 正如所记录的那样, BatchWriteItem “最多可以写入 16 MB 的数据,其中可以包含多达 25 个放置或删除请求。”

我有重复键问题,这意味着主键和排序键在批处理中具有重复值,但是,在我的情况下,如果我的时间戳在几分之一秒内,则不会从 AWS BatchWrite 方法返回此错误2020-02-09T08:02:36.71 ,这有点令人惊讶。 我通过使我的 createdAt(sort key) 变得更细化来解决这个问题 => 2020-02-09T08:02:36.7187从而使其不重复。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM