在开始学习大数据时,我参考过许多学习路线的建议,但觉得直接照搬别人的学习顺序未必适合自己。最后结合工作需要和个人经历,我制定了一套适合自己的学习路线: 开始学习Linux命令和系统基本概念。然后分别学习Java、Python以及Scala这几种在大数据开发中常用的编程语言。然后着重学习Hadoop核心技术如HDFS和MapReduce;接触数据库Hive后,学习数据流技术Kafka和分布式协调服务Zookeeper。深入研究Yarn和求执行引擎Spark。此外还了解其他技术如HBase、Sqoop等。同时学习计算机网络知识和操作系统原理。后面再系统学习关系数据库MySQL和数据仓库理论。学习分布式原理和架构也很重要。 这个学习顺序参考了我之前的工作和学习经历情况后订定。需要注意,大数据领域的技术很多很广,如Flink也值得研究。本人给出的仅作为一个参考案例,学习者还需结合实际情况选择合适的学习路径。
这里举一个我学习Spark时遇到的难点例子, alongside 相关代码。 学习难点:Spark中RDD的转换和行动操作 在开始学习Spark时,理解RDD的转换和行动操作是一个难点。RDD本身是一个不可变的分布式数据集,它支持两类基础操作: 转换操作(transformation):转换RDD会产生新的RDD。例如:map、filter、 flatMap 等。行动操作(action):RDD的转换操作是惰性计算的,只有在行动操作时才会真正触发任务的执行。 这给我带来一定困惑:RDD转换不会执行计算,它们会记录要运行的操作而不运行它们。那么转换产生的RDD是存储在Driver还是Executor中?当有多个转换操作时,它们如何串联执行?行动操作什么时候和怎样触发转换操作的执行?为了解答这些问题,我打印日志观察执行过程,并写了以下代码测试:
// 创建一个RDD
val rdd = spark.sparkContext.parallelize(1 to 1000)
// 转换操作
val mapRDD = rdd.map(_ * 2)
val filterRDD = mapRDD.filter(_ < 100)
// 行动操作
filterRDD.collect.foreach(println)
通过观察日志,我看到转换操作记录在Driver中而不执行,直到collect触发,此时串行所有转换操作在Executor上执行。这样解答了我之前的疑问,也巩固了RDD基本概念。这个例子帮助我理解Spark的运行机制。
再比如我学习SparkSQL时遇到的难点例子。 学习难点: SQL on RDD与SQL on Dataset/DataFrame的区别。 在学习SparkSQL时,我发现它支持两种SQL查询方式:使用SQL对RDD进行查询,以及使用SQL对Dataset/DataFrame进行查询。区分两个概念变得很重要。 为了理解区别,我编写了以下代码进行测试:
// 使用RDD
val rdd = spark.sparkContext.parallelize(
Seq(("a", 1), ("b", 2), ("c", 3))
)
// 注册RDD为临时表
rdd.toDF("key", "value").createOrReplaceTempView("table")
// SQL查询
spark.sql("SELECT key, value FROM table WHERE value > 1")
// 使用Dataset
val df = Seq(
("a", 1), ("b", 2), ("c", 3)
).toDF("key", "value")
// SQL查询
df.createOrReplaceTempView("table")
spark.sql("SELECT key, value FROM table WHERE value > 1")
通过观察执行计划,我发现:对RDD进行SQL查询,内部需要进行对象-关系映射的转换。而DataFrame/Dataset由结构化数据表示,可以直接支持Catalyst优化执行计划。这解答了我SQL两种方式执行效率的不同之处。这个实践例子帮助我真正理解了SparkSQL的运作机制。
再比如如何进行大数据的实时计算和分析。 以实时交易数据分析为例,需要对每笔交易进行实时计算和分析,找出异常交易模式。 这里使用Spark Streaming来处理这个需求:设置Spark Streaming环境,创建StreamingContext对象,设置批处理时间窗口为1秒
SparkConf conf = new SparkConf().setAppName("TransactionAnalysis");
JavaStreamingContext jssc = new JavaStreamingContext(conf, Durations.seconds(1));
从Kafkatopic中读取交易数据流
JavaInputDStream<String> transactionData = KafkaUtils.createStream(jssc, "localhost:2181","transaction-group", topic);
对每笔记录进行结构化,解析成Case类对象
JavaDStream<Case> transactions = transactionData.map(record -> {
//解析记录返回Case对象
return new Case(/*fields*/);
});
实时计算策略,如交易额是否超过一定阈值等
JavaDStream<Case> result = transactions.mapPartitions(iter -> {
//每批次数据内实时分析
while(iter.hasNext()) {
Case t = iter.next();
//计算策略
checkPolicy(t);
}
});
最后将结果写回其他存储系统如Redis。
感谢这次学习的机会,它让我对数据与技术有了新的认识。我对大数据还有很深的兴趣,未来还会继续研究相关领域。
infoq原文:我的大数据学习总结_Geek-yan_InfoQ写作社区