【问题标题】:Storing 1 million rows in a collection, updating in an actor在一个集合中存储 100 万行,在一个 actor 中更新
【发布时间】:2017-06-18 18:32:17
【问题描述】:

我有一个演员在后台每小时下载一个大约 100 万行的 CSV 产品文件,然后它将循环遍历 CSV 并改变一个集合。

现在在我的播放控制器中,我将向网站访问者显示这 100 万行中的一部分。

我将要求演员给我一份收藏的副本。 如果我基于每个页面请求执行此操作,这会是性能问题吗?还是像下面这样的电话非常接近任务?

val futProducts = myActor ? GetProducts

我的演员将拥有一系列每隔一小时左右更新一次的产品。

var products: List[Product] = ...

更新

我怎样才能创建一个对这个products 变量的全局引用,我可以在我的播放控制器中引用它,然后也可以在我的actor 中进行变异。我认为这是最好的方法,但不知道该怎么做。

【问题讨论】:

  • 影响性能的因素很多。如果您正在执行多页请求,您可能希望为每个页面创建 n 演员。

标签: scala playframework akka


【解决方案1】:

我不会通过对您的 products 变量的全局引用来解决这个问题,因为这意味着您拥有一个共享的可变状态。我会采用您将产品列表封装在您的演员中的第一种方法,如下所示:

import DataActor.{Page, Update}
import akka.actor.Actor

/**
  * Created by d058837 on 19.06.17.
  */
class DataActor extends Actor {

  var data: Seq[Int] = 1 to 100000
  val pageSize = 100

  override def receive: Receive = {
    case Update =>
      updateData()
    case Page(page) =>
      sender() ! data.slice(pageSize * page, pageSize * page + pageSize)
  }

  def updateData() = {
    data = data.map(_ + 100)
  }

}

object DataActor {

  case object Update
  case class Page(page: Int = 0)
}

您可以按照本次测试所示使用:

import akka.actor.{ActorSystem, Props}
import akka.pattern.ask
import akka.testkit.{ImplicitSender, TestKit}
import akka.util.Timeout
import org.scalatest.{Matchers, WordSpecLike}

import scala.concurrent.Await
import scala.concurrent.duration.DurationInt

class DataActorTest extends TestKit(ActorSystem("testSystem")) with WordSpecLike with Matchers with ImplicitSender {

  "actor with data should" should {
    "update data and return pages" in {
      implicit val timeout: Timeout = 3 seconds

      val dataActor = system.actorOf(Props[DataActor])

      val initialStateFuture = dataActor ? DataActor.Page(0)
      val initialState = Await.result(initialStateFuture, timeout.duration)
      initialState shouldBe (1 to 100)

      dataActor ! DataActor.Update

      val currentStateFuture = dataActor ? DataActor.Page(0)
      val currentState = Await.result(currentStateFuture, timeout.duration)
      currentState shouldBe (101 to 200)
    }
  }
}

我肯定会在这里采用分页方式,这样您就不会一直在庞大的产品列表中移动。

为了获得额外的性能,您可以在控制器中使用缓存,当您的 DataActor 更新其数据时,该缓存会失效,因此您只在请求新/未知页面时才访问实际的数据 Actor。

【讨论】:

    猜你喜欢
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多