Использование заводных актеров для увеличения пропускной способности базы данных? - PullRequest
2 голосов
/ 16 декабря 2010

Я работаю с библиотекой GPars, работая над улучшением масштабируемости соответствующей системы.Я хотел бы иметь возможность запрашивать базу данных и немедленно запрашивать базу данных, в то время как результаты обрабатываются одновременно.Узким местом является чтение из базы данных, поэтому я бы хотел, чтобы база данных была полностью занята при асинхронной обработке результатов, когда они доступны.Я понимаю, что у меня могут быть некоторые фундаментальные недоразумения относительно того, как работает структура актера, и я был бы рад, чтобы меня исправили!

В псевдокоде я пытаюсь сделать следующее:

Определить двух действующих лиц: один для запуска выбирает базу данных, а другой для обработки записей.

  1. queryActor запрашивает базу данных и отправляет результаты процессору процессора
  2. queryActor немедленно запрашивает базу данных снова, не дожидаясь окончания ProcessActor

Возможно, я смог бы добиться простого использованияслучай без использования акторов, но моя конечная цель - иметь пул акторов, который всегда работает над новыми запросами с потенциально разными источниками данных, чтобы увеличить пропускную способность системы в целом.

Актер обработки всегда будет многобыстрее, чем запрос к базе данных, поэтому я хотел бы запросить несколько реплик одновременно.

      def processor = actor {
    loop {
      react {querySet ->
        println "processing recordset"
        if (querySet instanceof Object[]) {
          MatcherDataRowProcessor matcher = new MatcherDataRowProcessor(matchedRecords, matchedRecordSet);

          matchedRecords = matcher.processRecordset(querySet);
          reply matchedRecords
        }
        else {
          println 'processor fed nothing, halting processor actor'
          stop()
        }
      }
    }
  }

  def dbqueryer = actor {
    println "dbqueryer has started"

    while (batchNum.longValue() <= loopLimiter) {
      println "hitting db"
      Object[] querySet
      def thisRuleBatch = new MatchRuleBatch(targetuidFrom, targetuidTo)
      thisRuleBatch.targetuidFrom = batchNum * perBatch - perBatch
      thisRuleBatch.targetuidTo = thisRuleBatch.targetuidFrom + perBatch
      thisRuleBatch.targetName = targetName
      thisRuleBatch.whereClause = whereClause
      querySet = dao.getRecordSet(thisRuleBatch)
      processor.send querySet
      batchNum++
    }

    react { processedRecords ->
      processor.send false
    }
  }

Ответы [ 2 ]

1 голос
/ 29 декабря 2010

Я бы посоветовал взглянуть на очереди потоков данных в разделе Параллельность потока данных в руководстве пользователя для GPars.Вы можете обнаружить, что потоки данных обеспечивают лучшую / более чистую абстракцию для вашей проблемы под рукой.Потоки данных также можно использовать совместно с акторами.

Я думаю, что в этой ситуации сработают либо акторы, либо потоки данных, и чувствую, что решение сводится к тому, какой из них обеспечивает абстракцию, которая более точно соответствует тому, что вы пытаетесь достичь,Для меня концепция задач, очередей, потоков данных представляется более подходящей по терминологии.

0 голосов
/ 20 января 2011

После еще одного исследования я обнаружил, что компонент параллелизма DataFlow в Gpars на самом деле построен поверх поддержки Actor. DataflowOperatorTest в демонстрационном дистрибутиве gpars java (мне нужно сделать реализацию java), кажется, хорошо соответствует тому, что мне нужно сделать. Основной поток ожидает заполнения нескольких потоковых входов, которые в моем случае являются параллельными запросами к базе данных.

...