Spark Core

1. 简介

1.1 定义

  • 专为大规模数据处理而设计的快速通用计算引擎
  • 与Hadoop的 MapReduce功能类似

MapReduce V.S. Spark

spark快

Spark框架组件丰富

  • spark特点
    • 1、速度快(比mapreduce在内存中快100倍,在磁盘中快10倍)
    • 2、易用性(可以通过java/scala/python/R开发spark应用程序)
    • 3、通用性(可以使用spark sql/spark streaming/mlib/Graphx)
    • 4、兼容性(spark程序可以运行在standalone/yarn/mesos)

启动pyspark

words = sc.textFile('file:///root/README.txt').flatMap(lambda line: line.split(' ')).map(lambda x: (x, 1)).reduceByKey(lambda a, b : a+b).collect()

2 RDD

RDD(Resilient Distributed Dataset)弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变、可分区、里面的元素可并行计算的集合.

  • Dataset:一个数据集,简单的理解为集合,用于存放数据
  • Distributed:它的数据是分布式存储,并且可以做分布式的计算
  • Resilient:弹性的
    • 数据可以保存在磁盘,也可以保存在内存中

3 RDD的创建

sparkContext

  • conf = SparkConf().setAppName(appName).setMaster(master)
    sc = SparkContext(conf=conf)
    
    
    sc = SparkContext(appName='xxx', master='xxx.xxx.xxx.xxx')
    
    
  • 进入pyspark环境会自动创建sc对象

192.168.19.137:4040

distData = sc.parallelize(data,5) 
通过sc parallelize方法把已经在内存的数据加载生成rdd

生成rdd时可以指定分区数量,一般是cpu核的2-4倍
太多就会导致更多的资源花在任务调度上

sc.textFile('file:///root/tmp/word.txt')
把文件加载生成rdd


1 RDD常用算子练习

1 RDD的三类算子介绍

RDD的三类算子包括 transformation action 和 persist, 前两种进行数据处理, persist处理数据存储相关操作

RDD 支持两种类型的操作:

  • transformation
    • 从一个已经存在的数据集创建一个新的数据集
  • action
    • 获取对数据进行运算操作之后的结果

特性

  • 所有的transformation操作都是惰性的(lazy)
  • 不会立即计算结果
  • 只记下应用于数据集的transformation操作
  • 只有调用action一类的操作之后才会计算所有transformation
  • 这种设计使Spark运行效率更高
  • 例如map reduce 操作,map创建的数据集将用于reduce,map阶段的结果不会返回,仅会返回reduce结果。

所有transformation操作生成的结果,打印出来只能得到一个值的属性,就是一个rdd

action操作会把数据集的内容打印出来

如果一串操作,最终把数据集内容打印出来,最后一个是action,前面的都是transformation

persist 操作 对rdd进行缓存

2 RDD Transformation算子

map(function)

  • 将function函数作用到数据集的每一个元素上,生成一个新的RDD返回
  • function可以是lambda表达式,也可以是一个函数

filter(function)

  • 选出所有function返回值为true的元素,生成一个新的RDD返回

flatMap(function)

  • flatMap会先执行map的操作,再将所有对象合并为一个对象

union

  • 对两个RDD求并集

intersection

  • 对两个RDD求交集

groupByKey

  • 以元组中的第0个元素作为key,进行分组,返回一个新的RDD

  • groupByKey之后的结果中 value是一个Iterable

  • list(result[2][1])
    

reduceByKey(function)

  • 第0个元素作为key,将key相同的键值对,按照function进行计算

  • rdd.reduceByKey(lambda x,y:x+y).collect()
    x,y 不是指的每个value
    而是,x上一轮的结果,y是当前的value
    是迭代计算的过程
    

sortByKey

  • sc.parallelize(tmp2).sortByKey(True, 3, keyfunc=lambda k: k.lower()).collect()
    
  • keyfunc这里处理的结果只会影响排序,并不会改变原始的key

3 RDD Action算子

collect

  • 返回一个list,list中包含 RDD中的所有元素

reduce(function)

  • reduceRDD中元素两两传递给输入function,同时产生一个新的值,新产生的值与RDD中下一个元素再被传递给输入函数直到最后只有一个值为止。

first

  • 返回RDD的第一个元素

take(n)

  • 返回RDD的前N个元素

