记录一下互联网日志实时收集和实时计算的简单方案

作为互联网公司,网站监测日志当然是数据的最大来源。我们目前的规模也不大,每天的日志量大约1TB。后续90%以上的业务都是需要基于日志来完 成,之前,业务中对实时的要求并不高,最多也就是准实时(延迟半小时以上),因此,我们使用Flume将数据收集到HDFS,然后进行清洗和分析。

后来,根据业务需要,我们有了两个Hadoop集群,并且部署在不同的地方(北京和西安),而所有的日志收集服务器在北京,因此需要将日志数据通过外网传输到西安,于是有了这样的部署:

很快,通过Flume流到西安Hadoop集群的数据就遇到了问题,比原始数据多或者少一些,造成这个问题的主要原因是在网络不稳定的情况下,北京 Flume Agent发送到西安Flume Collector的过程中,会发送失败,或者响应失败。另外,之前的数据准实时也不能满足业务的需求。

为了解决数据实时跨外网传输以及实时业务的问题,于是有了现在的架构:

  1. 引入Kafka,并且和日志收集服务器部署在北京同机房;
  2. 每台日志收集服务器上的Flume Agent,通过内网将数据发送至Kafka;
  3. Kafka的第一个消费者,北京网关机上的Flume,负责从Kafka中消费数据,然后流到北京Hadoop集群;
  4. Kafka的第二个消费者,西安网关机上的Flume,负责从Kafka中消费数据,然后流到西安Hadoop集群;这里是西安的Flume通过 外网连接北京Kafka,主动拉取数据,如果网络不稳定,那么当前批次拉取失败,最多重新拉一次,数据不会进Flume channel,更不会流到HDFS上,因此,这种方式在网络不稳定的情况下,不会造成数据缺失或重复;
  5. Kafka的第三个消费者,北京网关机上的实时计算模块,后面再说;
  6. Kafka的第N个消费者,其他;

Kafka中的数据分区及副本

这种架构下,Kafka成为了统一的日志数据提供者,至关重要。我们目前有4台Broker节点,每个Topic在创建时候都指定了4个分区,副本数为2;

数据在进入Kafka分区的时候,使用了Flume的拦截器,从日志中提取用户ID,然后通过HASH取模,将数据流到Kafka相应的分区中。这 种方式,一方面,完成了简单的负载均衡,另一方面,确保相同的用户数据都处于同一个分区中,为后面实时计算模块的统计提供了极大的便利。

Flume拦截器的使用

在整个流程中,有两个地方用到了同一个Flume拦截器(Regex Extractor Interceptor),就是在Flume Source中从消息中提取数据,并加入到Header,供Sink使用;

  • 一处是在LogServer上部署的Flume Source,它从原始日志中提取出用户ID,然后加入到Header中,Flume Sink(Kafka Sink)再入Kafka之前,从Header中拿出该用户ID,然后通过应用分区规则,将该条消息写入Kafka对应的分区中;
  • 另外一处是部署在西安的Flume Source,它从Kafka中读取消息之后,从消息中抽取出时间字段,并加入到Header中,后面的Flume Sink(HDFS Sink)通过读取Header中时间,根据消息中的时间,将数据写入HDFS相应的目录和文件中。如果在HDFS Sink中仅仅使用当前时间来确定HDFS目录和文件名称,这样会造成一小部分数据没有写入到正确的目录和文件中,比如:日志中8点59分59秒的数据可 能会被写进HDFS上9点的目录和文件中,因为原始数据经过Kafka,通过外网传输到西安的Flume,有个几秒的延时,那是很正常的。

Flume消费者的负载均衡和容错

在北京部署的Flume,使用Kafka Source从Kafka中读取数据流向北京Hadoop集群,西安的也一样,在消费同一Topic的消息时候,我们都是在两台机器上启动了两个 Flume Agent,并且设置的统一消费组(group.id),根据Kafka相同的Topic,一条消息只能被同一消费组内的一个消费者消费,因 此,Kafka中的一条消息,只会被这两个Flume Agent其中的一个消费掉,如果一个Flume Agent挂掉,那么另外一个将会消费所有消息;

