spark算法构图不准的问题原因排查

1: 问题描述:
图谱spark任务离线构图,发现原本有关联的点被分在多个连通图,且在一个连通图出现大量离散点,连通图构成出现错乱。
2: 问题初步排查及背景:
初步判断是spark提供的生成点唯一id算有问题。之前生成全图连通图时,原本提供的dense_rank函数在大数据量时,会有id重复的问题。所以换了一套更优秀的spark生成唯一id的方法,并且用在了离线团伙构建上,之前离线团伙构建并无问题,所以判断问题还是在vid生成算法。
3: 问题排查历程:
1: 切回原算法,发现构图无问题,可以生成正确的连通图,确定了问题就出现在vid算法部分,先保证线上不再出错。
2: 开发新代码,专门用作解决此问题,在一笔自建生产任务中,循环使用点/边数据,生成连通图,观察情况。
3: 将各种中间转换状态落odps表,分析中间转换过程,发现原始边是对的,给string生成的long型点id也唯一,但是转换为long边的时候,和原始边并不能对应。问题排查范围进一步缩小
在这里插入图片描述

此时觉得问题就出现join上,查资料并无发现有任何资料显示spark join结果会出错,而且原始算法也用的这一套逻辑,马上否定了自己。但为了确认,还是用原始算法又跑了一遍,发现构图也出错了,但看到odps点/边还是对的,跑了一笔生产的,还是对的。意识到应该是重复跑一笔任务导致的。查看临时写文件的地方是overwirte,没有错。想到应该是es本身数据没覆盖完全。初始化es数据
在这里插入图片描述

在kibana初始化es数据。再用原始算法跑,没问题,验证了join肯定是不会错的。
此时困惑中,回头看代码中不一样的地方
在这里插入图片描述

在离线构图任务使用的是getEncoderDs,全图逻辑是getVidEncoder,想到是不是创建Dataset时,字段必须对应起来? 本地测试十条没发现问题,测试十万条发现也能对应。这两个方法并无区别。
中间试了一下使用和全图构图一样的逻辑,使用getVidEncoder传入点的tagDs,发现可以正常构图。
想到是应该是悬挂边的问题?因为在转换时,使用了inner join,通过点可以过滤悬挂边,但是通过边的两点,无法过滤。
在这里插入图片描述

但觉得还不是真正的原因,因为全图构图过滤了悬挂边,还是有这个问题,说明真正的原因还是在隐藏中。再仔细查看这两个方法的实现,除了生成点id的算法不一致,好像并无差别。还是得回到生成点id算法中。
在这里插入图片描述

再仔细看这一段,发现果然是有点问题,encoderDs 使用了三次,考虑到spark机制,如果内存不足,会被gc,ds会重新触发计算,想到应该是这里的问题。
加了一个cache,果然发现问题解决,真正问题的原因还是因为encoderDs发生了重复计算,两次生成的唯一id不一致。
在这里插入图片描述

至于为什么原算法没问题。是因为原算法是一个窗口排序函数,根据vid排序,不管计算多少次,点的顺序总是唯一的,对应的long型 id也是唯一的。
在这里插入图片描述

4:问题结论
spark生成唯一点id的dataset,因为gc导致了重复计算,两次生成id不一致,导致了从string边转long边的转换中间过程出错,从全图构图到离线构图一直都是这个问题,至此才真正发现问题原因。
5: 问题解决
1: 给生成的encoderDs 加cache,但可能会导致oom.
在这里插入图片描述

2: 将生成的encoderDs写入hdfs,以后每次用从hdfs里取出来,这样即使重复计算也不会发生变化。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值