flume&sqoop

一. 背景

Hadoop提供了一个中央化的存储系统
有利于进行集中式的数据分析与数据共享
Hadoop对存储格式没有要求:

  • 用户访问日志
  • 产品信息
  • 网页数据等

如何将数据存入Hadoop

  • 数据分散在各个离散的设备上
  • 数据保存在传统的存储设备和系统

常见的两种数据来源
分散的数据源

  • 机器产生的数据
  • 用户访问日志
  • 用户购买日志

传统系统中的数据:

  • 传统关系型数据库:MySQL、Oracle等;
  • 磁盘阵列;
  • 磁带

Hadoop收集和入库基本要求
分布式

  • 数据源多样化
  • 数据源分散

可靠性

  • 保证不丢数据
  • 允许丢部分数据

可扩展

  • 数据源可能会不断增加

通过并行提高性

常见的Hadoop收集与入库系统
数据收集

  • Flume
  • Kafka
  • Scribe

传统数据库与Hadoop同步

  • Sqoop

二. Hadoop数据收集系统—Flume

Flume OG

  • OG:“Original Generation”
  • 0.9.x或cdh3以及更早版本
  • 由agent、collector、master等组件构成

Flume NG

  • NG:“Next/New Generation”
  • 1.x或cdh4以及之后的版本
  • 由Agent、Client等组件构成

为什么要推出NG版本

  • 精简代码
  • 架构简化

agent产生数据,由collector汇总
master监控前两者的状态

Agent
用于采集数据
数据流产生的地方
通常由source和sink两部分组成

  • Source用于获取数据,可从文本文件,syslog,HTTP等获 取数据;
  • Sink将Source获得的数据进一步传输给后面的Collector。

Flume自带了很多source和sink实现

  • syslogTcp(5140) | agentSink("localhost",35853)
  • tail("/etc/services") | agentSink("localhost",35853)

**Collector **
汇总多个Agent结果
将汇总结果导入后端存储系统,比如HDFS,HBase
Flume自带了很多collector实现

  • collectorSource(35853) | console
  • collectorSource(35853) | collectorSink("file:///tmp/flume/collected", "syslog");
  • collectorSource(35853) | collectorSink("hdfs://namenode/user/flume/ ","syslog");

Agent和Collector对应关系

可手动指定,也可自动匹配
自动匹配的情况下,master会平衡collector之间的负载

可以配置定时写一次,或者汇集多少数据写一次。

为什么引入collector?

  • 对Agent数据进行汇总,避免产生过多小文件;
  • 避免多个agent连接对Hadoop造成过大压力 ;
  • 中间件,屏蔽agent和hadoop间的异构性

**Master **
管理协调agent和collector的配置信息;
Flume集群的控制器;
跟踪数据流的最后确认信息,并通知agent;
通常需配置多个master以防止单点故障;
借助zookeeper管理管理多Master

容错机制

每个agent配置多个collect,首先导入主的collect上,如果挂了拷贝到备的collect上
如果hdfs挂了,collect保存本地
如果collect都挂了,agent保存本地

三种可靠性级别

  1. agentE2ESink[("machine"[,port])]
    agent收到确认消息才认为数据发送成功,否则重试.
  2. agentDFOSink[("machine"[,port])]
    当agent发现在collector操作失败的时候,agent写入到本地硬盘上,当 collctor恢复后,再重新发送数据。
  3. agentBESink[("machine"[,port])]
    效率最好,agent不写入到本地任何数据,如果在collector 发现处理失败, 直接删除消息

**构建基于Flume的数据收集系统 **
Agent和Collector均可以动态配置
可通过命令行或Web界面配置
命令行配置

  • 在已经启动的master节点上,依次输入"flume shell"->"connect localhost"
    如执行 exec config a1 'tailDir("/data/logfile")' 'agentSink'

Web界面

  • 选中节点,填写source、sink等信息

例子-拓扑1

