使用spark streaming 处理kafka数据,有时候程序出现异常,或者需要修改程序再次运行,就可能会造成这样的情况:
由于上面这些问题,所以希望可以自己人工地管理kafka中数据读取的状态。
原来是使用下面的方式创建kafka流:
kvs = KafkaUtils.createStream(ssc, "xxx.xxx.xxx.xxx:2182/kafka", group_id, {topic:1},{'auto.offset.reset':'smallest'})
这种方式是使用zookeeper来管理kafka中topic中每个partition读取的offset。
上网搜了一些资料,发现可以使用createDirectStream来自定义设置读取的offset:
from pyspark.streaming import StreamingContext
from pyspark import SparkContext,SparkConf
from pyspark.streaming.kafka import KafkaUtils, TopicAndPartition
spark_conf = SparkConf()
sc = SparkContext(conf=spark_conf)
ssc = StreamingContext(sc, 30)
topic = "test"
partition = 0
start = 0
topicPartion = TopicAndPartition(topic,partition)
fromOffset = {topicPartion: long(start)}
directKafkaStream = KafkaUtils.createDirectStream(ssc, [topic], {"metadata.broker.list": 'xxx.xxx.xxx.xxx:9092'}, fromOffsets=fromOffset)
其中,fromOffset保存topic partition对应的offset的信息,例子中test这个topic只有一个partition,设置从offset=0的位置开始读。
在数据处理完之后,希望可以保存数据读取位置的状态:
offsetRanges = []
def storeOffsetRanges(rdd):
global offsetRanges
offsetRanges = rdd.offsetRanges()
return rdd
def printOffsetRanges(rdd):
print rdd.count()
for o in offsetRanges:
print "__________________________________"
print "%s %s %s %s" % (o.topic, o.partition, o.fromOffset, o.untilOffset)
print "__________________________________"
directKafkaStream\
.transform(storeOffsetRanges)\
.foreachRDD(printOffsetRanges)
这样我们也可以将这些信息保存到mysql、mongodb等,在以后需要重启spark streaming任务的时候,就可以从数据库中保存的上次的offset开始读取数据。
api:http://spark.apache.org/docs/latest/api/python/pyspark.streaming.html#pyspark.streaming.kafka.KafkaUtils
github:https://github.com/Stratio/spark-kafka
stackoverflow: http://stackoverflow.com/questions/33268689/how-to-create-inputdstream-with-offsets-in-pyspark-using-kafkautils-createdirec