参考链接:
https://blog.youkuaiyun.com/xueba207/article/details/51135423 kafka 0.8.2.2
http://spark.apache.org/docs/latest/streaming-kafka-0-10-integration.html
一、前言(Kafka2.0.0)
Kafka支持producer的幂等性,并不支持consumer的幂等性,因此我们选择使用外部存储来维护consumer的offset。
以词频统计为例实现
SparkStreaming消费Kafka数据,把统计结果和offset保存到Redis中
词频结果Redis保存格式:wc_redis word cnt
offset信息Redis保存格式:topic_groupid partition offset
二、需要考虑的问题
1、业务结果和offset结果保存到Redis需要保证一致性
解决方法:使用jedis.pipeline
2、当redisOffset<KafkaOffset时,会报numRecords must not be negative,需要修正offset。
解决方法:1)把旧的词频结果rename(oldkey,old_tmp)
2) 把所有partition的offset设置为0,也就是重刷数据,写入到oldkey
三、代码实现
使用到以下四个类:
1)RedisUtils:设置redis连接信息,获取redis连接
2)KafkaOffsetTool:使用KafkaConsumer获取指定topic的每个partition的endOffset
3)MyOffsetsManager:获取和保存offset
4)StreamingKakfaApp:业务处理
RedisUtils
package com.wsd.spark.utils
import redis.clients.jedis.{JedisPool, JedisPoolConfig}
/**
* Redis连接
*
* @author wsd
* @date 2020/4/26 14:46
*/
object RedisUtils {
private val poolConfig = new JedisPoolConfig
poolConfig.setMaxTotal(2000)
poolConfig.setMaxIdle(1000)
poolConfig.setTestOnBorrow(true)
private val pool = new JedisPool(poolConfig, "master", 6379)
def getJedis = pool.getResource
}
KafkaOffsetTool
package com.wsd.spark.streaming.offset
import java.util.Properties
import java.{lang, util}
import org.apache.kafka.clients.consumer.KafkaConsumer
import org.apache.kafka.common.{Partiti