如何在HDFS hadoop Map Reduce中处理增量更新

如何在HDFS hadoop Map Reduce中处理增量更新,hadoop,apache-spark,mapreduce,hdfs,Hadoop,Apache Spark,Mapreduce,Hdfs,我在HDF中构建了基本文本文件,其中包含如下数据(在file.txt中): txt文件的大小为30 GB 我有一个增量数据文件1.txt,大小约为2 GB,在HFDS中以相同格式出现,如下所示: OgId|^|ItemId|^|segmentId|^|Sequence|^|Action|!| 4295877341|^|213|^|4|^|1|^|I|!| 4295877341|^|213|^|4|^|1|^|I|!| 4295877341|^|215|^|2|^|1|^|I|!| 429587

我在HDF中构建了基本文本文件,其中包含如下数据(在file.txt中):

txt文件的大小为30 GB

我有一个增量数据文件1.txt,大小约为2 GB,在HFDS中以相同格式出现,如下所示:

OgId|^|ItemId|^|segmentId|^|Sequence|^|Action|!|

4295877341|^|213|^|4|^|1|^|I|!|
4295877341|^|213|^|4|^|1|^|I|!|
4295877341|^|215|^|2|^|1|^|I|!|
4295877341|^|141|^|4|^|1|^|I|!|
4295877341|^|143|^|2|^|1|^|I|!|
4295877343|^|149|^|14|^|2|^|I|!|
123456789|^|145|^|14|^|1|^|D|!|
现在,我必须组合file.txt和file1.txt,创建一个包含所有唯一记录的最终文本文件

两个文件中的密钥都是OrgId。如果在第一个文件中找到相同的OrgId,那么我必须用新的OrgId替换,如果没有,那么我必须插入新的OrgId

最终的输出是这样的

OgId|^|ItemId|^|segmentId|^|Sequence|^|Action|!|

4295877346|^|136|^|4|^|1|^|I|!|
4295877341|^|213|^|4|^|1|^|I|!|
4295877341|^|215|^|2|^|1|^|I|!|
4295877341|^|141|^|4|^|1|^|I|!|
4295877341|^|143|^|2|^|1|^|I|!|
4295877343|^|149|^|14|^|2|^|I|!|
如何在mapreduce中执行此操作

我不会选择HIVE解决方案,因为我有这么多像这样的不同文件,大约10.000个,所以我必须在HIVE中创建10.000个分区


有没有关于在这个用例中使用Spark的建议?

我建议您在
scala
中为
Spark
编程。如果您在
mapreduce
中编程,它将仅对
hadoop
有用,但在
scala
中为
spark
编程将使您能够在
spark
以及
hadoop
中进行处理<启动code>Spark是为了解决
mapreduce
模型中的缺陷。您可以找到许多关于此主题的资源。其中之一是

关于您的问题,我建议您使用
dataframe

第一个任务是为数据帧创建
schema

val schema = StructType(Array(StructField("OgId", StringType),
  StructField("ItemId", StringType),
  StructField("segmentId", StringType),
  StructField("Sequence", StringType),
  StructField("Action", StringType)))
下一个任务是读取这两个文件并使用上述模式创建数据帧

import org.apache.spark.sql.functions._
val textRdd1 = sparkContext.textFile("input path to file1 in hdfs")
val rowRdd1 = textRdd1.map(line => Row.fromSeq(line.split("\\|\\^\\|", -1)))
var df1 = sqlContext.createDataFrame(rowRdd1, schema)
df1 = df1.withColumn("Action", regexp_replace($"Action", "[|!|]", ""))

val textRdd2 = sparkContext.textFile("input path to file 2 in hdfs")
val rowRdd2 = textRdd2.map(line => Row.fromSeq(line.split("\\|\\^\\|", -1)))
var df2 = sqlContext.createDataFrame(rowRdd2, schema)
df2 = df2.withColumn("Action", regexp_replace($"Action", "[|!|]", ""))
df1
的输出为