这种方式,也是在流向HDFS的消费者端做了负载均衡和容错。

实时计算模块

目前我们实时计算的业务比较简单,就是类似于根据不同维度统计PV和UV。比如:实时统计一个网站当天的累计PV、UV、IP数等,目前我们直接开发的JAVA程序,使用streamlib统计这些指标,UV和IP数这种需要去重的指标有2%以内的误差,业务可以接受。

实时计算模块使用Kafka low-level API,针对每一个Topic,都使用和分区数相等的线程去处理,每个线程消费一个分区的数据,由于数据在进入Kafka分区的时候,都是经过相应规则的分区,因此相同用户的数据会在同一个分区中;

另外,每个线程会在Redis中维护自己当前的Offsets,比如:在实时计算当天累计指标的业务场景中,每天0天在Redis中记录当前的 Offsets,这样,如果实时计算程序挂掉,下次启动时候,从Redis中读取当天的Offsets,重新读取和计算当天的所有消息。

由于我们的需求是实时统计当天累计的指标,而且能接受一定的误差,因此采用这种方式。如果需要精确统计累计去重指标,那么可能需要采用其它方式,比如:精确统计当天实时累计用户数,一种简单的办法是在HBase中使用计数器来配合完成。

其它实时数据消费者

如果需要实时统计一小段时间(比如十分钟、一小时)之内的PV、UV等指标,那么可以使用SparkStreaming来完成,比较简单。如果单独使用Spark Streaming来完成一天内海量数据的累计去重统计,我还不太清楚有什么好的解决办法。

另外,实时OLAP也可能作为Kafka的实时消费者应用,比如:Druid。

原文发布于微信公众号 - nginx(nginx-study)

原文发表时间:2016-06-15

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java达人

Netty 长连接服务

来源:Dozer's Technology Blog 链接:https://www.dozer.cc/2014/12/netty-long-connectio...

1.2K8
来自专栏EAWorld

从前世看今生,从JavaEE到微服务

我有一个习惯,接触到新概念、新技术出现后,就会探究他的前世今生、来龙去脉,正所谓“太阳底下没有新鲜事”,喜欢从对比中找到价值点,不如此就觉得理解不透彻,就觉得少...

3537
来自专栏性能与架构

美国建站平台 Wix 的架构变迁

背景 Wix 是全世界最大的自助建站云平台,可以让每一个人通过拖拽等简单的方式轻松的创建一个漂亮的网站 这个平台上已经创建了6000万个网站,覆盖190个国家...

5794
来自专栏大魏分享(微信公众号:david-share)

一个自来水公司的业务集成-数据库与Restful API的对接:构建以API为中心的敏捷集成系列-第三篇

CoolWater Inc.是一家当地的自来水公司,客户需要实施支付管理系统,目的是为客户提供便捷的在线水费支付界面。

1952
来自专栏Material Design组件

Human Interface Guidelines — Photo Editing

1137
来自专栏无题

各RDB与Nosql性能与特点总结

最近考虑到数据库包括各种缓存到底面对高并发情况性能到底是怎么样的,所以多方收集整理成此篇,以后也会持续更新。 mysql: 1.性能从10万条规模升到100万...

41611
来自专栏北京马哥教育

超实用:小团队如何从零搭建一个自动化运维体系?

如下图,现在行业内各巨头自动化运维架构的最终样子大家都知道了,但是如何根据自己团队当前的情况一步步向这个目标演进?

1480
来自专栏blackheart的专栏

[解读REST] 6.REST的应用经验以及教训

衔接上文[解读REST] 5.Web的需求 & 推导REST,上文根据Web的需求推导出了REST架构风格,以及REST的详细描述和解释。自从1994年以来,R...

26210
来自专栏小狼的世界

Ajax与REST

REST(Representational State Transfer)是一种开发思想,互联网不断发展,富媒体越来越多的应用,不断地冲击着我们的应用,使应用的...

1052
来自专栏加米谷大数据

Kafka性能测试

耗时:18秒 总体文件大小:2193.45MB 最大处理量:163.6659MB/S TPS:171616.1767条

3302

扫码关注云+社区

领取腾讯云代金券