我从Cloudera quickstart docker容器上的Python Spark(v 1.6.0)开始。 我在/user/root/access_log.txt下的hdfs中添加了一个静态 .txt文件(500 mb)。
在pyspark中,我尝试使用以下python代码行加载文件:
lines = sc.textFile("hdfs://quickstart.cloudera/user/root/access_log.txt")
这给了我没有错误。但我发现文件未完全加载。 还.. ..
lines.max()
当hdfs实际上有正确的文件大小时,不会给文件的正确的最后一个元素。
这是一个记忆问题吗?我的泊坞窗设置设置为3840 MB。 我不知道如何解决这个问题。我期待着你的回答。
修改
我计算了数据集中的元素:
lines.count()
令我惊讶的是它是正确的!这应该意味着我的文件已正确加载。但问题仍然是 .max()语句没有返回正确元素的原因。
这与不同的任务有关吗?
编辑2 : .txt文件中的一些示例行
10.190.174.142 - - [03/Dec/2011:13:28:10 -0800] "GET /images/filmpics/0000/2229/GOEMON-NUKI-000163.jpg HTTP/1.1" 200 184976
10.190.174.142 - - [03/Dec/2011:13:28:11 -0800] "GET /images/filmmediablock/360/GOEMON-NUKI-000163.jpg HTTP/1.1" 200 60117
10.190.174.142 - - [03/Dec/2011:13:28:10 -0800] "GET /images/filmmediablock/360/Chacha.jpg HTTP/1.1" 200 109379
10.190.174.142 - - [03/Dec/2011:13:28:11 -0800] "GET /images/filmmediablock/360/GOEMON-NUKI-000159.jpg HTTP/1.1" 200 161657
答案 0 :(得分:3)
一般来说,max
不应该返回(...)最后一个元素。在某些情况下,如果日志文件使用的格式强制执行字典顺序,并且您对内容感到幸运,那么它就不会发生。由于您的数据以IP地址为前缀并使用不友好(不是例如ISO 8601)时间戳格式,因此获取最后一个元素并不是您所期望的。
找到最后一个元素的一种方法是包含索引:
from operator import itemgetter
(rdd
.zipWithIndex() # Add line number to get (line, no)
.max(key=itemgetter(1))[0]) # Compare elements using index
有点不同的方法是找到每个分区的最后一个元素,然后找到最后一个元素。
from functools import reduce
rdd.mapPartitions(lambda part: reduce(lambda _, x: [x], part, [])).collect()[-1]
或者如果分区数量很大:
(rdd
.mapPartitionsWithIndex(
lambda i, part: reduce(lambda _, x: [(i, x)], part, []))
.max()[1]) # Take max using tuple ordering