工作上有这样一个需求:
服务端每天产生的埋点日志比较多>200万行,凌晨2点将这个日志的数据入库到数据库,便于BI分析。
最初我的思路是:写一个shell脚本,将入库的逻辑放入shell脚本中,再将这个shell脚本放入到linux服务器crontab任务中。
说起来简单,但在编写的过程中遇到了问题,主要是日志量大,入库的速度很慢,最初的实现是
cat statlog.log | while read line 这种遍历日志,按行读取来入库,速度超慢。
经优化,采用awk的方式来做:
1,代码如下:
BEGIN{
FS=","
user="test"
passwd="test"
host="192.168.0.9"
print "==============start=================="
sqlInsert="INSERT INTO log.logs_mobile_stat (p1, p2, p3, p4, p5, type, cookie, user_id, time, platform) VALUES"
sql=sqlInsert
idx=0
conMysql="mysql -h" host " -u" user " -p'" passwd "' log -e " "date +%Y-%m-%d\ %H:%M:%S" | getline time;print time;
}
{
idx=idx+1
#每1000条记录拼接长一条sql
if(idx==1000){
sqlValues="('"$2"', '"$3"', '"$4"', '"$5"', '"$6"', '"$7"', '"$8"', '"$9"','"$1"','"$10"');"
sql=sql sqlValues
str=conMysql "\"" sql "\" "
system(str)
idx=0
sql=sqlInsert
}else{
sqlValues="('"$2"', '"$3"', '"$4"', '"$5"', '"$6"', '"$7"', '"$8"', '"$9"','"$1"','"$10"'),"
sql=sql sqlValues
}
}
END{
#去掉最后的分号
sql= substr(sql, 0, length(sql))
str=conMysql "\"" sql "\" "
#执行最后不足1000条记录的sql
if(idx>0 && idx<1000){
system(str)
print"=============end============idx====="idx
}
"date +%Y--%m-%d\ %H:%M:%S" | getline time2;print time2
print"=============end================="
}
2,将上面的代码保存为stat.awk文件,写个调度stat.awk文件的shell,文件名为executeStat.sh
#!/bin/sh date=`date -d -1day +%Y-%m-%d`; log=/home/www/logs/taofen8/api/statlog.log.$date sudo awk -f /tmp/stat.awk $log
3,将executeStat.sh加入到crontab定时任务中, 每天凌晨2点执行
0 2 * * * sudo /tmp/executeStat.sh > /tmp/stat.log
经线上测试,200万左右的日志入库2分钟左右,速度还可以吧。

针对服务端每日产生的超过200万行埋点日志,本文介绍了一种使用awk脚本进行高效批量处理并入库的方法,大幅提高了入库速度。
845

被折叠的 条评论
为什么被折叠?



