Linux环境下后台所产生的海量数据大多是借助于Log保存的,但文本文件处理数据是有很大局限性的,因此需要对数据进行格式化处理,并存入数据库。其工作流程可以分为以下几方面:
一、数据拉取环节
数据拉取环节主要实现的是将数据从游戏服务器端拉取到跳板机端,对Log数据的处理要放在跳板机或实验机上完成,而不能直接在服务器上处理,因为服务器主要用于提供后台服务。
数据拉取实现的关键在于:实现一个可复用的Log拉取脚本,只要保证任意一份Log成功地从服务器端拉取到跳板机上,就能够重复地利用该脚本完成将整个Log数据拉取的过程。
需要考虑的参数有:数据拉取超时限制、服务器的IP、用户名、密码、目标文件、存储文件路径,这些都会以命令行参数的形式进行传入。
set timeout 1000
set ip [lindex $argv 0]
set user [lindex $argv 1]
set fromFile [lindex $argv 2]
set toFile [lindex $argv 3]
set password [lindex $argv 4]
最后使用rsync命令进行最后的数据拉取:
set pid [spawn /usr/bin/rsync -avzu ${user}@${ip}#36000:${fromFile} ${toFile}]
同时,还必须要考虑,在数据拉取的过程中,服务器端会要求用户的身份验证,为了避免在使用自动拉取脚本过程中还需要输入用户名和密码的问题。使用了spawn命令-Expect编程工具语言,用于自动和交互式任务进行通信。
expect {
“password:” {
send “${password}\r”
exp_continue
}
“yes/no)?” {
send “yes\r”
exp_continue
}
}
最后,我们可以复用数据自动拉取的脚本,遍历服务器端所需要拉到的所有文件,即可成功实现整个数据拉取的过程。比如拉取的是2010-8-30号~2010-9-05号的广东1~广东5区的所有Log,拉取过程持续约一个半小时。
二、数据库表的创建
当数据拉取完成之后,就进入了数据表的创建过程。对于Log日志中的每一条数据而言,都是用“|”进行分隔的。在这些数据段中,并非所有的数据项都是我们所需要的,通常在做数据分析之前,我们需要筛选有用的数据项。并将这些数据项创建成数据表,最后再将Log中的数据进行入库。
数据库选用MySQL,SQL语句的写法一般类似于:
create database if not exists `qxzb_log`;
USE `qxzb_log`;
/*Table structure for table `AccountLogin` */
DROP TABLE IF EXISTS `AccountLogin`;
CREATE TABLE `AccountLogin` (
`region` varchar(48) NOT NULL,
`iEventId` int(20) NOT NULL DEFAULT 0,
`iUin` int(20) NOT NULL,
`rankId` int(3) NOT NULL DEFAULT 0,
`dtEventTime` datetime DEFAULT NULL,
`vClientIp` varchar(20) NOT NULL,
`dtCreateTime` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
编码的格式采用UTF-8,存储引擎采用MyISAM,并且为了保证数据插入的效率,最初时候并不创建任何索引,而由后期一次性地将数据LOAD完成之后,再创建索引。
三、数据格式化处理
数据库表创建完成之后,就进入了数据格式化处理的阶段,即根据数据库表的设计,将Log日志处理成可以Load入数据库表的结构,并暂时存入到一个临时文件中。处理的编码类似于:
cat ${LOGPATH} | grep ${keyword} | awk -F ‘|’ ‘{print $region”|”$2″|”$3″|”$4″|”$5″|”$6″|”$7}’ >> ${TEMPPATH}/${keyword}_${day}_${hour}.txt
即将有用的数据项提取出来,并以“|”进行分隔,写入一个临时文件中。该过程耗时相当的长,大约2个多小时才完成6天的Log数据格式化处理。
四、数据入库处理
最后一个操作是数据入库的处理,主要完成将临时文件的内容Load进入数据库,并对关键字段创建索引。在第2步数据库表创建过程中,我们只是完成了基表的创建,我们不能够把所有的Log日志数据放到一张表里面,原因是每天都会产生海量的Log数据,这样会造成一张表内的数据量急剧膨胀,而一张表的容量有限,且海量数据存入一张表会造成数据读取访问性能的降低。通常的解决办法就是采用库表的散列,这里使用横向拆分,以每个小时作为时段,使用like命令,拷贝基表的结构,创建一张新的子表,并将该时段的数据入库。
拷贝基表的SQL语句写法类似于:
mysql -u${user} -s -e “create table if not exists ${DATABASE}.${tablename}_${day}_${hour} like ${DATABASE}.${tablename};”
考虑到该表可能已经存在,则需要清空之前所残留的数据:
mysql -u${user} -s -e “delete from ${DATABASE}.${tablename}_${day}_${hour};”
下面是具体的数据入库操作,是将我们之前所产生的已经格式化的临时文件Load入数据库,其SQL语句的写法类似于:
mysql -u${user} -s -e “load data infile ‘${TEMPPATH}/${keyword}_${day}_${hour}.txt’ into table ${DATABASE}.${keyword}_${day}_${hour} FIELDS terminated by ‘|’ ENCLOSED by ”;”
数据的Load操作属于猝发式的写入,效率要比一条记录一条记录的insert要高出很多,因此,我们通常是先格式化文件,再进行Load操作,以提高数据写入的效率。
最后,对关键字段创建索引,这里主要是对玩家的QQ号码字段进行创建索引,提高以后的查询效率和性能,SQL语句的写法类似于:
mysql -u${user} -s -e “create index index_${indexword} USING BTREE on ${DATABASE}.${keyword}_${day}_${hour} (${indexword});”
整个数据Load和创建索引的过程时间比较短,只需要10多分钟即可完成千万级数据的入库处理。
以上4个环节就是我对后台海量数据拉取入库整个流程的操作方法的总结,是暑假腾讯实习的一些经验收获。