Производительность вставки Cassandra с использованием коннектора spark-cassandra
Я новичок в искре и Кассандре. Я пытаюсь вставить в таблицу cassandra, используя разъем свечи-кассандры, как показано ниже:
import java.util.UUID
import org.apache.spark.{SparkContext, SparkConf}
import org.joda.time.DateTime
import com.datastax.spark.connector._
case class TestEntity(id:UUID, category:String, name:String,value:Double, createDate:DateTime, tag:Long)
object SparkConnectorContext {
val conf = new SparkConf(true).setMaster("local")
.set("spark.cassandra.connection.host", "192.168.xxx.xxx")
val sc = new SparkContext(conf)
}
object TestRepo {
def insertList(list: List[TestEntity]) = {
SparkConnectorContext.sc.parallelize(list).saveToCassandra("testKeySpace", "testColumnFamily")
}
}
object TestApp extends App {
val start = System.currentTimeMillis()
TestRepo.insertList(Utility.generateRandomData())
val end = System.currentTimeMillis()
val timeDiff = end-start
println("Difference (in millis)= "+timeDiff)
}
Когда я вставляю, используя вышеупомянутый метод (список с 100 сущностями), это занимает 300-1100 milliseconds
, Я попробовал те же данные, чтобы вставить с помощью фантомной библиотеки. Это займет всего меньше, чем 20-40 milliseconds
,
Может кто-нибудь сказать мне, почему свечи зажигания занимает столько времени для вставки? Я что-то не так делаю в своем коде или не рекомендуется использовать спарк-кассандровый разъем для операций вставки?
2 ответа
Похоже, что вы включаете операцию распараллеливания в вашем времени. Кроме того, поскольку ваш работник Spark работает на компьютере, отличном от Cassandra, операция saveToCassandra будет выполнять запись по сети.
Попробуйте настроить систему для запуска искровых рабочих на узлах Cassandra. Затем создайте СДР на отдельном шаге и вызовите на нем действие, например count (), чтобы загрузить данные в память. Также вы можете захотеть сохранить () или кэшировать () RDD, чтобы убедиться, что он остается в памяти для теста.
Тогда время только saveToCassandra того кешированного RDD.
Возможно, вы также захотите взглянуть на метод repartitionByCassandraReplica, предлагаемый соединителем Cassandra. Это позволит разделить данные в RDD на основании того, на какой узел Cassandra нужно выполнить запись. Таким образом, вы используете локальность данных и часто избегаете записи и перестановки по сети.
Есть некоторые серьезные проблемы с вашим "эталоном":
- Ваш набор данных настолько мал, что вы измеряете в основном только время настройки задания. Сохранение 100 объектов должно быть порядка одного миллисекунды на одном узле, а не секунд. Кроме того, сохранение 100 объектов не дает JVM возможности скомпилировать выполняемый код в оптимизированный машинный код.
- Вы включили инициализацию искрового контекста в свое измерение. JVM загружает классы лениво, поэтому после инициализации измерения действительно вызывается код для искровой инициализации. Это чрезвычайно дорогостоящий элемент, обычно выполняемый только один раз для всего применения искры, даже не для каждой работы.
- Вы выполняете измерение только один раз за запуск. Это означает, что вы даже неверно измеряете настройку spark ctx и время настройки задания, потому что JVM должна загрузить все классы в первый раз, и у Hotspot, вероятно, нет шансов активироваться.
Подводя итог, вы, скорее всего, измеряете в основном время загрузки классов, которое зависит от размера и количества загруженных классов. Spark - довольно большая вещь для загрузки, и несколько сотен миллисекунд не удивляют вообще.
Чтобы правильно измерить производительность вставки:
- использовать больший набор данных
- исключить единовременную настройку из измерения
- выполните несколько прогонов, используя один и тот же контекст искры, и отбросьте несколько начальных, пока не достигнете стабильной производительности.
Кстати, если вы включите уровень ведения журнала отладки, соединитель регистрирует время вставки для каждого раздела в журналах исполнителя.