2.6 统计与持久化日志统计信息
我们其实可以收集很多日志流的统计信息,但由于本节只是为了展示一些基本概念,因此我们只准备收集和处理单时间序列(每分钟)日志量。虽说如此,但这应该已经足以展示有关的设计和方法了,这些技巧能够帮助你在未来实现其他分析工作。
2.6.1 实战
Step01 下载storm-cassandra contrib项目并将其安装到Maven仓库中:
Step02 在storm.cookbook.log包中,创建一个继承自BaseRichBolt的类VolumeCountingBolt。为该Bolt声明以下三个字段:
Step03 然后实现一个静态工具方法,该方法的作用是获取日志的时间信息,按分钟形式表示出来:
Step04 实现execute方法(没错,函数体很短):
Step05 最后,参照第1章中的方法来创建LogTopology类,并按照如下方法创建Topology:
2.6.2 解析
该实现方法看起来简单得让人感到不可思议,但事实确实如此。在实现过程中我们使用了storm-cassandra项目(该项目属于storm-contrib组件)来对所有持久化复杂性进行抽象。storm-cassandra项目通过一个通用且可配置的backtype.storm.Bolt实现来集成Storm和Cassandra,该Bolt的作用是将StormTuple对象写入Cassandra 列族。
Cassandra是一个面向列族的数据库系统(http://cassandra.apache.org/)。Cassandra的列族数据模型在提供二级索引便利的同时还具备日志式结构更新的存储性能,另外也提供了健壮的物化视图支持和强大的内置缓存。Cassandra最新的一个功能是计数器列。你可以在集群上的任何地方,通过持久化指定计数器列族中的计数器列来实现计数器的安全自增。
storm-cassandra项目支持两种持久化风格,第一种是标准的Cassandra列族风格,第二种是基于计数器列的风格。我们在这里只关注第二种类型的风格,因为它非常适用于当前这个例子。你可以阅读项目的README文件中有关其他风格的介绍,基本上都差不多。
CassandraCounterBatchingBolt类的实例就能帮我们搞定所有工作 。只需告诉它我们要使用哪个列族,哪个Tuple字段作为行键,哪个Tuple字段作为增量,而Tuple中剩下的那个字段则指明了需要更新的计数器列。
我们来看看下面的构造函数:
以及以下作为输入的元组数据:
这会把columnFamily列族中的SomeCounter计数器列加1L。
对于任何有关系型数据库背景的开发人员来说,最关键的观念转变在于了解面向列族数据库中的数据建模。作为数据库中大数据家族的一分子,面向列族的数据库促进了高度不规则数据模型的应用。这个方法移除了表之间的关系以及它们的锁,实现了对数据库的大规模、并行读写的处理。虽然这种方法会增加数据的冗余,但为了满足当今大规模数据处理的需求,在一些普通磁盘上面的开销其实算不了什么问题。观念的转变在于我们要根据在数据集上执行的查询来选择适当的数据模型,而不是简单地将现实世界模型转化成固有和统一的结构。对应当前查询的数据类型可以归纳为:查询给定时间点上所有日志文件的总数 。
这种方法能让我们通过简单地发送Tuple来生成统计数据,我们可以使用这种方法来得到各种问题的答案,下面给出几个例子:
- 我们的日志体积随着给定时间周期(可以是日、月或者年)的变化趋势到底是什么样的?
- 日志文件中出现频率最高的词干是什么?
列族不只可以包含统计数据,你可以设计任意的不规则结构,并通过发送一个Tuple来表示某一行中任意列的集合。如果该行已经存在,Cassandra会简单地添加或者更新数据。这其实可以实现非常强大的功能。