Crontab定时Sqoop脚本问题
问题描述:如果上图我们的任务定时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文件,添加下面配置项(其实配置项存在,只要去掉注释就行)
<property>
<name>sqoop.metastore.client.record.password</name>
<value>true</value>
<description>If true, allow saved passwords in the metastore.
</description>
</property>
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
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 没有回滚策略,一旦运行失败,已经导入数据库中的数据就无法恢复。