我们在Spark中有一个要求,即来自Feed的每条记录都会被分成一组。
示例server.port=8089
server.ssl.enabled=true
server.ssl.key-store=src/main/resources/keystore.p12
server.ssl.key-store-password=****
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias=tomcat
,java.io.IOException: Alias name tomcat does not identify a key entry
at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:596)
at org.apache.tomcat.util.net.jsse.JSSESocketFactory.getKeyManagers(JSSESocketFactory.java:534)
at org.apache.tomcat.util.net.NioEndpoint.bind(NioEndpoint.java:363)
at org.apache.tomcat.util.net.AbstractEndpoint.start(AbstractEndpoint.java:739)
at org.apache.coyote.AbstractProtocol.start(AbstractProtocol.java:472)
at org.apache.coyote.http11.Http11NioProtocol.start(Http11NioProtocol.java:81)
at org.apache.catalina.connector.Connector.startInternal(Connector.java:986)
,{col1,col2,col3}=>Resource
等。
现在我需要在ETL层中生成一个唯一标识符,它可以分别持久保存到上述每个表/实体的数据库表中。
此唯一标识符用于查找值以标识每个表记录并在数据库中生成序列。
但是第二种选择并没有被很多人所接受。 在ETL层中创建唯一键的其他选项/解决方案有哪些,可以在DB中查找以进行比较。
先谢谢, Rajesh Giriayppa
答案 0 :(得分:1)
使用数据帧,您可以使用“生成单调增加的64位整数”20
函数(https://spark.apache.org/docs/2.1.0/api/scala/index.html#org.apache.spark.sql.functions $)。它可以这样使用:
monotonicallyIncreasingId
使用RDD,您可以使用dataframe.withColumn("INDEX", functions.monotonicallyIncreasingId())
或zipWithIndex
。前者生成一个真实的索引(在0和N-1之间排序,N是RDD的大小),而后者生成唯一的长ID,而没有进一步的保证,这似乎是你需要的(https://spark.apache.org/docs/2.1.0/api/scala/index.html#org.apache.spark.rdd.RDD)。请注意,zipWithUniqueId
甚至不会触发火花作业,因此几乎是免费的。
答案 1 :(得分:1)
感谢您的回复,我尝试过这种方法,它不会给我相关或代理主键来搜索数据库。每次运行etl作业索引或数字对于每条记录都会有所不同,如果我的数据集计数变化。 我需要唯一的我要与dB记录相关联,它只匹配一条记录,并且应该是以dB为单位的同一记录。
是否有任何好的设计模式或做法可以将etl数据集行与dB记录进行比较,并且具有唯一的I'。
答案 2 :(得分:1)
这有点晚了,但是如果有人在找...
我遇到了类似的要求。如Oli先前所述,zipWithIndex将给出顺序的,零索引的ID,然后您可以将其映射到偏移量。请注意,其中有一个关键部分,因此根据使用情况,可能需要锁定机制。
case class Resource(_1: String, _2: String, _3: String, id: Option[Long])
case class Account(_4: String, _5: String, _6: String, id: Option[Long])
val inDS = Seq(
("a1", "b1", "c1", "x1", "y1", "z1"),
("a2", "b2", "c2", "x2", "y2", "z2"),
("a3", "b3", "c3", "x3", "y3", "z3")).toDS()
val offset = 1001 // load actual offset from db
val withSeqIdsDS = inDS.map(x => (Resource(x._1, x._2, x._3, None), Account(x._4, x._5, x._6, None)))
.rdd.zipWithIndex // map index from 0 to n-1
.map(x => (
x._1._1.copy(id = Option(offset + x._2 * 2)),
x._1._2.copy(id = Option(offset + x._2 * 2 + 1))
)).toDS()
// save new offset to db
withSeqIdsDS.show()
+---------------+---------------+
| _1| _2|
+---------------+---------------+
|[a1,b1,c1,1001]|[x1,y1,z1,1002]|
|[a2,b2,c2,1003]|[x2,y2,z2,1004]|
|[a3,b3,c3,1005]|[x3,y3,z3,1006]|
+---------------+---------------+
withSeqIdsDS.select("_1.*", "_2.*").show
+---+---+---+----+---+---+---+----+
| _1| _2| _3| id| _4| _5| _6| id|
+---+---+---+----+---+---+---+----+
| a1| b1| c1|1001| x1| y1| z1|1002|
| a2| b2| c2|1003| x2| y2| z2|1004|
| a3| b3| c3|1005| x3| y3| z3|1006|
+---+---+---+----+---+---+---+----+
答案 3 :(得分:0)
以下内容可以帮助你@Rajesh吗?
import org.apache.spark.SparkConf
import org.apache.spark.sql.SparkSession
val sparkConf = new SparkConf().setAppName("hash-to-db").setMaster("local")
val spark = SparkSession.builder().config(sparkConf).getOrCreate()
import org.apache.spark.sql.functions._
import spark.implicits._
var dfA = spark.createDataset(Seq(
(4, "01/01/2017"),
(2, "03/01/2017"),
(6, "04/01/2017"),
(1, "05/01/2017"),
(5, "09/01/2017"),
(3, "02/01/2017"),
(11, "01/01/2017"),
(12, "03/01/2017"),
(16, "04/01/2017"),
(21, "05/01/2017"),
(35, "09/01/2017"),
(13, "02/01/2017")
)).toDF("id", "date")
dfA
.withColumn("db_id", sha2(concat($"id", $"date"), 256))
.toDF(cols: _*).show()
dfA.foreachPartition {
iter => /* update db here*/
}
最初我们有一个带有('id','date')的数据框,我们假设它是你的一个表。接下来使用withColumn("db_id", concat($"id", $"date"))
我们生成一个新列,我们通过连接id + date来调用 db_id ,这将是哈希的提要。
map函数将根据db_id中的SHA2算法生成一个哈希值。
最后在foreachPartition中,您可以将db_id和更多内容存储到数据库中。
这是我的样本数据的输出:
+---+----------+--------------------+
| id| date| db_id|
+---+----------+--------------------+
| 4|01/01/2017|6e8480d61a3c10dc6...|
| 2|03/01/2017|6274256111354de0a...|
| 6|04/01/2017|da1df6398a3d1cd1b...|
| 1|05/01/2017|7eee447fea5a0c617...|
| 5|09/01/2017|91ba5395428b9c020...|
| 3|02/01/2017|d645e6e7f3ea32143...|
| 11|01/01/2017|1d8efa87c0314d163...|
| 12|03/01/2017|f73fc571d46cb8ce8...|
| 16|04/01/2017|f68486fdb68499f21...|
| 21|05/01/2017|8d83f80492170d8e9...|
| 35|09/01/2017|66e99f71ba22d97e2...|
| 13|02/01/2017|996ae110f1a2fc855...|
+---+----------+--------------------+
如果您完全确定记录的唯一性,则可能决定仅保留连接部分并跳过哈希。
祝你好运