count

  • 返回RDD中元素的个数

2 spark-core 案例_点击日志分析

1 配置

1 配置pycharm远程连接虚拟机,通过ssh上传代码到虚拟机,在命令行执行代码

2 运行后提示 JAVA_HOME is not set,没有设置JAVA_HOME(Java运行环境)

PYSPARK_PYTHON and PYSPARK_DRIVER_PYTHON are correctly set. 需要指定当前使用的Python解释器位置

2 通过spark实现点击日志分析

  • PV page view 页面访问量 访问一次记一次pv
  • UV Unique Visitor 独立访客访问数,一台设备算一次UV
  • topN 访问量最大的前N个页面

pv:网站的总访问量,把日志中每一行都转成(‘PV’, 1),统计出’PV’的个数

sc = SparkContext('local[2]','PV')
rdd1 = sc.textFile('file:///root/sz39-spark/spark-data/access.log')
rdd2 = rdd1.map(lambda line: ('PV', 1))
rdd3 = rdd2.reduceByKey(lambda a, b: a+b)
result = rdd3.collect()
print(result)

uv: 网站的独立用户访问量,把日志中的ip解析出来,然后去重,每个ip都转成(‘UV’, 1)统计’UV’个数

from pyspark import SparkContext

sc = SparkContext('local[2]','UV')
rdd1 = sc.textFile('file:///root/sz39-spark/spark-data/access.log')
rdd2 = rdd1.map(lambda line: line.split(' ')[0])
rdd3 = rdd2.distinct().map(lambda ip: ('UV', 1))
rdd4 = rdd3.reduceByKey(lambda a,b:a+b)
rdd4.saveAsTextFile("hdfs:///uv2/result") # action操作
result = rdd4.collect()
print(result)

topn:访问次数最多的链接的topN,把日志中的链接解析出来,把每个链接和1一起生成tuple,把链接作为key统计个数,接着排序

from pyspark import SparkContext

sc = SparkContext('local[2]','UV')
rdd1 = sc.textFile('file:///root/sz39-spark/spark-data/access.log')
rdd2 = rdd1.map(lambda line: line.split(' ')).filter(lambda x : len(x)>10).map(lambda x: (x[10], 1))
rdd3 = rdd2.reduceByKey(lambda a, b: a+b).sortBy(lambda x: x[1], ascending=False)
#result = rdd3.take(5)
print(rdd3.take(5))
print(rdd3.collect())

3 Spark-core案例 IP统计

1 需求

把后台访问日志中的ip转化成经纬度,统计相同经纬度的个数,然后在地图上以热力图的形式展示

已有数据

访问日志,中访问的ip地址

ip.txt,存的是ip范围和经纬度的对应关系

从日志中提取出ip地址,把ip地址转成数,把这个数放到ip.txt中用二分查找法找到对应的经纬度,统计出经纬度的个数

ip_to_num计算过程

# 1.0.1.0
# [1, 0, 1, 0]
# ip_num = 0
i = 1
ip_num = 0
000000000
int(1) | ip_num << 8
000000001

ip_num = 000000001
i = 0
int(0) | ip_num << 8
00000000100000000
ip_num = 00000000100000000

i = 1
int(1) | ip_num << 8
0000000010000000000000000
ip_num = 0000000010000000000000001

i = 0
int(0) | ip_num << 8
000000001000000000000000100000000
ip_num = 000000001000000000000000100000000


def ip_to_num(ip):
    ips = ip.split('.')
    ip_num = 0
    for i in ips:
        ip_num = int(i) | ip_num << 8
        
    return ip_num

整体流程

1、 加载城市ip段信息,获取ip起始数字和结束数字,经度,纬度

2、 加载日志数据,获取ip信息,然后转换为数字,和ip段比较

3、 比较的时候采用二分法查找,找到对应的经度和纬度

4,对相同的经度和纬度做累计求和

二分查找法

def binary_search(ip_num, broadcast_value):
    start = 0
    end = len(broadcast_value)-1
    while(start <= end):
        mid = int((start+end)/2)
        if ip_num >= int(broadcast_value[mid][0]) and ip_num <= int(broadcast_value[mid][1]):
            return mid
        if ip_num < int(broadcast_value[mid][0]):
            end = mid
            
        if ip_num > int(broadcast_value[mid][1]):
            start = mid

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值