因为子类中容易造成变量的定义混乱。
跟Java相比,Scala函数类似于静态方法,但是却不需要依赖某个具体的类,Java中就算是静态方法也需要类名打点的形式进行调用,Scala中的函数不依赖某个具体的类。
Byte,Char,Short,Int,Long,Float,Double,Boolean。
简单来说,带有特质的对象就是在对象构造时指定其所需要的特质。
Unit类似于Java中的void,但又不完全相同。Unit更像是关系型数据库的null,虽然表示空的概念,但是null还是要占用底层存储的,void则表示一个空的概念,什么也没有。
数组转换的本质是对一个原始数组进行遍历操作的同时进行一些其它操作,操作完成后形成新的结果数组,原始数组不受影响。
在Java中,访问权限分为:public,private,protected和默认。在Scala中,可以通过类似的修饰符达到同样的效果;但是使用上有区别:
将一个接收多个参数的函数转化成一个接受一个参数的函数过程,可以简单的理解为一种特殊的参数列表声明方式。
是一种表达式,你不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。
协变:对于一个带类型参数的类型,比如List[T],如果对A及其子类型B,满足List[B]也符合List[A]的子类型,那么就称为covariance(协变)
逆变:如果List[A]是List[B]的子类型,即与原来的父子关系正相反,则称为contravariance(逆变)
样例类在主构造器前加case,自动生成伴生对象,自动封装属性。
判断对象是否为某个类型的实例
obj.isInstanceOf[T]
将对象转换为某个类型的实例
obj.asInstanceOf[T]
获取对象的类名
classOf
和Java一样,Scala构造对象也需要调用构造方法,并且可以有任意多个构造方法。
Scala类的构造器包括:主构造器和辅助构造器
如果主构造器无参数,小括号可省略,构建对象时调用的构造方法的小括号也可以省略。
Scala类的主构造器函数的形参包括三种类型:未用任何修饰、var修饰、val修饰
Scala语言是完全面向对象的语言,所以并没有静态的操作(即在Scala中没有静态的概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,该对象为单例对象。若单例对象名与类名一致,则称该单例对象这个类的伴生对象,这个类的所有静态内容都可以放置在它的伴生对象中声明。
Scala中Object所有属性和方法都是静态的,Object修饰单例对象(检测:创建两个对象,输出hashcode,若值相同,指向同一地址,则为单例模式)
好处:
序列化的作用是将对象或者其他数据结构转换成二进制流,便于传输,后续再使用反序列化将其还原。因为二进制流是最便于网络传输的数据格式。
apply方法在遇到类名就调用,一般声明在Object里面,因为Object是一个静态的单例对象,就可以直接调用,比方一个对象Object对象demo,调用apply方法如下,demo.apply(),简化形式就是demo(),非常容易和创建对象new demo()混淆,在apply方法里面都是创建对象等初始化工作。
模式匹配是一种类似Java里面的switch case语句的形式。但是比Java里面的switch case要强大很多,可以匹配基本数据类型,匹配数组,集合,还可以匹配类型,匹配样例类等,模式匹配有两种特殊形式:一种是偏函数,一种是option函数。
Actor是一个并发编程模型,类似Java里面的多线程,它是一个发消息-接受消息的机制实现并发,相比与Java的好处就是不需要操作共享变量,因此不会像Java多线程因为有共享变量而导致需要加锁,死锁等问题。
隐式转换是Scala里面非常高级的一个特性,广泛用在Scala的底层代码中,它本质来说是一个转换,需要有一个类,这个类一般是单例的(Object),里面定义了隐式的方法,隐式的函数,隐式的值,如果在其他地方需要导入隐式转换,那么就需要用import导入。
spark包含spark core,spark sql,spark streaming,spark graphX,spark mllib
RDD是Spark里面的弹性分布式数据集,RDD有如下5个特点:
Spark的shuffle意味着数据要重新洗牌,主要分为两个流程,第一个是shuffle write,另外一个是shuffle read。
shuffle write有两种方式,第一种类似于mapreduce的shuffle,第二种采用的是先排序后建立索引的方式,能大大减少第一种方式里面中间文件产生导致的性能降低。
shuffle的read过程,要先判断需要读取数据来自于本节点还是其他节点,如果是其他节点需要先建立一个socket连接,然后通过文件块的方式来读取。
SparkStreaming是Spark里面的一个做流式准实时计算的组件,它使用的数据结构是Dstream,Dstream里面是一连串时间片的rdd。
相比于Storm,SparkStreaming在实时性,保证数据不丢失方面都不占用优势,SparkStreaming在Spark支持者眼中的优势是SparkStreaming具有高吞吐性,最本质来说,SparkStreaming相比于Storm的优势是SparkStreaming可以和SparkCore,SparkSQL无缝整合。
相比于窄依赖,宽依赖需要Shuffle,从父RDD到子RDD,一个分片里面的数据,宽依赖的数据会分叉,就是会产生“多子”现象。而窄依赖,一个父RDD的分片对应于子RDD的一个分片,就是所谓的“独子”现象。
窗口函数是SparkStreaming中,可以自己定义一个时间段,这个时间段是前面DStream的时间切片的整数倍,同时定义一个窗口移动的时间这个时间也是前面时间切片的整数倍。
DStream是SparkStreaming的数据模型,本质就是一连串不间断的RDD,但是它是一个时间段的RDD,这些时间段的RDD源源不断的连接在一起。
这个时间可以自己设置,时间设置的越短,实时性越高,但是性能消耗也越大。
用户在Client端提交作业后,会由Driver运行main方法并创建SparkContext上下文。
执行RDD算子,形成DAG图输入DAGScheduler,按照RDD之间的依赖关系划分Stage输入TaskScheduler,TaskScheduler会将Stage划分为TaskSet分发到各个节点的Executor中执行。
Hadoop:map端保存分片数据,通过网络收集到reduce端。
Spark:Spark的Shuffle是在DAGSchedular划分Stage的时候产生的,TaskSchedule要分发Stage到各个Worker的Executor。
减少shuffle可以提高性能。
RDD分布式弹性数据集,简单的理解成一种数据结构,是Spark框架上的通用货币。
所有算子都是基于RDD来执行的,不同的场景会有不同的rdd实现类,但是都可以进行互相转换。
RDD执行过程中会形成DAG图,然后形成Lineage保证容错性等。
从物理的角度来看RDD存储的是block和node之间的映射。
Spark是用Scala语言编写的。Spark在Scala,Python和Java中提供了一个API,以便与Spark进行交互。它还提供R语言的API。
因为程序在运行之前,已经申请过资源了,Driver和Executors通讯,不需要和Master进行通讯的。
前提是定位数据倾斜,是OOM了,还是任务执行缓慢,看日志,看WebUI
解决方法,有多个方面
序列化可以减少数据的体积,减少存储空间,高效存储和传输数据,不好的是使用的时候要反序列化,非常消耗CPU。
不一定,除了一对一的窄依赖,还包含一对固定个数的窄依赖(就是对父RDD的依赖的Partition的数量不会随着RDD数量规模的改变而改变),比如join操作的每个partition仅仅和已知的partition进行join,这个join操作是窄依赖,依赖固定数量的父RDD,因为是确定的partition关系。
Spark的容错机制分为两种;
第一种方式,Lineage内部如果有分片数据丢失,可以通过上下的依赖关系,启动重算机制,进行容错。
第二种方式,Spark可以通过CheckPoint机制,设置一个第三方存储路径(一般是HDFS),当有数据丢失的时候,从对应的路径恢复数据,但是一旦启动了CheckPoint意味着之前的Lineage被终止。
序列化对于提高分布式程序的性能起到非常重要的作用。一个不好的序列化方式(如序列化模式的速度非常慢或者序列化结果非常大)会极大降低计算速度。很多情况下,这是你优化Spark应用的第一选择。Spark试图在方便和性能之间获取一个平衡。Spark提供了两个序列化类库:
Java 序列化:在默认情况下,Spark采用Java的ObjectOutputStream序列化一个对象。该方式适用于所有实现了java.io.Serializable的类。通过继承 java.io.Externalizable,你能进一步控制序列化的性能。Java序列化非常灵活,但是速度较慢,在某些情况下序列化的结果也比较大。
Kryo序列化:Spark也能使用Kryo(版本2)序列化对象。Kryo不但速度极快,而且产生的结果更为紧凑(通常能提高10倍)。Kryo的缺点是不支持所有类型,为了更好的性能,你需要提前注册程序中所使用的类(class)。
RDD和它依赖的parent RDD(s)的关系有两种不同的类型,即窄依赖(narrow dependency)和宽依赖(wide dependency)。
每个数据分片都对应具体物理位置,数据的位置是被BlockManager,无论数据是在磁盘,内存还是tacyan,都是由BlockManager管理
事实上,SparkStreaming绝对谈不上比Storm优秀。这两个框架在实时计算领域中,都很优秀,只是擅长的细分场景并不相同。
SparkStreaming仅仅在吞吐量上比Storm要优秀,而吞吐量这一点,也是历来挺SparkStreaming,贬Storm的人着重强调的。但是问题是,是不是在所有的实时计算场景下,都那么注重吞吐量?不尽然。因此,通过吞吐量说SparkStreaming强于Storm,不靠谱。
事实上,Storm在实时延迟度上,比SparkStreaming就好多了,前者是纯实时,后者是准实时。而且,Storm的事务机制、健壮性/容错性、动态调整并行度等特性,都要比SparkStreaming更加优秀。
SparkStreaming,有一点是Storm绝对比不上的,就是:它位于Spark生态技术栈中,因此SparkStreaming可以和SparkCore、SparkSQL无缝整合,也就意味着,我们可以对实时处理出来的中间数据,立即在程序中无缝进行延迟批处理、交互式查询等操作。这个特点大大增强了SparkStreaming的优势和功能。