假设这样一个场景,用户有许多的机器(ECS或者自有机房的都可以),每天产生非常多的日志,记录了用户的访问的一些信息,比如userId,访问的页面地址,访问的时间,访问Ip等等。我们对这些数据进行一个离线分析,每天分析一次,计算网站的各个页面的UV、PV,并观察一下是否有作弊的情况:如多个不同的账号来自于同一个IP。并能将最终的这个结果同步到数据库中,在管理后台查看。
那么使用E-MapReduce要如何来做呢?
第一步 获取日志数据
首先,我们需要获取所有服务器的日志数据。这个可以通过阿里云的日志服务(SLS)来完成。
可以安装日志服务的客户端到指定的机器上,然后在日志服务的控制台进行数据收集配置,就能够把数据收集上来了。
具体的可以参考日志服务使用说明
你可以在配置中指定你需要收集的目录和文件名,通过这一步,所有的机器上的日志就都会被收集到日志服务中去。
第二步 将数据投递到OSS
收集到了数据。现在我们要把这些数据都放到OSS上去。主要是几个原因
- OSS的存储本身非常便宜,而日志服务默认数据并不永久保存
- 日志服务没有提供读取大量离线数据的接口
在LogStore管理标签下能够看到有一栏日志投递,如下
点击对应的LogStore后面的OSS(创建),就可以创建一个到OSS的投递任务了
详细的配置参考,投递到OSS
其中有几点要注意的
- 投递的时候,是否压缩选项请选择非压缩的文本
- 是OSS投递的路径最终是这样构成的,会自动加上很多层的路径
- 所有的投递的数据都是一个json结构,并不是原始的数据格式
这个就需要我们在处理数据的时候,要对所有的目录进行遍历,并将数据做一次json解析,将最终要处理的数据内容取出来
第三步 使用Hive处理数据
这里假定,日志文件的内容是一个文本,对应到一个key叫content。里面的多个字段使用|来分割,保存到OSS中的数据类似如下的格式 {"content":"1463987545149|12345|121.164.16.19|www.xxxx.com/user"}
若使用emr-1.0.x或者emr-1.1.x,其中的Hive版本是1.0.1,使用下面的sql
CREATE EXTERNAL TABLE logtable (logcontent string) stored AS textfile location 'oss://{accesskeyId}: {accesskeysecret}@{bucketname}.{endpoint}/{dirname}/';
set hive.mapred.supports.subdirectories=true;
set mapreduce.input.fileinputformat.input.dir.recursive=true;
select get_json_object(logcontent, '$.content') as content from logtable limit 10000;
若使用emr-1.2.x或者emr-1.3.x,其中的Hive版本是2.0.0,使用下面的sql
CREATE EXTERNAL TABLE logtable (logcontent string) stored AS textfile location 'oss://{accesskeyId}: {accesskeysecret}@{bucketname}.{endpoint}/{dirname}/';
set mapreduce.input.fileinputformat.input.dir.recursive=true;
select get_json_object(logcontent, '$.content') as content from logtable limit 10000;
accesskeyId,accesskeysecret就是你的akid,和secret
bucketname是OSS对应的bucket的名字
dirname是投递到OSS的目录,因为设置了遍历所有目录,所以只要写这一级目录就可以了
endpoint的配置可以参考这里
get_json_object就是用来从json格式数据中将content这个key对应的内容取出来使用
接下来我们需要把要使用的字段都解析出来使用,比如UserId,Ip等等,我们使用分隔符|来对日志内容进行分割。
我这里是采用创建了一张新的表,而这张表的对应数据是保存在计算集群的HDFS上的
drop table if exists resulttable;
create table resulttable
as
select
split(get_json_object(logcontent, '$.content'), "\\|")[0] as visit_time,
split(get_json_object(logcontent, '$.content'), "\\|")[1] as user_id,
split(get_json_object(logcontent, '$.content'), "\\|")[2] as visit_ip,
split(get_json_object(logcontent, '$.content'), "\\|")[3] as visit_url
from logtable;
这张resulttable表就可以作为后续处理的起点,对数据进行各种统计,比如PV,UV等。
第四步 同步数据到Mysql
所有的数据计算完成以后,我们可以把结果同步到Mysql(RDS)中去。
要同步数据,请参考这里 使用Sqoop同步数据
目前同步数据还不是自动化的,后续E-MapReduce会有数据同步的作业支持,在计算完成以后,直接就进行数据同步。敬请期待。