agentA : tail(“/ngnix/logs”) | agentSink("collector",35853); 
agentB : tail(“/ngnix/logs”) | agentSink("collector",35853); 
agentC : tail(“/ngnix/logs”) | agentSink("collector",35853); 
agentD : tail(“/ngnix/logs”) | agentSink("collector",35853); 
agentE : tail(“/ngnix/logs”) | agentSink("collector",35853); 
agentF : tail(“/ngnix/logs”) | agentSink("collector",35853); 
collector : collectorSource(35853) | collectorSink("hdfs://namenode/flume/","srcdata"); 

srcdata是文件的前缀

**例子—拓扑2 **

agentA : src | agentE2ESink("collectorA",35853); 
agentB : src | agentE2ESink("collectorA",35853); 
agentC : src | agentE2ESink("collectorB",35853); 
agentD : src | agentE2ESink("collectorB",35853); 
agentE : src | agentE2ESink("collectorC",35853); 
agentF : src | agentE2ESink("collectorC",35853); 
collectorA : collectorSource(35853) | collectorSink("hdfs://...","src"); 
collectorB : collectorSource(35853) | collectorSink("hdfs://...","src"); 
collectorC : collectorSource(35853) | collectorSink("hdfs://...","src"); 

例子—拓扑3

agentA : src | agentE2EChain("collectorA:35853","collectorB:35853"); 
agentB : src | agentE2EChain("collectorA:35853","collectorC:35853"); 
agentC : src | agentE2EChain("collectorB:35853","collectorA:35853"); 
agentD : src | agentE2EChain("collectorB:35853","collectorC:35853"); 
agentE : src | agentE2EChain("collectorC:35853","collectorA:35853"); 
agentF : src | agentE2EChain("collectorC:35853","collectorB:35853"); 
collectorA : collectorSource(35853) | collectorSink("hdfs://...","src"); 
collectorB : collectorSource(35853) | collectorSink("hdfs://...","src"); 
collectorC : collectorSource(35853) | collectorSink("hdfs://...","src"); 

三. 传统数据库与Hadoop间数据同步

Sqoop是什么
Sqoop:SQL-to-Hadoop
连接 传统关系型数据库 和 Hadoop 的桥梁

  • 把关系型数据库的数据导入到 Hadoop 系统 (如 HDFS HBase 和 Hive) 中;
  • 把数据从 Hadoop 系统里抽取并导出到关系型数据库里。
    利用MapReduce加快数据传输速度
    批处理方式进行数据传输

Sqoop优势
高效、可控地利用资源

  • 任务并行度,超时时间等

数据类型映射与转换

  • 可自动进行,用户也可自定义

支持多种数据库

  • MySQL
  • Oracle
  • PostgreSQL

Sqoop1

Sqoop2

将数据从关系型数据库导入Hadoop中
步骤1:Sqoop与数据库Server通信获取数据库表的元数据 信息;
步骤2:Sqoop启动一个MapOnly的MR作业,利用元数据信 息并行将数据写入Hadoop

sqoop import \     
    --connect jdbc:mysql://mysql.example.com/sqoop \     
    --username sqoop \     
    --password sqoop \     
    --table cities 

--connnect: 指定JDBC URL
--username/password:mysql数据库的用户名
--table:要读取的数据库表
查看

bin/hadoop fs -cat cities/part-m-* 

默认导入同名的目录下,如果想指定目录

sqoop import \      
    --connect jdbc:mysql://mysql.example.com/sqoop \      
    --username sqoop \    
    --password sqoop \     
    --table cities \     
    --target-dir /etl/input/cities 

导入符合某种要求的数据

sqoop import \     
    --connect jdbc:mysql://mysql.example.com/sqoop \     
    --username sqoop \     
    --password sqoop \     
    --table cities \     
    --where "country = 'USA'" 

默认是文本格式,如果想导成其他格式

sqoop import \     
    --connect jdbc:mysql://mysql.example.com/sqoop \    
    --username sqoop \     
    --password sqoop \     
    --table cities \     
    --as-sequencefile

限制并发map的数量,防止把这个数据库拖垮

sqoop import \     
    --connect jdbc:mysql://mysql.example.com/sqoop \    
    --username sqoop \     
    --password sqoop \     
    --table cities \     
    --num-mappers 10 

