Sqoop实践

Crontab定时Sqoop脚本问题

Sqoop实践_第1张图片

问题描述:如果上图我们的任务定时2小时一次,正常情况下任务在2小时可以执行完成,但是出现未知异常任务执行超过了2小时,所以第二个任务没有在第一个任务执行完后执行,这样可能导致执行错误。

解决方法

使用flock命令给脚本加锁
  • 命令格式:

      flock [-sxon] [-w timeout] lockfile [-c] command...
      flock [-sxun] [-w timeout] fd
    
  • 常用选项:
    -s, --shared :获得一个共享的锁。
    -x, --exclusive :获得一个独占的锁。
    -u, --unlock :移除一个锁,通常是不需要的,脚本执行完后会自动丢弃锁。
    -n, --nonblock :如果没有立即获得锁直接失败而不是等待。
    -w, --timeout :如果没有立即获得锁就等待指定的时间。
    -o, --close :在运行命令前关闭文件的描述符。用于如果命令产生子进程时会不受锁的管控。
    -c, --command :在shell中运行一个单独的命令。
    -h, --help :显示帮助。
    -V, --version :显示版本。

  • 测试

    //编写test.sh 脚本
    vim test.sh 
    echo "测试~~~~~~~~~~~~:"" `date '+%Y-%m-%d %H:%M:%S'`" >> test.log
    sleep 70
    
    //赋予可执行权限
    chmod 777 test.sh 
    
    //定时设置(1分钟执行一次)
    crontab -e
    */1 * * * * /usr/bin/flock -xn /home/hadoop/test.lock -c '/home/hadoop/test.sh'
    
    //观察日志
    //加锁的日志,10:30:01这个执行点没有执行
    测试~~~~~~~~~~~~: 2017-07-06 10:29:01
    测试~~~~~~~~~~~~: 2017-07-06 10:31:01
    
    //没有加锁的日志(每分钟一次)
    测试~~~~~~~~~~~~: 2017-07-06 10:33:01
    测试~~~~~~~~~~~~: 2017-07-06 10:34:01
    
    

Crontab定时执行脚本和手动执行脚本结果不一致

问题描述:因为CDH5.7.6的Sqoop1.4.6的bug导致使用--incremental lastmodified增量导入数据保存,所以安装了官网的Sqoop1.4.6,因为CDH中已经安装了Sqoop,所以我使用软连接来处理sqoop命令的冲突,官网的sqoop用sqoop1来替代,但是发现Crontab定时执行脚本和手动执行脚本结果不一致,表现在无法创建Sqoop job

解决方法

在脚本头添加 source /etc/profile(配置完环境变量后我也执行过source /etc/profile,但是不知为啥还要在脚本中执行一次)


//创建软连接,配置环境变量
Sqoop的安装位置:/opt/sqoop
//创建软连接
ln -s /opt/sqoop/bin/sqoop /opt/sqoop/bin/sqoop1
//配置环境变量
export PATH=$PATH:/opt/sqoop/bin/sqoop1
//使环境变量生效
source /etc/profile

Sqoop每次执行需要输入数据库密码

解决方法

修改sqoop安装目录conf下的sqoop-site.xml文件,添加下面配置项(其实配置项存在,只要去掉注释就行)

  
    sqoop.metastore.client.record.password
    true
    If true, allow saved passwords in the metastore.
    
  

Sqoop Job如何中如何避免明文输入密码

  • 首先我们使用hadoop credential create [alias_name] -provider [hdfs_location]命令(该命令在hadoop 2.6.0之后才有)在keystore中创建密码以及密码别名

    hadoop credential create mysql.pwd.alias -provider jceks://hdfs/user/password/mysql.pwd.jceks
    
  • 在Enter alias password后面输入我们数据库的密码。执行完后,程序在hdfs的/user/password/下创建了一个mysql.pwd.jceks文件,而且mysql.pwd.alias就是我们的密码别名。我们可以使用mysql.pwd.alias来代替我们真实的数据库密码。在执行sqoop命令时,我们可以使用--password-alias参数,参数的值就是我们刚才自己指定的密码别名

    sqoop list-databases -Dhadoop.security.credential.provider.path=jceks://hdfs/user/password/mysql.pwd.jceks --connect jdbc:mysql://hadoop01 --username root --password-alias mysql.pwd.alias
    

sqoop提供数据库密码的4种方式

MySQL到Hive数据类转换

Hive表结构中的数据类型与MySQL对应列有如下关系

MySQL(bigint) --> Hive(bigint) 
MySQL(tinyint) --> Hive(tinyint) 
MySQL(int) --> Hive(int) 
MySQL(double) --> Hive(double) 
MySQL(bit) --> Hive(boolean) 
MySQL(varchar) --> Hive(string) 
MySQL(decimal) --> Hive(double) 
MySQL(date/timestamp) --> Hive(string)

可以看出MySQL的decimal类型变成了Hive中的double类型。此时需要在导入时通过--map-column-hive 作出映射关系指定,如下所示:

sqoop import --connect jdbc:mysql://hadoop01/test --username root --password 123 --query "SELECT * FROM xi WHERE date>='2015-09-16' AND date<='2015-10-01' AND $CONDITIONS" --split-by date --hive-import -m 5 --map-column-hive cost="DECIMAL",date="DATE" --delete-target-dir -m 1 --hive-table student

Sqoop增量导入数据数据重复问题

问题描述:线上使用Sqoop增量抽取MySQL数据到Hive,但是发现40W条完全一样的数据,通过时间排查那个时间端集群很不稳地,最终查找资料得到原因。

原因

Map Task 执行失败, 那么该 Map 任务会转移到另外一个节点执行重新运行,这时候之前导入的数据又要重新导入一份,造成数据重复导入。 因为 Map Task 没有回滚策略,一旦运行失败,已经导入数据库中的数据就无法恢复。

你可能感兴趣的:(Sqoop实践)