使用Akka grpc流从DB读取和写入到Elasticsearch的同步速度

时间:2019-01-10 12:15:00

标签: scala elasticsearch grpc akka-stream

在这里,我们开发了多种服务,每个服务都使用akka actor,并且服务之间的通信是通过Akka GRPC实现的。有一项服务可以填充内存数据库,而另一项服务称为“读取器”,它会应用一些查询和形状数据,然后将它们传输到elasticsearch服务以进行插入/更新。每个读取阶段的数据量约为1M行。 当Reader传输大量数据时,就会出现问题,因此elasticsearch无法处理它们并全部插入/更新它们。

我将akka流方法用于这两种服务通信。我还使用scalike jdbc lib和下面的代码来读取和插入批处理数据,而不是整个数据。

def applyQuery(query: String,mergeResult:Map[String, Any] => Unit) = {
  val publisher = DB readOnlyStream {
    SQL(s"${query}").map(_.toMap()).list().fetchSize(100000)
      .iterator()
  }

  Source.fromPublisher(publisher).runForeach(mergeResult)
}
////////////////////////////////////////////////////////
var batchRows: ListBuffer[Map[String, Any]] = new ListBuffer[Map[String, Any]]
val batchSize: Int = 100000
def mergeResult(row:Map[String, Any]):Unit = {
    batchRows :+= row

    if (batchRows.size == batchSize) {

      send2StorageServer(readyOutput(batchRows))
      batchRows.clear()
    }
  }

  def readyOutput(res: ListBuffer[Map[String, Any]]):ListBuffer[StorageServerRequest] = {

// code to format res  
  }

现在,当使用“ foreach”命令时,它会使操作变慢得多。我尝试了不同的批次大小,但没有任何意义。我在使用foreach命令时是否错了,还是有使用akka流,流等解决速度问题的更好方法。

1 个答案:

答案 0 :(得分:0)

我发现要用于附加到ListBuffer的操作是

batchRows + =行

但是使用:+不会产生错误,但是效率很低,因此尽管使用了速度问题,但使用正确的运算符,foreach不再慢。这次,读取数据很快,但是写入elasticsearch却很慢。

经过一些搜索,我想到了以下解决方案:  1.将队列用作数据库和elasticsearch之间的缓冲区可能会有所帮助。  2.同样,如果在完成写入之前阻塞读取操作并不昂贵,     这可能是另一种解决方案。

相关问题