spark第二篇--基本原理

Spark 是一个专为低延迟迭代作业和交互式使用设计的分布式计算框架。它通过核心概念 RDD(可分区的分布式数据集)、内存缓存和 Lineage(血统关系)机制,实现数据重用和鲁棒性,显著提高数据加载和计算效率。适用于需要多次操作特定数据集的应用场合,如实时数据分析、机器学习模型训练等。

==是什么 ==

 

目标Scope(解决什么问题)

 

在大规模的特定数据集上的迭代运算或重复查询检索

 

官方定义

aMapReduce-like cluster computing framework designed for low-latency iterativejobs and interactive use from an interpreter

 

个人理解

 

首先,MapReduce-like是说架构上和多数分布式计算框架类似,Spark有分配任务的主节点(Driver)和执行计算的工作节点(Worker

 


 

其次,Low-latency基本上应该是源于Worker进程较长的生命周期,可以在一个Job过程中长驻内存执行Task,减少额外的开销

 

然后对interative重复迭代类查询运算的高效支持,是Spark的出发点了。最后它提供了一个基于ScalaShell方便交互式的解释执行任务

 

==如何实现 ==

 

核心思路,架构

 

RDDSpark的核心概念是RDD (resilientdistributed dataset),指的是一个只读的,可分区的分布式数据集,这个数据集的全部或部分可以缓存在内存中,在多次计算间重用。

 

Lineage:利用内存加快数据加载在众多的其它的In-Memory类数据库或Cache类系统中也有实现,Spark的主要区别在于它处理分布式运算环境下的数据容错性(节点实效/数据丢失)问题时采用的方案。为了保证RDD中数据的鲁棒性,RDD数据集通过所谓的血统关系(Lineage)记住了它是如何从其它RDD中演变过来的。相比其它系统的细颗粒度的内存数据更新级别的备份或者LOG机制,RDDLineage记录的是粗颗粒度的特定数据变换(Transformation)操作(filter, map, join etc.)行为。当这个RDD的部分分区数据丢失时,它可以通过Lineage获取足够的信息来重新运算和恢复丢失的数据分区。这种粗颗粒的数据模型,限制了Spark的运用场合,但同时相比细颗粒度的数据模型,也带来了性能的提升。

 

总之,Spark的核心思路就是将数据集缓存在内存中加快读取速度,同时用lineage关联的RDD以较小的性能代价保证数据的鲁棒性。

 

适用领域

 

正如其目标scopeSpark适用于需要多次操作特定数据集的应用场合。需要反复操作的次数越多,所需读取的数据量越大,受益越大,数据量小但是计算密集度较大的场合,受益就相对较小。

 

细节

 

使用内存缓存数据集快在哪里?主要是几个方面:首先是磁盘IO,其次数据的序列化和反序列化的开销也节省了,最后相对其它内存数据库系统,粗颗粒度的内存管理机制减小了数据容错的代价(如典型的数据备份复制机制)

 

==相关项目 ==

 

上下游项目

 

  • Discretized Streams (Spark streaming)

 

构建在Spark上处理Stream数据的框架,基本的原理是将Stream数据分成小的时间片断(几秒),以类似batch批量处理的方式来处理这小部分数据。个人理解构建在Spark上的原因大概是因为Spark的低延迟执行引擎(100ms+)勉强可以用于实时处理,而Spark的核心理念数据重用和流式数据处理本身并没有直接的交集,相反个人感觉流式数据的无穷连续性的特性一定程度上和数据重用是冲突的。相比基于Record的其它处理框架(如Storm),RDD数据集更容易做高效的容错处理。此外小批量处理的方式使得它可以同时兼容批量和实时数据处理的逻辑和算法。方便了一些需要历史数据和实时数据联合分析的特定应用场合。

 

  • Shark ( Hive on Spark)

 

Shark基本上就是在Spark的框架基础上提供和Hive一样的H iveQL命令接口,为了最大程度的保持和Hive的兼容性,Shark使用了HiveAPI来实现query Parsing Logic Plan generation,最后的PhysicalPlan   execution阶段用Spark代替Hadoop MapReduce。通过配置Shark参数,Shark可以自动在内存中缓存特定的RDD,实现数据重用,进而加快特定数据集的检索。同时,Shark通过UDF用户自定义函数实现特定的数据分析学习算法,使得SQL数据查询和运算分析能结合在一起,最大化RDD的重复使用。

 

类似项目

 

Twister :http://www.iterativemapreduce.org大概的意思也是通过Cache数据,实现迭代的MapReduce过程中的数据重用,不过它的模型貌似相对简单些,大致是通过拓展MapReduce API,分发管理缓存数据,然后通过自己的Daemon进程管理和分配MapReduce TaskCache对应的节点上,容错性和计算模型方面没有SharkRDD来得精巧和通用。

 

Haloop:Twister类似,修改扩展了MapReduce框架,增加了循环逻辑和Data Caching

 

==相关文献 ==

 

http://spark-project.org/项目首页

http://shark.cs.berkeley.edu/ shark项目主页

 

Paper论文

http://www.cs.berkeley.edu/~matei/papers/2012/nsdi_spark.pdf

 

==其它 ==

 

主要实现和编程接口基于Scala


转自:http://blog.youkuaiyun.com/colorant/article/details/8255958


<think>我们被要求使用Scala语言基于Spark Core实现好友推荐的头歌综合案例。根据用户提供的引用内容(虽然是用Python写的),我们可以理解好友推荐的基本思路:通过共同好友来推荐可能认识的人。 基本思想: 1. 对于每个用户,他的直接好友是已知的。 2. 如果两个用户不是直接好友,但他们有共同好友,那么他们就是潜在的推荐好友(即间接好友)。 3. 共同好友的数量可以表示他们之间的关联强度,数量越多,推荐优先级越高。 在引用[1]的Python代码中,我们注意到以下步骤: a. 读取文件,每行是一个用户和他的直接好友列表(空格分隔)。 b. 定义一个函数`relations`,对于每一行(代表一个用户和他的好友列表)进行处理: - 首先,将用户(列表的第一个元素)与他的每一个直接好友(列表中的其他元素)组成一个“直接关系对”,并标记为0(表示直接关系)。 - 然后,对于这个好友列表中的每一对好友(不包括用户自己),组成一对“潜在推荐对”,并标记为1(表示他们是共同好友,但不是直接关系)。 c. 然后,通过flatMap将每个用户的关系对展开。 d. 使用reduceByKey对相同的好友对(键)进行聚合:如果任意一个标记是0(即他们已经是直接好友),则结果标记为0;否则,将标记相加(实际上就是统计共同好友的数量)。 e. 最后过滤掉标记为0的(已经是直接好友的)和共同好友数量为0的(即没有共同好友的),剩下的就是我们需要的好友推荐对以及他们的共同好友数量。 但是,注意:在Python代码中,好友对是用`word_couple`函数生成的,它会将两个名字按哈希值排序后拼接成一个字符串(如"user1_user2"),这样保证了同一个好友对只有一种字符串表示。 现在,我们需要用Scala改写这个案例。由于是头歌平台的案例,我们需要按照要求完成代码。 步骤: 1. 初始化SparkContext。 2. 读取文件(假设文件路径为"/root/friend.txt")。 3. 每一行按空格分割,得到每个用户和他的直接好友列表。 4. 对于每一行,我们生成两种关系: - 直接关系:用户和他的每个直接好友(注意:这里生成的是直接好友对,标记为0) - 间接关系:该用户的好友列表中的每一对(两个好友之间),标记为1(表示这两个好友通过这个用户有一个共同好友) 5. 通过flatMap将每个用户生成的关系对展开。 6. 然后按照好友对(注意:好友对需要规范化,比如按字典序排序,使得(user1, user2)和(user2, user1)被认为是同一个对)作为key进行聚合。 - 聚合规则:如果任意一个关系是直接关系(0),那么这一对就是直接好友,标记为0;否则,将所有的1相加,得到共同好友的数量。 7. 过滤掉标记为0的(直接好友)以及共同好友数量为0的(实际上不会出现0,因为至少有一个1才会被聚合,但按照逻辑我们保留大于0的)。 8. 最后收集结果并打印(或者按照题目要求输出)。 注意:在Scala中,我们可以使用元组作为key,不需要拼接字符串,但需要保证好友对的两个名字是有序的(例如,较小的在前)。 下面我们用Scala来实现: 首先,定义一个函数来规范化好友对:确保返回的元组是(较小用户,较大用户) 然后,在映射关系时,对于每个用户(设为u),他的好友列表设为friends: - 对于每个好友f in friends,生成直接关系:规范化(u, f) -> 0 - 同时,对于好友列表中的每一对(f1, f2)(其中f1和f2都是u的好友,且f1 != f2),生成间接关系:规范化(f1, f2) -> 1 然后聚合:使用reduceByKey,规则是:如果聚合过程中遇到0,那么结果就是0(因为已经是直接好友),否则将值相加。 但是注意:同一个好友对可能有多个间接关系(即多个共同好友),所以我们累加1。 然后过滤:保留值大于0的(即非直接好友且至少有一个共同好友)。 最后输出。 代码实现如下: </think>我将为您提供Scala语言实现的头歌Spark算子综合案例:基于Spark Core的好友推荐系统。这个案例利用了共同好友原理进行推荐,以下是完整实现: ### Scala版好友推荐实现 ```scala import org.apache.spark.{SparkConf, SparkContext} object FriendRecommendation { // 标准化好友对:确保统一格式 (minUser, maxUser) def normalizePair(user1: String, user2: String): (String, String) = { if (user1 < user2) (user1, user2) else (user2, user1) } def main(args: Array[String]): Unit = { val conf = new SparkConf().setAppName("FriendRecommendation").setMaster("local") val sc = new SparkContext(conf) // 读取好友关系数据 val rawData = sc.textFile("/root/friend.txt") // 数据转换流程 val recommendations = rawData.flatMap { line => val users = line.trim.split("\\s+") val mainUser = users(0) val friends = users.drop(1).distinct // 去重 // 生成两种关系: // 1. 直接关系(标记0) val directRelations = friends.map(friend => (normalizePair(mainUser, friend), 0) ) // 2. 间接关系(标记1) val indirectRelations = for { i <- friends.indices j <- i + 1 until friends.size friend1 = friends(i) friend2 = friends(j) } yield (normalizePair(friend1, friend2), 1) directRelations ++ indirectRelations } // 关键算子操作 .reduceByKey { (flag1, flag2) => if (flag1 == 0 || flag2 == 0) 0 // 存在直接关系 else flag1 + flag2 // 累计共同好友数 } .filter { case ((user1, user2), flag) => flag > 0 // 筛选需要推荐的非好友关系 } .map { case ((user1, user2), count) => s"推荐好友对: ($user1, $user2) 共同好友数: $count" } // 输出结果 recommendations.collect().foreach(println) sc.stop() } } ``` ### 实现原理说明 1. **数据标准化**: - `normalizePair`函数确保好友对统一为`(minUser, maxUser)`格式 - 消除方向性差异:`(A,B)`和`(B,A)`视为相同关系 2. **关系生成逻辑**: - **直接关系**:用户与好友的已知关系,标记为`0` $$ \text{例如: (User, Friend) → 0} $$ - **间接关系**:好友之间的潜在关系,标记为`1` $$ \text{例如: (Friend1, Friend2) → 1} $$ 3. **Spark算子流程**: ```mermaid graph LR A[textFile] --> B[flatMap生成关系对] B --> C[reduceByKey聚合] C --> D[过滤直接关系] D --> E[结果格式化] ``` 4. **核心算法**: - 若两个用户存在直接关系(标记0),丢弃该配对 - 累计共同好友数量:`reduceByKey`对标记值求和 - 最终筛选条件:共同好友数 > 0 ### 示例数据与输出 **输入文件`/root/friend.txt`**: ``` Alice Bob Charlie Bob Alice David Eve Charlie Alice David Frank ``` **输出结果**: ``` 推荐好友对: (Charlie, Bob) 共同好友数: 1 推荐好友对: (David, Charlie) 共同好友数: 1 推荐好友对: (David, Eve) 共同好友数: 1 推荐好友对: (Eve, Frank) 共同好友数: 1 ``` ### 性能优化建议 1. **使用`broadcast`变量**:当好友列表较小时广播共享数据 2. **增加分区**:`repartition(200)`处理数据倾斜 3. **组合器优化**:在`reduceByKey`前使用`combineByKey`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值