2016-04-01 10 views
1

Ich habe eine Prototyp-Anwendung mit Spark-Streaming in Java erstellt, die HyperLogLog verwendet, um verschiedene Benutzer aus einem simulierten Klick-Stream zu schätzen.Spark Streaming-Parallelität mit einem einzigen Schlüssel

Lassen Sie mich kurz meine Lösung skizzieren. Zuerst erstelle ich einen Stream mit dem KafkaUtils:
JavaPairReceiverInputDStream<String, String> directKafkaStream = KafkaUtils.createStream(streamingContext, ZOOKEEPER_ADDRESS, ZOOKEEPER_GROUP, topics);

Von dort erstelle ich einen Strom, der nur den gewünschte Feld enthält, fullVisitorId:
JavaDStream<String> fullvisitorids = directKafkaStream.map(line -> line._2().split(",")[0]);

Um einen globalen Zustand zu erhalten (mein HyperLogLog-Object) den einzigen Weg, Ich fand die Methoden udpateStateByKey oder mapWithState. Beide scheinen ein Schlüssel-Wert-Paar zu benötigen ... aber in meinem Anwendungsfall brauche ich keinen Schlüssel.

Also beschloss ich, eine „Dummy-Taste“ zu verwenden:
fullvisitorids.mapToPair(value -> new Tuple2<String, String>("key", value));

Aber jetzt meine Fragen:
a) Wie Spark-Transformationen nicht parallelisieren mit updateStateByKey oder mapWithState auf diesem Strom, der nur einen einzigen Schlüssel hat? Oder wie teilt es die RDD über den Cluster?

b) Gibt es eine bessere Lösung für mein Problem als das Hinzufügen eines Dummy-Schlüssels, der überhaupt keine Funktion hat?

Antwort

1

a) Der Stream wird nicht parallelisiert, wenn Sie den Hash-Partitionierer mit einem einzelnen Wert für den Schlüssel verwenden. Definieren Sie entweder Ihren eigenen Partitionierer oder verwenden Sie keinen einzelnen Schlüssel.

b) Die Lösung wäre, updateStateByKey nicht zu verwenden, das nicht für den globalen Status gedacht ist. Sie sollten einfach ein globales einzelnes HLL-Objekt verwenden, z. von Algebird (here is a Gist that demonstrates how this might look).

+0

Danke. zu b) Wie genau würde eine solche Lösung über einen Cluster verteilt werden? – JayKay