导入多个表,对表做join连接,然后导入

sqoop import \   
    --connect jdbc:mysql://mysql.example.com/sqoop \   
    --username sqoop \   
    --password sqoop \   
    --query 'SELECT normcities.id, \                  
            countries.country, \                  
            normcities.city \                  
            FROM normcities \                  
            JOIN countries USING(country_id) \                  
            WHERE $CONDITIONS' \ 
    --split-by id \ 
    --target-dir cities

增量导入
append模式,只增加,需要指定上一次最新id的值,然后这次id递增导入

sqoop import \     
    --connect jdbc:mysql://mysql.example.com/sqoop \     
    --username sqoop \     
    --password sqoop \     
    --table visits \     
    --incremental append \     
    --check-column id \     
    --last-value 1 

适用于数据每次被追加到数据库中,而已有数据不变的情况;
仅导入id这一列值大于1的记录。
自动运行作业

sqoop job \   
    --create visits \   
    --import \   
    --connect jdbc:mysql://mysql.example.com/sqoop \   
    --username sqoop \   
    --password sqoop \   
    --table visits \   
    --incremental append \   
    --check-column id \   
    --last-value 0 运行sqoop作业:sqoop job 
    --exec visits 

运行sqoop作业:sqoop job --exec visits
每次成功运行后,sqoop将最后一条记录的id值保存到 metastore中,供下次使用,不用人工记忆id值了

update模式

sqoop import \   
    --connect jdbc:mysql://mysql.example.com/sqoop \   
    --username sqoop \   
    --password sqoop \   
    --table visits \   
    --incremental lastmodified \   
    --check-column last_update_date \   
    --last-value “2013-05-22 01:01:01” 

数据库中有一列last_update_date,记录了上次修改时间;
Sqoop仅将某时刻后的数据导入Hadoop

Sqoop Export
将数据从Hadoop导入关系型数据库导中
步骤1:Sqoop与数据库Server通信,获取数据库表的元数据 信息;
步骤2:并行导入数据:

  • 将Hadoop上文件划分成若干个split;
  • 每个split由一个Map Task进行数据导入

使用方法:

sqoop export \     
--connect jdbc:mysql://mysql.example.com/sqoop \     
--username sqoop \     
--password sqoop \     
--table cities \    
--export-dir cities 

--connnect: 指定JDBC URL
--username/password:mysql数据库的用户名
--table:要导入的数据库表
export-dir:数据在HDFS上存放目录

保证原子性

sqoop export \     
    --connect jdbc:mysql://mysql.example.com/sqoop \     
    --username sqoop \     
    --password sqoop \     
    --table cities \     
    --staging-table staging_cities

更新已有数据
不覆盖

sqoop export \     
    --connect jdbc:mysql://mysql.example.com/sqoop \     
    --username sqoop \     
    --password sqoop \     
    --table cities \     
    --update-key id 

已有数据覆盖

sqoop export \     
    --connect jdbc:mysql://mysql.example.com/sqoop \     
    --username sqoop \     
    --password sqoop \     
    --table cities \     
    --update-key id \     
    --update-mode allowinsert 

选择性导入

sqoop export \     
    --connect jdbc:mysql://mysql.example.com/sqoop \     
    --username sqoop \     
    --password sqoop \     
    --table cities \     
    --columns country,city

Sqoop与其他系统结合
Sqoop可以与Oozie、Hive、Hbase等系统结合;
用户需要在sqoop-env.sh中增加HBASE_HOME、 HIVE_HOME等环境变量

Sqoop与Hive结合

sqoop import \     
    --connect jdbc:mysql://mysql.example.com/sqoop \     
    --username sqoop \     
    --password sqoop \     
    --table cities \     
    --hive-import  

**Sqoop与HBase结合 **

sqoop import \     
    --connect jdbc:mysql://mysql.example.com/sqoop \     
    --username sqoop \     
    --password sqoop \     
    --table cities \     
    --hbase-table cities \     
    --column-family world 

参考:Apache Sqoop Cookboo

posted @ 2016-09-13 20:17  zhangshihai1232  阅读(208)  评论(0)    收藏  举报