以前的定时任务都是使用 for循环加 sleep ,这种伪装的定时任务 有很大的局限性,为了 更好的使用数据流传输 到 hdfs,我们在不借助工具的前提下 使用 scp expect hadoop 等多个linux非原生的 命令组合的脚本 完成了 数据的传输,当然为了实现自动化传输 ,必须借助 linux的 crontab 定时任务 组件命令 在执行脚本,
脚本的执行有 按天 执行 按小时执行 ,未来也会有按周或者 按月执行的。
在使用crontab 我也遇到了一些问题,当然这些问题 有crontab自身的小bug,和对 crontab应用不熟悉造成的,做一个小的流水账记录一下
1.定时任务 是和 linux的用户绑定的,root 设置的定时任务 只有 root 用户才可以执行设置和切换到root 用户才能查看,其他用户设置的定时任务也只有本用户自己可以执行设置和查看,要使用哪个用户执行 要心中有数 ,使用 crontab -e ,设置定时任务
2.使用定时任务要执行的脚本 需要 修改其权限,使之 有权限执行脚本
chmod 777 *.sh
3.首先 crontab 的配置文件 /etc/crontab 的环境变量 和 root 用户下/etc/profile 、 普通用户 下 ~/.bashrc不共通的,这也是造成 为什么在shell 中直接执行没有问题,但是到crontab 就无法执行 或根本没有执行,或者执行出错,比如 就 scp expect hadoop 这些命令 crontab 的环境变量是没有的,不可能识别,为了 被识别 可以通过两种方式
1.全局修改 全局生效 在 crontab的配置文件 把 环境变量补充到和 /etc/profile 、 普通用户 下 ~/.bashrc 一致的PATH 变量,一般 缺少 /usr/local/bin /usr/local/sbin ,然后把 一些 特殊的 命令 比如 scp 和except 找到他们的执行全路径
which scp
which except
把得到的全路径 以 alias 形式 写入到 /etc/crontab中 即可
比如 scp=/usr/bin/scp
这样就可以执行 scp 命令
- 局部修改 局部起效 ,把要执行的 命令的全路径在 你要执行的脚本中 做一下声明 ,就可以直接使用 ,比如
声明:
HADOOP=/usr/local/hadoop/bin/hadoop
我在使用时 就是
$HADOOP fs -put ./* /pathdir
4.另外就是 定时任务设定的时间,以前总听 大家讲按天 执行 脚本的定时任务都是设置在后半夜 凌晨两三点的,这样做能尽可能的不影响线上业务 ,得到的信息可能也是比较容易计算 的不会多少。可是我刚开始也这么做了,结果没有拿到数据,我不知道为什么,还以为是脚本没被执行或者执行错误,但最后通过观察 源文件目录的生成时间原来是下午一点多,当然非常可笑,人家都没有生成 ,我能捉到了才怪呢,所以这个脚本的执行时间 一定是受源文件的生成时间有关的,一定是在源文件生成之后完整后才可以抓取,这样一来 执行的时间也是考究的,不一定非要后半夜 ,折中一下选择更合适的时间
5.存储和删除
我们的定时任务这期主要是中转数据,数据量 每天大概有600G 左右,有时候需要修补数据,每天产生的数据就更多了,我们在中转机器上挂载了 一个2T 的硬盘,按道理装两天的肯定够,不过还是经常能碰到 数据传输的时候,磁盘就剩20G了,稍微不注意,磁盘被占满,数据传输被阻塞 ,使用scp 是不支持中断传输的,数据流 最烦的就是传了一半半半儿的,修补数据使用 通配符 或者正则匹配都多多少少有点小麻烦,很多人推荐使用 rsync 传输 ,支持中断和 update 覆盖,存储是限量的,所以 必要的定时删除也是必要的,删除的时机也很重要,比如按天分类目录的,我们在前一天的日志 传输完整 数据完整性验证后 并上传到 目的地 完成相应的存储和计算任务 后,并 新一天的数据开始正常传输后的一到两个小时内 删除即可,这是整体一口气删除,当然这个时候 可能 部分数据会占用一天的磁盘时间,假如我们是按小时传输 验证的,也完全可以在每小时 传输验证后的 十分钟内删除 掉上一个时间段的中转数据,这样做的节省磁盘空间 ,缺点是出现异常 修补数据可能需要重新从源机器传输,另外 rm -rf file 删除大文件也是一个非常耗时的,耗 cpu 的,600G 的数据一口气删完 ,对于8核16G的 centos 来说可能也需要 20分钟。
6.打印日志 ,
当 把 写脚本 设置定时任务走一遍 ,突然发现 好像 正常的日志流工具也是这么操作的,算是更加熟悉了 ,在我们在执行脚本时 有时候 甚至大部分不在电脑前 半夜凌晨三点还在睡觉,所以追踪track 定时任务的执行情况很重要 ,有了这些日志才可能在出现异常是及时捕获到,可以悠闲滴 喝着拿铁 查看监控,最简单的 就是
echo "$Date( "%y%m%d %H:%M:%S") track message " >> data.log
对于异常 信息 当然更需要被捕获
这样清晰明了 ,我在定位问题的关键节省了很多功夫,排除了很多障碍物
7 数据完整性验证
数据在传输的过程中就必然会遭遇到 数据的丢失和失败,比如 就刚才的 磁盘满了,传输阻塞,某些文件传输到一半就被 咔嚓掉了,假如你没有验证就把他当成完整数据来处理,带来的损失可能非常大,首先数据完整性是一个工程性的话题,一你要尽最大努力保证 数据传输的稳定和可靠,我们使用except >>eof 确保 读原始数据读完,然后在传输到 目的地后 通过简单的 wc -l 比对行数 或者 文件字节大小 du -h ./file ,如果时间充裕或者性能 高亢,我们还可以通过MD5 或者其他 算法 验证文件中途是否遭遇被篡改,数据完整性验证后 通过一个 标志性 success.log空文件 作为 目录验证通过的标志。
8 邮件监控和报警
作为某些leader 他总有各种强迫症,希望可以喝着咖啡 查收邮件 来确认工作的进度,在我们 批量的定时任务执行后 数据验证成功 ,按道理 为了安抚领导的小情绪,我们只有按照一定的套路来让他放心,就是数据最后的状态信息邮件发给他,email的中文
前一行 是醒目的 红色 success 或者 黑色的failed ,剩下的从 传输日志中抓取到的日志信息,让他看个够,最好是够喝一杯星巴克的时间,还有大部分为了数据安全,没有公网只有 内网,这个邮件服务还是需要中转一下,挺头痛的。
9.定时任务队列
在我们执行定时任务是 ,有时候不单单是一个定时任务,可能是很多,比如 我昨天就还开始了 17个定时任务,我们的建议是 定时任务 要有高内聚 低耦合的意识,同一个流程的尽量写在一个脚本里 ,这样也可以做一些类似数据库事务的处理,不是一个流程 的尽量在不同的脚本中,防止一个流程任务的失败 影响到其他任务。
当然 任务的开启就像是打印机的打印流程,先来后到总是有的, 按小时执行的 我们尽量安排在 一个时刻内的05到-45之间,因为 一个任务不可能是立马执行结束的,需要一些时间,太早了怕是元数据没有,太晚了,会影响到下一个时刻的定时任务,我们能做到的就是尽量在一个时刻内解决掉本时刻的所有任务,不要拖累下一个时刻,不然累积就是一个大问题 ,造成越来越多的任务延后执行,甚至宕机。
10后台进程
我们的任务
11.脚本管理
刚才说了 我一天就开了17个定时任务,大致写了20个脚本,如果脚本很散乱,可能不便于管理,假如哪天不小心删除了,想死的心 和想杀人的怒火,哎,好吧我收敛一下。。。
我的建议是 有一个专门的目录 比如 scripts 做脚本管理,脚本的命名最好也是有规律的,可以一目了然之意的。做好脚本的备份和 gitlab的版本控制
12 修补数据 和 流程管理 维护
刚才也说了 数据有时候就像我们的裤子,修修补补又三年,数据丢失 传输失败,肯定要修补一下,怎么修补 和我们的数据文件定义有很大关系,比如我们的源数据是按小时 按机器生成的,我们在修补的时候直接修补丢失时刻的数据即可,但是千万不要刻舟求剑。
另外 一台中转机器一天800G 数据的传输,肯定要使用内网传输,大数据量对于单台机器来说 占用相当大的带宽 ,也会造成一些 延时操作 等等问题。我们还要错开传输的高峰期
13 半夜23点之痛
这个主要是针对我们按小时生成的元数据,我们一般都是延后一个小时去抓取上一个时刻的数据,比如8点十分去抓取 七点一个小时的元数据 ,这个延后一小时会有一定的影响,比如 到了凌晨12点 在linux就是00时刻,就是第二天了,但是我们还要去抓取 上一天的23点的数据, 有时候我脑子就错乱了,这个时候就需要 针对 23点做一个 if处理 ,通过教训,为了最小化脚本的代码,有些 脚本 的中出现的 数值 字符串 一定要 变量话,这样在流程管理中 会节省很大功夫,也不容易出错
14 压缩和解压之痛
gzip 压缩可以达到 八倍,在加上tarball ,其实能够很好的处理数据,但是 解压时间超级长,比如说 tarball 是 10G ,解压后 100G ,这个解压过程其实有半个小时左右,很长很吓人,我们本想使用snappy ,但是在linux上操作还有点问题,我们的原始数据是隔天打包,大前天打包 ,昨天的不压缩,所以只能争取尽快在没压缩之前传输,另外 争取 使用snappy 更好 更快。