提交 1f9f142f 编写于 作者: kingreatwill's avatar kingreatwill

大数据学习。

上级 80e06d84
[哈弗大学 排序算法动画](https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html)
\ No newline at end of file
[哈弗大学 排序算法动画](https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html)
[算法可视化](https://github.com/algorithm-visualizer/algorithm-visualizer)
[算法可视化 demo](https://algorithm-visualizer.org/simple-recursive/cellular-automata)
\ No newline at end of file
......@@ -26,7 +26,7 @@ export SPARK_MASTER_IP=192.168.110.216
export SPARK_MASTER_PORT=7077
export SPARK_WORKER_CORES=1
export SPARK_WORKER_INSTANCES=1
export PYSPARK_PYTHON=python3
......@@ -101,6 +101,8 @@ Row(value='# Apache Spark')
# Scala
%SPARK_HOME%\bin\spark-shell
# PYSPARK_DRIVER_PYTHON设置为ipython后,pyspark交互模式变为ipython模式
```
......
https://github.com/onurakpolat/awesome-bigdata
https://github.com/youngwookim/awesome-hadoop
\ No newline at end of file
## distributed-storage
### SeaweedFS - HDFS
https://github.com/chrislusf/seaweedfs
## distributed-computing
### gleam - spark
https://github.com/chrislusf/gleam
## distributed-database
### etcd - zookeeper
https://github.com/etcd-io/etcd
Relational
hive
Wide column
HBase
Cassandra
## spark架构原理
1、Driver,启动之后执行一些初始化操作,然后向Master进行注册,让master知道有一个spark应用程序要执行。在Executor反向注册以后,就可以开始正式执行spark程序,首先第一步创建初始RDD,读取数据源。从HDFS文件内容中读取数据,分布到work节点上,形成内存中的分布式数据集也就是初始RDD。Driver会根据我们对RDD定义的操作,提交一堆task去excecutor上去
2、Master,master主要复制资源调度和集群监控等功能。它收到Driver发送的请求后,发送请求给work,进行资源分配就是分配一些executor
3、Worker,主要负责存储rdd的一些和部分partition,另外一个就是启动其他进程和线程对partition进行版型处理和计算。Executor启动后会反向向Driver进行注册,这样Driver就知道那些executor为他进行服务
4、Executor,executor接收到多个task后会启动多个线程来执行task
5、Task task就会对RDD的partition数据执行指定的算子操作,形成新的RDD的partition
![](img/spark-flow.png)
## spark-spark RDD的创建
进行Spark核心编程时,首先要做的第一件事,就是创建一个初始的RDD。该RDD中,通常就代表和包含了Spark应用程序的输入源数据。然后在创建了初始的RDD之后,才可以通过Spark Core提供的transformation算子,对该RDD进行转换,来获取其他的RDD。
Spark Core提供了三种创建RDD的方式,包括:使用程序中的集合创建RDD;使用本地文件创建RDD;使用HDFS文件创建RDD。
1、使用程序中的集合创建RDD,主要用于进行测试,可以在实际部署到集群运行之前,自己使用集合构造测试数据,来测试后面的spark应用的流程。`sc.parallelize(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));`
2、使用本地文件创建RDD,主要用于临时性地处理一些存储了大量数据的文件。集群上运行时需要所有集群上都有该文件 `sc.textFile("C://Users//Administrator//Desktop//spark.txt");`
3、使用HDFS文件创建RDD,应该是最常用的生产环境处理方式,主要可以针对HDFS上存储的大数据,进行离线批处理操作。`sc.textFile("hdfs://spark1:9000/spark.txt");`
如果要通过并行化集合来创建RDD,需要针对程序中的集合,调用SparkContext的parallelize()方法。Spark会将集合中的数据拷贝到集群上去,形成一个分布式的数据集合,也就是一个RDD。相当于是,集合中的部分数据会到一个节点上,而另一部分数据会到其他节点上。然后就可以用并行的方式来操作这个分布式数据集合,即RDD。
调用parallelize()时,有一个重要的参数可以指定,就是要将集合切分成多少个partition。Spark会为每一个partition运行一个task来进行处理。Spark官方的建议是,为集群中的每个CPU创建2~4个partition。Spark默认会根据集群的情况来设置partition的数量。但是也可以在调用parallelize()方法时,传入第二个参数,来设置RDD的partition数量。比如parallelize(arr, 10)
Spark是支持使用任何Hadoop支持的存储系统上的文件创建RDD的,比如说HDFS、Cassandra、HBase以及本地文件。通过调用SparkContext的textFile()方法,可以针对本地文件或HDFS文件创建RDD。
有几个事项是需要注意的:
1、如果是针对本地文件的话,如果是在windows上本地测试,windows上有一份文件即可;如果是在spark集群上针对linux本地文件,那么需要将文件拷贝到所有worker节点上。
2、Spark的textFile()方法支持针对目录、压缩文件以及通配符进行RDD创建。
3、Spark默认会为hdfs文件的每一个block创建一个partition,但是也可以通过textFile()的第二个参数手动设置分区数量,只能比block数量多,不能比block数量少。
## Spark-Spark RDD操作
Spark只支持两种RDD操作,transformation和action操作,transformation针对已有的RDD创建一个新的RDD文件,action主要是对RDD进行最后操作,比如遍历和reduce、保存到文件等,并可以返回结果到Driver程序
transformation,都具有lazy特性,只定义transformation操作是不会执行,只有接着执行一个action操作后才会执行。通过lazy特性避免产生过多中间结果。
wordcount程序就是如下执行流程,如下这块都在driver节点执行。所有transformation都是lazy,不会立即执行,只有执行了action后,才会触发job,提交task到spark集群上,进行实际的执行
transformation介绍
操作 | 介绍
---|---
map |将RDD中的每个元素传入自定义函数,获取一个新的元素,然后用新的元素组成新的RDD
filter |对RDD中的元素进行判断,如果返回true则保留,返回false则剔除
flatMap |与map类似,但是对每个元素都可以返回一个或多个新元素
groupByKey |根据key进行分组,每个key对应一个Iterable<Value>
reduceByKey |对每个key对应的value进行reduce操作
sortByKey |对每个key对应的value进行排序操作
join| 对两个包含`<key,value>`对的RDD进行join操作,每个key join上的pair,都会传入自定义函数进行处理
co'group | 同join,但是每个可以对应的`Interable<value>`都会传入自定义函数进行处理
action介绍
操作| 介绍
---|---
reduce |将RDD元素进行聚合操作,第一个和第二个聚合,然后值与第三个依次类推
collect |将RDD中所有元素获取到本地客户端
count |获取RDD元素总数
take(n) |获取RDD前N个元素
saveAsTextFile |将RDD元素保存到文件中,对每个元素调用toString方法
countByKey |对每个Key进行count计数
foreach |对RDD中元素进行遍历
## Spark-RDD持久化
多次对某个RDD进行transformation或者action,如果没有做RDD持久化,那么每次都要重新计算一个RDD,会消耗大量时间,降低Spark性能。
Spark非常重要的一个功能特性就是可以将RDD持久化在内存中。当对RDD执行持久化操作时,每个节点都会将自己操作的RDD的partition持久化到内存中,并且在之后对该RDD的反复使用中,直接使用内存缓存的partition。这样的话,对于针对一个RDD反复执行多个操作的场景,就只要对RDD计算一次即可,后面直接使用该RDD,而不需要反复计算多次该RDD。
巧妙使用RDD持久化,甚至在某些场景下,可以将spark应用程序的性能提升10倍。对于迭代式算法和快速交互式应用来说,RDD持久化,是非常重要的。
要持久化一个RDD,只要调用其cache()或者persist()方法即可。在该RDD第一次被计算出来时,就会直接缓存在每个节点中。而且Spark的持久化机制还是自动容错的,如果持久化的RDD的任何partition丢失了,那么Spark会自动通过其源RDD,使用transformation操作重新计算该partition。
cache()和persist()的区别在于,cache()是persist()的一种简化方式,cache()的底层就是调用的persist()的无参版本,同时就是调用persist(MEMORY_ONLY),将数据持久化到内存中。如果需要从内存中清楚缓存,那么可以使用unpersist()方法。
Spark自己也会在shuffle操作时,进行数据的持久化,比如写入磁盘,主要是为了在节点失败时,避免需要重新计算整个过程。
RDD持久化是可以手动选择不同的策略的。比如可以将RDD持久化在内存中、持久化到磁盘上、使用序列化的方式持久化,多持久化的数据进行多路复用。只要在调用persist()时传入对应的StorageLevel即可。
持久化级别 | 含义
---|---
MEMORY_ONLY |以非序列化的Java对象的方式持久化在JVM内存中。如果内存无法完全存储RDD所有的partition,那么那些没有持久化的partition就会在下一次需要使用它的时候,重新被计算
MEMORY_AND_DISK|同上,但是当某些partition无法存储在内存中时,会持久化到磁盘中。下次需要使用这些partition时,需要从磁盘上读取
MEMORY_ONLY_SER |同MEMORY_ONLY,但是会使用Java序列化方式,将Java对象序列化后进行持久化。可以减少内存开销,但是需要进行反序列化,因此会加大CPU开销。
MEMORY_AND_DSK_SER |同MEMORY_AND_DSK。但是使用序列化方式持久化Java对象
DISK_ONLY |使用非序列化Java对象的方式持久化,完全存储到磁盘上
MEMORY_ONLY_2<br/>MEMORY_AND_DISK_2<br/>等等|如果是尾部加了2的持久化级别,表示会将持久化数据复用一份,保存到其他节点,从而在数据丢失时,不需要再次计算,只需要使用备份数据即可。
如何选择RDD持久化策略?
Spark提供的多种持久化级别,主要是为了在CPU和内存消耗之间进行取舍。下面是一些通用的持久化级别的选择建议:
1、优先使用MEMORY_ONLY,如果可以缓存所有数据的话,那么就使用这种策略。因为纯内存速度最快,而且没有序列化,不需要消耗CPU进行反序列化操作。
2、如果MEMORY_ONLY策略,无法存储的下所有数据的话,那么使用MEMORY_ONLY_SER,将数据进行序列化进行存储,纯内存操作还是非常快,只是要消耗CPU进行反序列化。
3、如果需要进行快速的失败恢复,那么就选择带后缀为_2的策略,进行数据的备份,这样在失败时,就不需要重新计算了。
4、能不使用DISK相关的策略,就不用使用,有的时候,从磁盘读取数据,还不如重新计算一次。
不使用RDD持久化
![](img/spark-rdd-notpersist.png)
使用RDD持久化`sc.textFile("E:\\spark\\spark.txt").cache();`
## Spark-共享变量工作原理
Spark一个非常重要的特性就是共享变量。
默认情况下,如果在一个算子的函数中使用到了某个外部的变量,那么这个变量的值会被拷贝到每个task中。此时每个task只能操作自己的那份变量副本。如果多个task想要共享某个变量,那么这种方式是做不到的。
Spark为此提供了两种共享变量,一种是Broadcast Variable(广播变量),另一种是Accumulator(累加变量)。Broadcast Variable会将使用到的变量,仅仅为每个节点拷贝一份,更大的用处是优化性能,减少网络传输以及内存消耗。Accumulator则可以让多个task共同操作一份变量,主要可以进行累加操作。
![](img/spark-share-vars.png)
broadcast示例
```java
package cn.spark.study.core;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.VoidFunction;
import org.apache.spark.broadcast.Broadcast;
import java.util.Arrays;
import java.util.List;
public class BroadcastVariable {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setAppName("WordCountLocal")
.setMaster("local");
JavaSparkContext sc = new JavaSparkContext(conf);
final int factor =3;
final Broadcast<Integer> factorBroadCast = sc.broadcast(factor);
List<Integer> numberlist = Arrays.asList(1,2,3,4,5);
JavaRDD<Integer> numbers = sc.parallelize(numberlist);
JavaRDD<Integer> multipleNumbers = numbers.map(new Function<Integer, Integer>() {
private static final long serialVersionUID =1l;
@Override
public Integer call(Integer integer) throws Exception {
return integer * factorBroadCast.getValue();
}
});
multipleNumbers.foreach(new VoidFunction<Integer>() {
@Override
public void call(Integer integer) throws Exception {
System.out.println(integer);
}
});
sc.close();
}
}
package cn.spark.study.core
import org.apache.spark.{SparkConf, SparkContext}
object BroadcastVariable{
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("Broadcast")
.setMaster("local")
val sparkContext = new SparkContext(conf)
val factor =3
val broadcast = sparkContext.broadcast(factor)
val numberArray = Array(1,2,3,4,5)
val numbers = sparkContext.parallelize(numberArray,1)
val multipleNumbers = numbers.map{num => num * broadcast.value}
multipleNumbers.foreach{num => println(num)}
}
}
```
```python
import sys
from operator import add
from pyspark.sql import SparkSession
if __name__ == "__main__":
spark = SparkSession \
.builder \
.appName("PythonWordCount") \
.getOrCreate()
sc = spark.sparkContext
factor = 3
b_f = sc.broadcast(factor)
counts = sc.parallelize(range(1, 6)).map(lambda x: x * b_f.value)
output = counts.collect()
print(output)
spark.stop()
```
accumulator示例
```java
package cn.spark.study.core;
import org.apache.spark.Accumulator;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.Function;
import org.apache.spark.api.java.function.VoidFunction;
import java.util.Arrays;
import java.util.List;
public class AccumulatorVariable {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setAppName("WordCountLocal")
.setMaster("local");
JavaSparkContext sc = new JavaSparkContext(conf);
final Accumulator<Integer> accumulator = sc.accumulator(0);
List<Integer> numberlist = Arrays.asList(1,2,3,4,5);
JavaRDD<Integer> numbers = sc.parallelize(numberlist);
numbers.foreach(new VoidFunction<Integer>() {
@Override
public void call(Integer integer) throws Exception {
accumulator.add(integer);
}
});
System.out.println(accumulator);
sc.close();
}
}
package cn.spark.study.core
import org.apache.spark.{SparkConf, SparkContext}
object AccumulatorVariable {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setAppName("Broadcast")
.setMaster("local")
val sparkContext = new SparkContext(conf)
val sum = sparkContext.accumulator(0)
val numberArray = Array(1,2,3,4,5)
val numbers = sparkContext.parallelize(numberArray,1)
numbers.foreach{sum +=_}
println(sum)
}
}
```
\ No newline at end of file
此差异已折叠。
[Go 编译器内核:给 Go 新增一个语句 ](https://studygolang.com/articles/25101)
\ No newline at end of file
## 学习资源
数据科学Python笔记本:深度学习(TensorFlow、Theano、Caffe、Keras)、scikit-learn、Kaggle、大数据(Spark、Hadoop MapReduce、HDFS)、matplotlib、panda、NumPy、SciPy、Python essentials、AWS和各种命令行。
https://github.com/donnemartin/data-science-ipython-notebooks
## IronPython vs. Python .NET
https://stackoverflow.com/questions/1168914/ironpython-vs-python-net
https://ironpython.net/
......
## gcc
gcc 是GNU编译器套件,是Linux下默认的C/C++编译器.在windows环境下可以通过MinGw等GNU for Windows类工具使用gcc编译套件
gcc最简单的编译命令如下
`gcc -c hello.c -ohello`
gcc -c 后可跟多个输入源文件,最终输出的可执行文件以-o表示.
-o后紧着希望生成的可执行文件的名称。
-c 选项表示只编译源文件,而不进行链接,所以对于链接中的错误是无法发现的
如果不使用-c选项则仅仅生成一个可执行文件,没有目标文件。
##Make
这里的make 代指 GNU Make,首先我们看下GNU Make的英文释义
GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files.
Make gets its knowledge of how to build your program from a file called the makefile, which lists each of the non-source files and how to compute it from other files. When you write a program, you should write a makefile for it, so that it is possible to use Make to build and install the program.
可以看出make工具的定义是通过编写的makefile脚本文件描述整个工程的编译、链接规则;通过脚本文件,对于复杂的工程也可以只通过一个命令就完成整个编译过程。
## CMake
CMake是一个跨平台的编译工具。事实上Cmake并不直接构建出最终的软件,而是产生不同平台标准的构建档(如 Unix的Makefile 或是 Windows Visual C++的 projects/workspaces),然后再依一般的构建方式使用。
CMkae目前主要使用场景是作为make的上层工具,产生可移植的makefile文件。
## Apple LLVM compiler 4.2和LLVM GCC 4.2
[LLVM和GCC的区别](https://www.cnblogs.com/zuopeng/p/4141467.html)
https://gcc.gnu.org/
[开发者将 GCC 的 JIT 库移植到 Windows](https://gcc.gnu.org/pipermail/gcc-patches/2020-May/546384.html)
\ No newline at end of file
## Chrome devtools
### 命令(Command) 菜单
Ctrl + Shift + P(mac->Cmd + Shift + P)打开“命令”菜单。
### 截图DOM元素
直接选中那个节点,打开 命令(Command) 菜单并且使用 节点截图(screenshot) 就可以了。
截取特定节点对应上图命令是Screenshot Capture node screenshot。
**全屏截图**:通过 Screenshot Capture full size screenshot 命令。
### 在控制台中使用上次操作的值
使用`$_`可以引用在控制台执行的前一步操作的返回值。如果您正在控制台调试一些JavaScript代码,并且需要引用先前的返回值,那么这可能非常方便。
### 重新发起xhr请求
我们可以通过google提供的Replay XHR的方式去发起一条新的请求,这样对于我们开发效率的提升是有所帮助的。(右键请求-》Replay XHR)
### 编辑页面上的任何文本
在控制台输入document.body.contentEditable="true"或者document.designMode = 'on'就可以实现对网页的编辑了。
其实这个还是比较实用的,比如你要测试一个DOM节点文字太长时,样式是否会混乱,或者要去直接修改页面元素去满足一些业务需求时。(我之前是在Elements面板一个一个去修改的)
### 网络面板(Network)的幻灯片模式
启动Network 面板下的Capture screenshots就可以在页面加载时捕捉屏幕截图。有点幻灯片的感觉。
单击每一帧截图,显示的就是对应时刻发生的网络请求。这种可视化的展现形式会让你更加清楚每一时刻发生的网络请求情况。
### 网络面板(Network)记录之前的请求
启动Network 面板下的Preserve log,之前页面跳转后之前的请求就不见了,很不方便。
### 动画检查
DevTools 中有一个动画面板,默认情况下它是关闭的,很多人可能不太清楚这个功能。它可以让你控制和操纵 CSS 动画,并且可视化这些动画是如何工作的。
要打开该面板,可以在 DevTools 右上角菜单 → More tools 中打开 Animations。
默认情况下,DevTools 会“监听”动画。一旦触发,它们将被添加到列表中。你能看到这些动画块如何显示。在动画本身上,DevTools 会向我们展示哪些属性正在更改,例如 background-color 或 transform。
然后,我们可以通过使用鼠标拖动或调整时间轴来修改该动画。
### 递增/递减 CSS 属性值
作为前端开发,平时少不了通过Elements面板去查找元素以及它的css样式。有时调整像素px会比较麻烦一点,这时就可以使用快捷键去帮你完成:
```
* 增量0.1
* Mac:Option +向上和Option +向下
* Windows:Alt +向上和Alt +向下
* 增量1
* Mac:向上+向下
* Windows:向上+向下
* 增量10
* Mac:⇧+向上和⇧+向下
* Windows:⇧+向上和⇧+向下
* 递增100
* Mac:⌘+向上和⌘+向下
* Windows:Ctrl +向上和Ctrl +向下
```
### 在低端设备和弱网情况下进行测试
我们平时开发一般都是在办公室(wifi 网速加快),而且设备一般都是市面上较新的。但是产品的研发和推广,一定要考虑低设备人群和弱网的情况。
在Chrome DevTools中可以轻松调节CPU功能和网络速度。这样,我们就可以测试 Web 应用程序性能并进行相应优化。
具体打开方式是:在Chrome DevTools中通过CMD/Ctrl + Shift + p打开命令菜单。然后输入Show Performance打开性能面板。
### copying & saving
在调试的过程中,我们总会有对 Dev Tools 里面的数据进行 复制 或者 保存 的操作,其实他们也是有一些小技巧的!
- copy() 没有试验通过, 不明白
可以通过全局的方法 copy() 在 console 里 copy 任何你能拿到的资源
- Store as global variable
如果在console中打印了一堆数据,想对这堆数据做额外的操作,可以将它存储为一个全局变量。只需要右击它,并选择 “Store as global variable”选项。第一次使用的话,它会创建一个名为 temp1 的变量,第二次创建 temp2,第三次 ... 。通过使用这些变量来操作对应的数据,不用再担心影响到他们原来的值。
### 自定义 devtools
大家平时用的最多的Chrome 主题可能就是白色/黑色这两种了,但用的久了,难免想尝试像IDE一样切换主题。
首先需要启用实验模式中的Allow custom UI themes
地址栏输入如下url`chrome://flags/#enable-devtools-experiments` # 启用实验功能并重启浏览器
控制台中使用快捷键F1打开设置,切换到Experiments 选项,启用Allow custom UI themes
从Chrome商店安装Material DevTools Theme Collection扩展程序,选择你喜欢的主题即可
### CSS/JS 覆盖率
Chrome DevTools 中的Coverage功能可以帮助我们查看代码的覆盖率。
打开调试面板,用快捷键 ctrl+shift+P 输入 Show Coverage调出相应面板,点击reload 按钮开始检测,
点击相应文件即可查看具体的覆盖情况(绿色的为用到的代码,红色表示没有用到的代码)
### 自定义代码片段 Snippets
在平常开发过程中,我们经常有些 JavaScript 的代码想在 Chrome Devtools中调试,直接在 console 下 写比较麻烦,或者我们经常有些代码片段(防抖、节流、获取地址栏参数等)想保存起来,每次打开 Devtools 都能获取到这些代码片段,而不用再去google,正好Chrome Devtool 就提供了这种功能。
在 Sources 这个tab栏下,有个 Snippets 标签,在里面可以添加一些常用的代码片段。
### 将图片复制为数据 URI
选择Network面板
在资源面板中选择Img
右键单击将其复制为数据URI(已编码为base 64)
### 媒体查询
什么是媒体查询(不懂):https://www.cnblogs.com/Kuoblog/p/12442780.html
媒体查询是自适应网页设计的基本部分。在Chrome Devtools中的设备模式下(左边的手机按钮),在三圆点菜单中点击 Show Media queries即可启用(最又上的三点按钮)。
Devtools会在样式表中检测媒体查询,并在顶端标尺中将它们显示为彩色条形。
那怎么使用呢?其实也很简单:
- 点击媒体查询条形,调整视口大小和预览适合目标屏幕大小的样式
- 右键点击某个条形,查看媒体查询在 CSS 中何处定义并跳到源代码中的定义
### keys/values
这个是Devtools提供的快速查看一个对象的key、values的API。用起来也很简单:
`keys(obj)` or `values(obj)` (`obj.keys()` `obj.values()`也可以)
### table
Devtools提供的用于将对象数组记录为表格的API:
table(listjson)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册