20200625大数据spark学习笔记

启动
src/redis-server redis.conf 

src/redis-cli -h hadoop000 -p 6379

 keys * 查询里面的key


 HBase特点

 大:
 面向列:列族(可以存放很多列),列族/列独立索引
 稀疏:对于空的列,不会占用存储空间

 数据类型单一:btye/string
 无模式:每一行的数据所对应的列不一定相同,每行的列是可以动态添加的
 数据多版本:比如company可以存放不同的版本的值
     默认情况下版本号是自动分配的,是列的值插入时的时间戳

 启动hbase
 cd /bin
 ./hbase shell

 create 'member','member_id','address','info'    

 插入数据 put 表明, rowkey, cf :column,value

 put 'member','pk','info:age','28'

 put 'member','pk','info:birthday','1990-05-05'
 
 put 'member','pk','info:company','imooc'


get 'member','pk','info'

put 'member','pk','info:age','18'  //改年纪


 scan 'member'

HBase 的api操作

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.filter.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class HBaseApp {
    Connection connection = null;
    Table table = null;
    Admin admin = null;

    String tableName = "pk_hbase_java_api";


    @Before
    public void setUp() {
        Configuration configuration = new Configuration();
        configuration.set("hbase.rootdir", "hdfs://hadoop000:8020/hbase");
        configuration.set("hbase.zookeeper.quorum", "hadoop000:2181");

        try {
            connection = ConnectionFactory.createConnection(configuration);
            admin = connection.getAdmin();

            Assert.assertNotNull(connection);
            Assert.assertNotNull(admin);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void getConnection() {

    }


    @Test
    public void createTable() throws Exception {
        TableName table = TableName.valueOf(tableName);
        if (admin.tableExists(table)) {
            System.out.println(tableName + " 已经存在...");
        } else {
            HTableDescriptor descriptor = new HTableDescriptor(table);
            descriptor.addFamily(new HColumnDescriptor("info"));
            descriptor.addFamily(new HColumnDescriptor("address"));
            admin.createTable(descriptor);
            System.out.println(tableName + " 创建成功...");
        }
    }


    @Test
    public void queryTableInfos() throws Exception {
        HTableDescriptor[] tables = admin.listTables();
        if (tables.length > 0) {
            for (HTableDescriptor table : tables) {
                System.out.println(table.getNameAsString());

                HColumnDescriptor[] columnDescriptors = table.getColumnFamilies();
                for (HColumnDescriptor hColumnDescriptor : columnDescriptors) {
                    System.out.println("\t" + hColumnDescriptor.getNameAsString());
                }
            }
        }
    }


    @Test
    public void testPut() throws Exception {
        table = connection.getTable(TableName.valueOf(tableName));

//        Put put = new Put(Bytes.toBytes("pk"));
//
//        // 通过PUT设置要添加数据的cf、qualifier、value
//        put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes("28"));
//        put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("birthday"), Bytes.toBytes("xxxx"));
//        put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("company"), Bytes.toBytes("imooc"));
//
//        put.addColumn(Bytes.toBytes("address"), Bytes.toBytes("country"), Bytes.toBytes("CN"));
//        put.addColumn(Bytes.toBytes("address"), Bytes.toBytes("province"), Bytes.toBytes("GUANGDONG"));
//        put.addColumn(Bytes.toBytes("address"), Bytes.toBytes("city"), Bytes.toBytes("shenzhen"));
//
//
//        // 将数据put到HBase中去
//        table.put(put);


        List puts = new ArrayList<>();

        Put put1 = new Put(Bytes.toBytes("jepson"));
        put1.addColumn(Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes("18"));
        put1.addColumn(Bytes.toBytes("info"), Bytes.toBytes("birthday"), Bytes.toBytes("xxxx"));
        put1.addColumn(Bytes.toBytes("info"), Bytes.toBytes("company"), Bytes.toBytes("apple"));
        put1.addColumn(Bytes.toBytes("address"), Bytes.toBytes("country"), Bytes.toBytes("CN"));
        put1.addColumn(Bytes.toBytes("address"), Bytes.toBytes("province"), Bytes.toBytes("SHANGHAI"));
        put1.addColumn(Bytes.toBytes("address"), Bytes.toBytes("city"), Bytes.toBytes("SHANGHAI"));


        Put put2 = new Put(Bytes.toBytes("xingxing"));
        put2.addColumn(Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes("19"));
        put2.addColumn(Bytes.toBytes("info"), Bytes.toBytes("birthday"), Bytes.toBytes("xxxx"));
        put2.addColumn(Bytes.toBytes("info"), Bytes.toBytes("company"), Bytes.toBytes("PDD"));
        put2.addColumn(Bytes.toBytes("address"), Bytes.toBytes("country"), Bytes.toBytes("CN"));
        put2.addColumn(Bytes.toBytes("address"), Bytes.toBytes("province"), Bytes.toBytes("SHANGHAI"));
        put2.addColumn(Bytes.toBytes("address"), Bytes.toBytes("city"), Bytes.toBytes("SHANGHAI"));


        puts.add(put1);
        puts.add(put2);

        table.put(puts);
    }


    @Test
    public void testUpdate() throws Exception {
        table = connection.getTable(TableName.valueOf(tableName));

        Put put = new Put(Bytes.toBytes("xingxing"));
        put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("age"), Bytes.toBytes("20"));


        table.put(put);

    }


    @Test
    public void testGet01() throws Exception {
        table = connection.getTable(TableName.valueOf(tableName));
//        table = connection.getTable(TableName.valueOf("access_20190130"));
//
//        Get get = new Get("20190130_1433814004".getBytes());
//        //get.addColumn(Bytes.toBytes("info"), Bytes.toBytes("age"));
//
//        Result result = table.get(get);
//        printResult(result);

        Get get = new Get("pk".getBytes());
        get.addColumn(Bytes.toBytes("info"), Bytes.toBytes("age"));
        Result result = table.get(get);
        printResult(result);
    }


    @Test
    public void testScan01() throws Exception {
        table = connection.getTable(TableName.valueOf(tableName));

        Scan scan = new Scan();
//        scan.addFamily(Bytes.toBytes("info"));
        scan.addColumn(Bytes.toBytes("info"), Bytes.toBytes("company"));

        //Scan scan = new Scan(Bytes.toBytes("jepson")); // >=
        //Scan scan = new Scan(new Get(Bytes.toBytes("jepson")));
        //Scan scan = new Scan(Bytes.toBytes("jepson"),Bytes.toBytes("xingxing")); // [)
        ResultScanner rs = table.getScanner(scan);

//        ResultScanner rs = table.getScanner(Bytes.toBytes("info"), Bytes.toBytes("company"));
        for(Result result : rs){
            printResult(result);
            System.out.println("~~~~~~~~~~~~~");
        }

    }

    @Test
    public void testFilter() throws Exception {
        table = connection.getTable(TableName.valueOf(tableName));
        Scan scan = new Scan();
//        String reg = "^*ing";
//        Filter filter = new RowFilter(CompareFilter.CompareOp.EQUAL, new RegexStringComparator(reg));
//        scan.setFilter(filter);


//        Filter filter = new PrefixFilter(Bytes.toBytes("p"));
//        scan.setFilter(filter);

        FilterList filters = new FilterList(FilterList.Operator.MUST_PASS_ONE);
        Filter filter1 = new PrefixFilter("p".getBytes());
        Filter filter2 = new PrefixFilter("j".getBytes());

        filters.addFilter(filter1);
        filters.addFilter(filter2);
        scan.setFilter(filters);

        ResultScanner rs = table.getScanner(scan);
        for(Result result : rs){
            printResult(result);
            System.out.println("~~~~~~~~~~~~~");
        }
    }

    private void printResult(Result result) {
        for (Cell cell : result.rawCells()) {
            System.out.println(Bytes.toString(result.getRow()) + "\t "
                    + Bytes.toString(CellUtil.cloneFamily(cell)) + "\t"
                    + Bytes.toString(CellUtil.cloneQualifier(cell)) + "\t"
                    + Bytes.toString(CellUtil.cloneValue(cell)) + "\t"
                    + cell.getTimestamp());
        }
    }


    @After
    public void tearDown() {
        try {
            connection.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

项目背景
    离线+实时  基于Spark(RDD/SQL/Streaming)
    基于慕课网的访问日志进行统计分析
        访问日志:离线  HBase
            点击流日志:
            搜索:关键字
        订单数据日志:实时  Redis

        统计:不同需求/业务+根据不同的维度进行统计
            今天:新增了多少注册会员、订单量多少、订单金额多少?
            今天和昨天对比:增长?减少?百分比
            会员
            订单
            运营商/地市


离线项目的架构/处理流程
    数据采集:落地到HDFS  外部将数据采集到内部
        SDK数据==>日志==>Hadoop
        Server日志:Flume、Logstash
        数据库:Sqoop
        提供给你们采集过来的数据,直接存放在HDFS上即可,后续的所有操作都是基于这份数据进行的
    (*****)数据预处理/数据清洗: 脏/乱数据 ==> 数据规整化(RDD/DF/DS)
        [30/Jan/2019:00:00:21 +0800] ==> 时间解析
        按照指定的分隔符进行拆分
        加字段
            ip==>城市、运营商、经纬度
        减字段
        使用技术:Spark
        HDFS ==> Spark ==> HBase
    (*****)数据入库:把规整化的数据写入到存储(HBase)
        Hive、HBase、Redis......
        使用技术:HBase
        rowkey设计
        cf
        column
    (*****)数据分析
        出报表的核心所在
        统计分析结果可以找个地方存储起来
        使用技术:Spark
        HBase ==> MapReduce/Spark ==> 业务逻辑分析(代码)  ==> DB
        HBase ==> Hive/Spark SQL  ==> SQL ==> DB

    数据展示:将分析所得到的数据进行可视化显示
        使用技术:HUE、Zeppelin、Echarts、自研


离线项目中要统计的指标/需求
    1)区域统计:国家、省份
    2)终端统计:浏览器、版本号
    ==> Spark + HBase综合运用  *****
    两个版本:
        业务逻辑实现
        各种性能的优化
    两种实现
        Spark Core
        Spark SQL


Spark:
    日志按照统计需求清洗到HBase表中
        log ==> df
        DF  ==> put
        Spark把put写入到HBase中

    对HBase表中的数据进行维度指标的统计分析操作
        Spark把HBase中的Result读取出来
            使用RDD进行统计分析
            使用DataFrame API进行统计分析
            使用Spark SQL API进行统计分析

next:对这章的内容进行优化和重构

UserAgent进行处理和统计分析
    如何解析UserAgent的信息呢?
        自己开发:麻烦
        首先想到的是Github,是不是已经有开源的解析处理的工程呢?
        https://github.com/chetan/UASparser
    操作系统信息、浏览器信息


统计各个省份、地市的访问信息
    需要根据IP进行解析
        开源:纯真(有兴趣的,自己去尝试使用纯真进行解析)
        生产:收费 ,会定时更新IP库、直接调用人家公司提供的IP解析API就可以的
    调用Spark的方法,内部已经给你们集成好的

Spark+HBase+Redis综合使用,pom.xml中需要添加一些框架的依赖

基于Spark的流处理框架
项目背景:
    离线处理/批处理:慕课网的访问日志:点击、搜索
    实时处理:订单日志
        谁、什么时候、下单了什么课程、支付、IP(运营商、地市)、UA


流处理系统
    Spark Streaming
    Structured Streaming  *****
    Flink
    Storm
    Kafka Stream


项目架构及处理流程
    log==>Flume==>Kafka==>SparkStreaming(Direct)==>Redis
    实时:代码来生成订单日志==>Kafka==>SparkStreaming(Direct)==>Redis
    离线:HDFS==>Spark==>HBase

公司大数据团队的分工:采集、批处理、实时处理、API、前端


项目需求
1)统计每天付费成功的总订单数、订单总金额
2)统计每个小时付费成功的总订单数、订单金额
==>统计每分钟付费成功的总订单数、订单金额
==>统计基于Window付费成功的总订单数、订单金额
==>付费订单占到总下单的占比:天、小时、分钟

