Отправка большого CSV в Kafka с помощью python Spark
Я пытаюсь отправить большой CSV Кафке. Основная структура состоит в том, чтобы прочитать строку CSV и закрепить ее заголовком.
a = dict(zip(header, line.split(",")
это затем преобразуется в json с:
message = json.dumps(a)
затем я использую библиотеку kafka-python для отправки сообщения
from kafka import SimpleProducer, KafkaClient
kafka = KafkaClient("localhost:9092")
producer = SimpleProducer(kafka)
producer.send_messages("topic", message)
использование PYSPARK Я легко создал RDD сообщений из файла CSV
sc = SparkContext()
text = sc.textFile("file.csv")
header = text.first().split(',')
def remove_header(itr_index, itr):
return iter(list(itr)[1:]) if itr_index == 0 else itr
noHeader = text.mapPartitionsWithIndex(remove_header)
messageRDD = noHeader.map(lambda x: json.dumps(dict(zip(header, x.split(","))
теперь я хочу отправить эти сообщения: я определяю функцию
def sendkafka(message):
kafka = KafkaClient("localhost:9092")
producer = SimpleProducer(kafka)
return producer.send_messages('topic',message)
Затем Я создайте новый RDD для отправки сообщений
sentRDD = messageRDD.map(lambda x: kafkasend(x))
затем я вызываю sentRDD.count ()
который начинает сбивать и отправлять сообщения
к сожалению, это происходит очень медленно. Он отправляет 1000 сообщений в секунду. Это на кластере 10 узлов по 4 процессора каждый и 8 ГБ памяти.
для сравнения, создание сообщений занимает около 7 секунд на 10 миллионов строк csv. ~ 2 ГБ
Я думаю, проблема в том, что я создаю экземпляр продюсера Кафки внутри функция. Однако, если я этого не делаю, spark жалуется, что производитель не существует, хотя я попытался определить его глобально.
возможно, кто-то может пролить свет на то, как эта проблема может быть решена.
спасибо,
1 ответов
вы можете создать одного производителя на раздел и использовать либо mapPartitions
или foreachPartition
:
def sendkafka(messages):
kafka = KafkaClient("localhost:9092")
producer = SimpleProducer(kafka)
for message in messages:
yield producer.send_messages('topic', message)
sentRDD = messageRDD.mapPartitions(sendkafka)
если выше только не поможет, вы можете попытаться расширить его с помощью асинхронный продюсер.
В Spark 2.x также можно использовать источник данных Kafka. Вам придется включить spark-sql-kafka
jar, соответствующая версия Spark и Scala (здесь 2.2.0 и 2.11 соответственно):
spark.jars.packages org.apache.spark:spark-sql-kafka-0-10_2.11:2.2.0
преобразование данных в DataFrame
(если это не DataFrame
уже):
messageDF = spark.createDataFrame(messageRDD, "string")
и писать DataFrameWriter
:
(messageDF.write
.format("kafka")
.option("topic", topic_name)
.option("kafka.bootstrap.servers", bootstrap_servers)
.save())