问题描述
spark脚本提交之后,遇到异常,重要堆栈如下:
Caused by: java.io.FileNotFoundException: File does not exist: hdfs://bigdata5:8020/apps/spark/warehouse/ds1152_sys_order_log/pt_day=20191104/part-00000-74c707e7-e509-4b5a-9937-3eff3522b29c.c000.snappy.parquet
It is possible the underlying files have been updated. You can explicitly invalidate the cache in Spark by running 'REFRESH TABLE tableName' command in SQL or by recreating the Dataset/DataFrame involved.
at org.apache.spark.sql.execution.datasources.FileScanRDD$$anon$1.org$apache$spark$sql$execution$datasources$FileScanRDD$$anon$$readCurrentFile(FileScanRDD.scala:131)
at org.apache.spark.sql.execution.datasources.FileScanRDD$$anon$1.nextIterator(FileScanRDD.scala:182)
at org.apache.spark.sql.execution.datasources.FileScanRDD$$anon$1.hasNext(FileScanRDD.scala:109)
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage2.scan_nextBatch_0$(Unknown Source)
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage2.processNext(Unknown Source)
at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.hasNext(WholeStageCodegenExec.scala:614)
at scala.collection.Iterator$$anon$11.hasNext(Iterator.scala:408)
at org.apache.spark.shuffle.sort.BypassMergeSortShuffleWriter.write(BypassMergeSortShuffleWriter.java:125)
at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:96)
at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:53)
at org.apache.spark.scheduler.Task.run(Task.scala:109)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
产生原因
根据异常描述,可以看到,是由于spark读取parquet文件的时候,文件找不到。
parquet文件设计的时候考虑到性能,会将元数据信息保存到头文件里,spark会将这部分元数据缓存到spark session里。
一般产生这个问题的原因是因为多个spark进程同时读取一个路径的parquet文件导致的,如两个sparkSession常驻进程,其中一个session更新了某一张表的数据,这样另外一个线程再尝试读取该数据的时候就会通过sparksession缓存读取,进而就会报错。
其他原因
如果魔镜本身是单机版,或者确定MQ都正常,那就要考虑是否有其他外部系统也在更新这张表,如果其他系统更新了这张表,而没有通知魔镜,也会出现这样的问题。
如果是这种情况,如果手工改了一次,则可以通过"表管理"->"表的下拉菜单"->"高级操作"->"Spark Refresh Table" 按钮手工刷新缓存。
如果是程序定期改,则需要调用魔镜接口刷新缓存,可以通过http://**/mojing-server/public/refreshTable?tableName=ads.t_user 来刷新该表的缓存。
解决办法
这种情况针对魔镜主要会出现在多台魔镜集群上,由于每台魔镜都有一个sparksession的常驻进程,多台魔镜之间是通过mq来通过这个缓存状态的,所以需要排查几点:
- 检查MQ是否配置,并且服务是否正常。
- 如果很多表同时出现,则极大可能是MQ服务不正常。
- 如果偶尔一张表出现,则去这张表的更新记录里面看看是否报错的时刻这张表有另外一个进程也在更新。(目前魔镜只有并发写锁,没有读写锁,所以极端情况会出现这个问题)。
- 如果都没有问题,则极端可能MQ网络抖动了,可以尝试通过“数据开发”->“表管理”->表的高级操作->“spark refresh table”进行单个表的缓存更新。
本文固定链接:杨晨辉的个人博客 » 魔镜spark refresh table问题排查
本站内容除特别标注外均为原创,欢迎转载,但请保留出处!