不能拘泥于某个具体的需求,而因为从一类场景中进行拓展/扩展,进而举一反三,才能达到更好的学习效果

Spark Streaming来进行统计分析,分析结果我们需要写入到Redis(数据类型的合适选择)


Spark Streaming&Kafka&Redis整合

离线项目:访问日志
实时项目:付费日志
    下单,但是没付钱
    下单,付钱
    time,userid,courseid,orderid,fee
    json格式提供

SparkStreaming读取Kafka的数据,通过fastjson的方式把我们所需要的字段解析出来
根据我们的业务逻辑实现功能:代码的重构,好好理解下
根据不同的业务选择合适的Redis的数据类型进行存储即可

我们的职责是把数据存储到Redis就行了,对于后续还有展示的功能,我们不考虑这部分的实现

我就不打包了到服务器上运行了,
作业:自己根据离线项目的讲解,把实时项目打包到服务器上运行
如果有疑问的,到时候加入到我们课程的QQ群里,我们一起来交流和讨论

彩蛋:这们课程我们会定时在课程群里,安排直播答疑

"auto.offset.reset" -> "latest"
如果Spark挂了,Kafka还在运行的话,可能会有数据的丢失
Kafka offset管理起来


StreamingContext
从Kafka中获取要处理的数据
根据业务来处理数据
处理结果入库
启动程序,等待程序终止

挂了:kafka的数据到底是从头开始还是从最新数据开始

正确的做法:
    第一次应用程序启动的时候,要从某个地方获取到已经消费过的offset
    业务逻辑处理完之后,应该要把已经处理完的offset给它保存到某个地方去


offset存储的地方
    Checkpoint
    Kafka
    ZK/MySQL/HBase/Redis

作业:把offset管理起来


------------------------------------------------------------------------

有点坑,把kafka版本换到2.11-0.10.0.0
配置下tmp目录跟localhost->hadoop000

cd /bin 启动
./kafka-server-start.sh -daemon ~/app/kafka_2.11-0.10.0.0/config/server.properties 

./kafka-topics.sh --create --zookeeper hadoop000:2181 --replication-factor 1 --partitions 1 --topic pkkafka


./kafka-topics.sh --create --zookeeper hadoop000:2181 --replication-factor 1 --partitions 1 --topic pkkafkatest


//测试
./kafka-console-producer.sh --broker-list hadoop000:9092 --topic pkkafkatest

./kafka-console-consumer.sh --zookeeper hadoop000:2181 --topic pkkafkatest
 

你可能感兴趣的:(大数据之路)