个性化的需求
随着互联网知识信息指数级膨胀,个性化的需求对于用户来说越来越重要,通过推荐算法和用户点击行为的流式计算可以很简单的做出一个商用的推荐系统。
流程
- java
- spark streaming
- kafka
- redis
- mysql
spark streaming从kafka读取用户行为数据,过滤数据后从redis中拉取物品相似度矩阵,从db或缓存中获取用户历史行为,通过协同过滤进行兴趣/ctr候选集计算,将结果缓存到redis,异步持久化到db,通过接口进行数据展示。
开发包使用KafkaUtils类
设置消费者offset
数据从kafka拉取时,可能因为程序异常,造成数据丢失或不一致,可以通过kafka把数据重新拉取,可以指定offset读取。
从kafka拉取数据,转换为spark streaming中的数据结构DStream。 接收数据有两种:
- 利用receiver接收数据;
- 直接从kafka读取数据;
receiver方式
基本的使用kafka高阶api,接收的所有数据存储在spark的executor中,之后spark streaming提交的job会处理这些数据。
reveiver方式,spark中partiton和kafka的partition并不是相关的,如果加大每个topic的partition数量,仅仅增加线程来处理由单一receiver消费的主题,但并没有增加spark在处理数据上的并行度。
对于不同的group和topic,可以使用多个receiver创建不同的DStream来提升并行度,之后利用union来统一成一个DStream。
直接读取方式
Direct方式,没有receiver这一层,会周期性的获取kafka中每个topic的每个partition中新的offset,之后根据设定的maxRatePerPartition来处理每个batch。
相较于receiver方式的优势是:
- 简化的并行:direct方式中,kafka的partiton与rdd的partition是一一对应的,并行读取kafka数据,这种映射关系利于优化和理解。
- 高效:receiver方式中,为了达到0数据丢失,将数据存入Write ahead log中,这样kafka和日志中就保存了两份数据,浪费;direct方式不存在这个问题。
- 精确:receiver方式,使用的是kafka的高阶api从zk中获取offset值,也是传统的同kafka中读取的方式,但spark streaming消费数据和zk中记录的offset不同步,偶尔造成数据重复消费;direct方式直接使用低阶kafka api,offset利用spark streaming的checkpoints记录,消除不一致。
receiver方式,是从zk获取offset值,zk保存了当前消费的offset值,如果重新启动开始消费会接着上次offset继续消费。 direct方式中,直接从kafka来读取数据,offset要自己记录,可以通过checkpoint,数据库,文件记录,或者写回到zk。
调优
如果批处理时间设置短,产生的job并不能在这期间完成,就会造成数据不断累积,导致spark streaming阻塞。
spark streaming中的DStream如果被反复利用,最好使用cache(),将数据流缓存起来,防止过度调度造成网络开销。
设置合理的GC,并行垃圾回收。