+----------+------+---------+--------+------+
|OgId      |ItemId|segmentId|Sequence|Action|
+----------+------+---------+--------+------+
|4295877341|136   |4        |1       |I     |
|4295877346|136   |4        |1       |I     |
|4295877341|138   |2        |1       |I     |
|4295877341|141   |4        |1       |I     |
|4295877341|143   |2        |1       |I     |
|4295877341|145   |14       |1       |I     |
+----------+------+---------+--------+------+
+----------+------+---------+--------+------+
|OgId      |ItemId|segmentId|Sequence|Action|
+----------+------+---------+--------+------+
|4295877341|213   |4        |1       |I     |
|4295877341|215   |2        |1       |I     |
|4295877341|141   |4        |1       |I     |
|4295877341|143   |2        |1       |I     |
|4295877343|149   |14       |2       |I     |
+----------+------+---------+--------+------+
df2
的输出为

+----------+------+---------+--------+------+
|OgId      |ItemId|segmentId|Sequence|Action|
+----------+------+---------+--------+------+
|4295877341|136   |4        |1       |I     |
|4295877346|136   |4        |1       |I     |
|4295877341|138   |2        |1       |I     |
|4295877341|141   |4        |1       |I     |
|4295877341|143   |2        |1       |I     |
|4295877341|145   |14       |1       |I     |
+----------+------+---------+--------+------+
+----------+------+---------+--------+------+
|OgId      |ItemId|segmentId|Sequence|Action|
+----------+------+---------+--------+------+
|4295877341|213   |4        |1       |I     |
|4295877341|215   |2        |1       |I     |
|4295877341|141   |4        |1       |I     |
|4295877341|143   |2        |1       |I     |
|4295877343|149   |14       |2       |I     |
+----------+------+---------+--------+------+
现在,根据您的要求,如果
OgId
df2
匹配,您需要从
df1
中删除
,并将所有
df2
附加到
df1
。这些要求可按如下方式完成

val tempdf = df2.select("OgId").withColumnRenamed("OgId", "OgId_1")

df1 = df1.join(tempdf, df1("OgId") === tempdf("OgId_1"), "left")
df1 = df1.filter("OgId_1 is null").drop("OgId_1")
df1 = df1.union(df2)
最终输出为

+----------+------+---------+--------+------+
|OgId      |ItemId|segmentId|Sequence|Action|
+----------+------+---------+--------+------+
|4295877346|136   |4        |1       |I     |
|4295877341|213   |4        |1       |I     |
|4295877341|215   |2        |1       |I     |
|4295877341|141   |4        |1       |I     |
|4295877341|143   |2        |1       |I     |
|4295877343|149   |14       |2       |I     |
+----------+------+---------+--------+------+
此最终结果可以保存在
hdfs
中,如下所示

df1.write.format("com.databricks.spark.csv").save("output file path in hdfs")
我希望这是有帮助的


注意:确保正确写入输入和输出位置的路径

为什么要在mapreduce中使用?我建议你用scala回答Spark和Hadoop的问题好吗?是的,请回答…一些代码可能是greatI我猜你对Spark、scala和dataFrame有一定的了解,是吗?我不理解你的行
。如果在第一个文件中找到相同的OrgId,那么我必须替换为新的OrgId,如果没有,那么我必须插入新的OrgId。
你能澄清一下吗?是的,我已经开始学习。对于我的问题,基本上,如果OrgId不匹配,我必须用新记录替换记录然后它将被视为新记录,因此将被追加。如果您遇到任何问题,请务必告诉我。:)如果你认为答案值得,请投赞成票thanksHi Ramesh只有一个问题,如果我有一个增量文件,它的头和基文件不一样,那么这个解决方案也会起作用?而且我的增量文件是有序的,所以如果我们加入,那么更新顺序将被保留?头名称是用模式定义的。因此,头名称是否不同并不重要。但数据应采用相同的列格式。我不明白你的第二个问题。嗨,拉梅什。这也是主订单吗?我的意思是先到的记录会先更新吗?玩一下:)我想你可以做到。我建议您增加executor cores:)