【问题标题】:Performance on scanAll operation vs executescanAll 操作与执行的性能
【发布时间】:2021-08-29 11:05:43
【问题描述】:

我在我的aerospike 恢复过程中使用了以下truncate 实现,这让我可以清楚地了解在操作期间受影响的记录数量:

 def truncate(startTime: Long, durableDelete: Boolean): Iterable[Int] = {

    // Setting LUT
    val calendar = Calendar.getInstance()

    logger.info(s"truncate(records s.t LUT <= $startTime = ${calendar.getTime}, durableDelete = $durableDelete) on ${config.toRecoverMap}")

    // Define Scan and Write Policies
    val writePolicy = new WritePolicy()
    val scanPolicy = new ScanPolicy()
    writePolicy.durableDelete = durableDelete
    scanPolicy.filterExp = Exp.build(Exp.le(Exp.lastUpdate(), Exp.`val`(calendar)))

    // Scan all records such as LUT <= startTime
    config.toRecoverMap.flatMap { case (namespace, mapOfSetsToBins) =>
      for ((set, bins) <- mapOfSetsToBins) yield {
        val recordCount = new AtomicInteger(0)
        client.scanAll(scanPolicy, namespace, set, new ScanCallback() {
          override def scanCallback(key: Key, record: Record): Unit = {
            val requiresNullify = bins.filter(record.bins.containsKey(_)).toSeq // Instead of making bulk requests which maybe not be needed and load AS
            if (requiresNullify.nonEmpty) {
              recordCount.incrementAndGet()
              client.put(writePolicy, key, requiresNullify.map(Bin.asNull): _*)
              logger.debug {
                val (nullified, remains) = record.bins.asScala.partition { case (key, _) => requiresNullify.contains(key) }
                s"(#$recordCount): Record $nullified bins of record with userKey: ${key.userKey}, digest: ${Buffer.bytesToHexString(key.digest)} nullified, remains: $remains"
              }
            }
          }
        })

问题是操作由于回调而花费了很多时间并且无法在production环境中受到影响,我将实现更改为以下而不是大约2小时,时间减少了到10分钟。

def truncate(startTime: Long, durableDelete: Boolean): Unit = {

    // Setting LUT
    val calendar = Calendar.getInstance()

    logger.info(s"truncate(records s.t LUT <= $startTime = ${calendar.getTime}, durableDelete = $durableDelete) on ${config.toRecoverMap}")

    // Define Write Policy
    val writePolicy = new WritePolicy()
    writePolicy.durableDelete = durableDelete

    config.toRecoverMap.flatMap { case (namespace, mapOfSetsToBins) =>
      for ((set, bins) <- mapOfSetsToBins) yield {

        // Filter all elements s.t lastUpdate <= startTime on $set
        writePolicy.filterExp = Exp.build(
          Exp.and(
            Exp.le(Exp.lastUpdate(), Exp.`val`(calendar)),
            Exp.eq(Exp.setName(), Exp.`val`(set)))
        )

        val statement = new Statement
        statement.setNamespace(namespace)
        val toNullify = bins.map(Bin.asNull).map(Operation.put).toList
        client.execute(writePolicy, statement, toNullify: _*).waitTillComplete(10.seconds.toMillis.toInt, 1.hour.toMillis.toInt)
      }
    }
  }

但问题是我没有像提供给我的第一种方法那样对受影响的记录有任何可见性(查看logger.debug

是否有解决方案如何以良好的性能运行并提供日志?

谢谢!

【问题讨论】:

    标签: aerospike


    【解决方案1】:

    看起来您正在使用企业,并且您的截断只考虑了 LUT。首选方法是使用truncate API。这与扫描和持久删除方法相比具有显着优势,因为它不需要为每个已删除的键保留一个墓碑条目,相反,它将有一个条目将集合中的所有记录标记为已删除。它也不需要调用“古墓丽影”,这是一种定期磁盘扫描,用于搜索不再在设备上标记死记录的墓碑(又名“纪念碑”)。每个节点通过truncate删除的记录数可以找到truncated_records

    您可以使用truncate info 命令调用此截断方法。


    顺便说一句,您可以通过在扫描策略中将includeBinData 选项设置为false 来显着加快第一种方法。这导致 Aerospike 只需要在扫描期间读取和发送内存中的元数据。我相信如果您已经将记录的密钥与记录一起存储了密钥,我们仍然需要读取设备。

    【讨论】:

    • 嘿,感谢您的回复 - 关于truncate,它不是通过XDR 发货的。 IncludeBinData 是个不错的选择,我试试
    猜你喜欢
    • 2013-07-31
    • 2013-08-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2019-12-03
    • 2013-01-12
    • 2023-02-23
    • 1970-01-01
    相关资源
    最近更新 更多