这里有个疑问?内存不够怎么办呢?
Does my data need to fit in memory to use Spark? 我的数据需要放入内存才能使用Spark吗?
No. Spark’s operators spill data to disk if it does not in memory, allowing it to run well on any sized data. Likewise, cached datasets that do not fit in memory are either spilled to disk or recomputed on the fly when needed, as determined by the RDD’s storage level.
不会。如果不合适存储在内存,那么Spark的操作员会将数据溢写到磁盘上,这样就可以不管数据大小如何而良好运行。同样,不适合内存的缓存数据集要么溢出到磁盘,要么在需要时实时重新计算,这由RDD的存储级别决定。
standAlone:它是 spark 自带的独立运行模式,整个任务的资源分配由 spark 集群的老大 Master 负责
yarn:可以把 spark 程序提交到 yarn 中运行,整个任务的资源分配由 yarn 中的老大 ResourceManager 负责
mesos:它也是 apache 开源的一个类似于 yarn 的资源调度平台
cassandra:是一套开源分布式 NoSQL 数据库系统
kubernetes:用于管理云平台中多个主机上的容器化的应用
hbase:是一个分布式的、面向列的开源数据库
实现要搭建好 Zookeeper 和 Hadoop 集群
# 在 node01 的 /bigdata/soft 目录下载
wget https://archive.apache.org/dist/spark/spark-2.3.3/spark-2.3.3-bin-hadoop2.7.tgz
tar -zxvf spark-2.3.3-bin-hadoop2.7.tgz -C /bigdata/install
spark-env.sh
:进入到 spark 安装目录下对应的 conf 目录,先在 node01 进行如下文件的修改# 修改 spark-env.sh
$ pwd
/bigdata/install/spark-2.3.3-bin-hadoop2.7/conf
$ cp spark-env.sh.template spark-env.sh
$ vim spark-env.sh
# 配置 JAVA 的环境变量
export JAVA_HOME=/usr/apps/jdk1.8.0_241
export SPARK_HISTORY_OPTS="-Dspark.history.ui.port=4000 -Dspark.history.retainedApplications=3 -Dspark.history.fs.logDirectory=hdfs://node01:8020/spark_log"
# 配置 ZK 相关信息
export SPARK_DAEMON_JAVA_OPTS="-Dspark.deploy.recoveryMode=ZOOKEEPER -Dspark.deploy.zookeeper.url=node01:2181,node02:2181,node03:2181 -Dspark.deploy.zookeeper.dir=/spark"
slaves
$ cp slaves.template slaves
$ vim slaves
# 指定spark集群的worker节点
node01
node02
node03
spark-defaults.conf
$ cp spark-defaults.conf.template spark-defaults.conf
$ vim spark-defaults.conf
# 修改内容如下
spark.eventLog.enabled true
spark.eventLog.dir hdfs://node01:8020/spark_log
spark.eventLog.compress true
# 如果 spark 运行过程中报 lzo 错误,将以下两项添加进来
spark.driver.extraClassPath /bigdata/install/hadoop-3.1.4/share/hadoop/common/hadoop-lzo-0.4.20.jar
spark.executor.extraClassPath /bigdata/install/hadoop-3.1.4/share/hadoop/common/hadoop-lzo-0.4.20.jar
$ cd /bigdata/install/
$ scp -r spark-2.3.3-bin-hadoop2.7/ node02:$PWD
$ scp -r spark-2.3.3-bin-hadoop2.7/ node03:$PWD
hdfs dfs -mkdir -p /spark_log
$ sudo su
# vim /etc/profile
# 配置Spark环境变量
export SPARK_HOME=/bigdata/install/spark-2.3.3-bin-hadoop2.7
export PATH=$PATH:$SPARK_HOME/bin
# source /etc/profile
# node01 执行
$ pwd
/bigdata/install/spark-2.3.3-bin-hadoop2.7/sbin
# 在哪里启动start-all.sh脚本,就在当前该机器启动一个Master进程,整个集群的worker进程的启动由 workers 文件决定
$ ./start-all.sh
# 启动历史服务
$ ./start-history-server.sh
$SPARK_HOME/sbin/start-master.sh
xcall jps
$SPARK_HOME/sbin/stop-all.sh
$SPARK_HOME/sbin/stop-master.sh
如何恢复到上一次活着的 master 挂掉之前的状态?
在master的恢复阶段对任务的影响?
spark-submit \
--class <main-calss> \
--master <master-url> \
--deploy-mode <deploy-mode> \
--conf <key>=<value> \
... #其他 options
<application-jar> \
[application-arguments]
参数名称 | 参数含义 | 参数默认值 | 适用模式 |
---|---|---|---|
–master | 指定主节访问路径 | spark://host:port, mesos://host:port, yarn, k8s, or local 默认local[*] |
不同模式 使用不同值 |
–deploy-mode | 部署模式 | client ,cluster(默认client模式) | standAlone, on yarn |
–class | 指定main方法所在的class类 | 无默认值 | 同上 |
–name | application的名称 | 任意给定的名称 | 同上 |
–jars | 使用逗号隔开的列表 用以指定多个依赖的外部jar包 |
无默认值 | 同上 |
–packages | 通过maven坐标来搜索jar包 | 无默认值,一般不用这个参数 | 同上 |
–exclude-packages | 排除掉某些jar包 | 无默认值 | 同上 |
–repositories | 与–packages参数搭配使用 用于搜索指定远程仓库 |
无默认值,一般不用这个参数 | 同上 |
–files | 逗号隔开的文件列表 用于传递文件到executor里面去 |
无默认值,可以用作广播变量 | 同上 |
–conf | 指定spark的配置项 | 无默认值 | 同上 |
–properties-file | 指定spark的配置文件 | 无默认值 | 同上 |
–driver-memory | driver端内存大小 | 默认1024M,可以指定2G | 同上 |
–driver-java-options | 额外的jar的配置选项传递到driver端 | 无默认值 | 同上 |
–driver-library-path | driver端额外指定的jar包路径 | 无默认值 | 同上 |
–driver-class-path | 为driver端指定额外的class文件 | 无默认值 | 同上 |
–executor-memory | 每个executor的内存大小 | 默认 1G | 同上 |
–proxy-user | 指定代理提交用户 | 无默认值 | 同上 |
–driver-cores | driver的CPU核数 | 默认值 1 | cluster模式 |
–supervise | 如果指定这个参数 任务失败就重启driver端 |
无默认值 | Spark standAlone cluster模式 |
–kill | 杀死指定的driver | 无默认值 | 同上 |
–status | 查看driver的状态 | 无默认值 | 同上 |
–total-executor-cores | 总共分配多少核CPU给所有的executor | 无默认值 | Spark standalone |
–executor-cores | 每个executor分配的CPU核数 | standAlone on yarn | |
–queue | 提交到哪个yarn队列 | yarn | |
–num-executors | 启动的executor的个数 | yarn | |
–archives | 逗号隔开的列表 | yarn |
$ pwd
/bigdata/install/spark-2.3.3-bin-hadoop2.7
$ spark-submit \
--class org.apache.spark.examples.SparkPi \
--master local \
--executor-memory 2G \
--total-executor-cores 4 \
examples/jars/spark-examples_2.11-2.3.3.jar \
10
spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://node01:7077 \
--deploy-mode client \
--executor-memory 2G \
--total-executor-cores 4 \
examples/jars/spark-examples_2.11-2.3.3.jar \
10
# 多master提交
spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://node01:7077,node02:7077 \
--deploy-mode client \
--executor-memory 2G \
--total-executor-cores 4 \
examples/jars/spark-examples_2.11-2.3.3.jar \
10
spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://node01:7077,node02:7077 \
--deploy-mode cluster \
--executor-memory 2G \
--total-executor-cores 4 \
examples/jars/spark-examples_2.11-2.3.3.jar \
10
spark集群中有很多个master,并不知道哪一个master是活着的master,即使你知道哪一个master是活着的master,它也有可能下一秒就挂掉,这里就可以把所有master都罗列出来
–master spark://node01:7077,node02:7077
后期程序会轮训整个master列表,最终找到活着的master,然后向它申请计算资源,最后运行程序。
export HADOOP_CONF_DIR=/bigdata/install/hadoop-3.1.4/etc/hadoop
spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode client \
examples/jars/spark-examples_2.11-2.3.3.jar \
10
# 告诉yarn要跳转的spark的historyServer地址
spark.yarn.historyServer.address=node01:4000
# 设置spark的historyServer端口
spark.history.ui.port=4000
spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
examples/jars/spark-examples_2.11-2.3.3.jar \
10
# 创建 word.txt 文件
vim words.txt
# 内容如下
hadoop flink spark
hive flink spark
flink datax
hadoop dfs -put words.txt /
spark-shell
scala> sc.textFile("/words.txt").flatMap(line => line.split(' ')).map((_,1)).reduceByKey(_ + _).collect
<dependency>
<groupId>org.apache.sparkgroupId>
<artifactId>spark-core_2.11artifactId>
<version>2.3.3version>
dependency>
hello,spark
hello,scala,hadoop
hello,hdfs
hello,spark,hadoop
hello
public class JavaWordCount {
public static void main(String[] args) {
// 1. 创建 SparkConf 对象
SparkConf sparkConf = new SparkConf()
.setAppName(JavaWordCount.class.getSimpleName())
.setMaster("local[*]");
// 2. 构建 JavaSparkContext 对象
JavaSparkContext jsc = new JavaSparkContext(sparkConf);
// 3. 读取数据文件
JavaRDD<String> lines = jsc.textFile(ClassLoader.getSystemResource("word.csv").getPath());
// 4. 切分每一行获取所有的单词
// 将每行数据,生成一个由单词组成的数组;然后每行组成的数组进行 flat,生成最终的所有的单词组成的数组 ==>> RDD
JavaRDD<String> words = lines.flatMap(line -> Arrays.asList(line.split(",")).iterator());
// 5. 将单词变成(word, 1)
JavaPairRDD<String, Integer> wordAndOne = words.mapToPair(word -> new Tuple2<>(word, 1));
// 6. 将 wordAndOne 按照 key 分组,每组 value 进行聚合
JavaPairRDD<String, Integer> wordAndTotal = wordAndOne.reduceByKey(Integer::sum);
// 7. 结果,按照每组的个数进行排序
/**
* (hadoop, 2) (hive, 1)
* (spark, 3) ==>> (hadoop, 2)
* (hive, 1) (spark, 3)
*
* ① 为了实现按照数值进行排序的功能,首先将每个kv对的kv进行调换位置 (hadoop, 2) 变成了(2, hadoop)
* ② 然后按照k进行排序(这是的key是数值) (2, hadoop)
* ③ 排完顺序后,再将kv调换顺序,(word, totalCount)的形式
*/
JavaPairRDD<Integer, String> totalAndWord = wordAndTotal.mapToPair(v -> new Tuple2<>(v._2, v._1));
JavaPairRDD<Integer, String> sortedTotalAndWord = totalAndWord.sortByKey(true);
JavaPairRDD<String, Integer> sortedResult = sortedTotalAndWord.mapToPair(v -> new Tuple2<>(v._2, v._1));
List<Tuple2<String, Integer>> result = sortedResult.collect();
for (Tuple2<String, Integer> tuple2 : result) {
System.out.println("单词:" + tuple2._1 + ", 个数:" + tuple2._2);
}
jsc.stop();
}
}
object WordCountLocalV1 {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf()
.setAppName(WordCountLocalV1.getClass.getSimpleName)
.setMaster("local[*]")
val sc: SparkContext = new SparkContext(sparkConf)
val tuples: Array[(String, Int)]= sc.textFile(ClassLoader.getSystemResource("word.csv").getPath)
.flatMap(line => line.split(","))
.map(word => (word, 1))
.reduceByKey((x, y) => x + y)
.collect()
tuples.foreach(println)
sc.stop()
}
}
/**
* 集群模式运行 简写版本
*/
object WordCountCluster {
def main(args: Array[String]): Unit = {
val sparkConf = new SparkConf()
.setAppName(WordCountCluster.getClass.getSimpleName)
// .setMaster("local[*]")
val sc: SparkContext = new SparkContext(sparkConf)
val ret: RDD[(String, Int)]= sc.textFile(args(0))
.flatMap(_.split(" "))
.map((_, 1))
.reduceByKey(_ + _)
// .collect()
ret.saveAsTextFile(args(1))
sc.stop()
}
}
# spark standalone client模式
spark-submit --master spark://node01:7077,node02:7077 \
--deploy-mode client \
--class com.yw.spark.example.WordCountCluster \
--executor-memory 1g \
--total-executor-cores 2 \
original-spark-demo-1.0.jar \
hdfs://node01:8020/words.txt hdfs://node01:8020/words_output
# spark standalone cluster模式
spark-submit --master spark://node01:7077,node02:7077 \
--deploy-mode cluster \
--class com.yw.spark.example.WordCountCluster \
--executor-memory 1g \
--total-executor-cores 2 \
hdfs://node01:8020/original-spark-demo-1.0.jar \
hdfs://node01:8020/words.txt hdfs://node01:8020/words_output
注意:如果是cluster模式,需要将jar包上传到hdfs上,路径为->hdfs://node01:8020/xxx.jar
各参数的值根据自己的实际情况修改,如–master、–class、jar包名称等