ESBasic 可复用的.NET类库(25) -- 增量自动获取器 IIncreaseAutoRetriever

来源:互联网 发布:数据库查询软件密码 编辑:程序博客网 时间:2024/04/27 23:44

1.缘起:

    假设我们的订单报表系统,需要能够实时地统计当天的已成交订单的报表。最直观的解决方案就是,当每次接收到查询报表的请求时,就从存储设备读取当天所有已成交的订单,然后再进行分析计算给出结果。这是可行的,而且得到的结果也是非常实时的。

但是,这种方式无疑也是非常低效的,因为我们报表数据的统计过程可能相当复杂,而且,可能是成千上万的用户在同时查询报表数据。在这种情况下,将给存储服务器和业务服务器都造成巨大的压力。

现在我们假设需求能够放宽一点――报表数据不用非常实时,可以允许最大为1分钟的延迟。对于绝大多数业务系统来说,报表数据延迟在1分钟以内,都是能够接受的,所以这个假设并不过分,下面我们基于这个假设来继续讨论。

在报表数据能够允许最大延迟为1分钟许可条件下,我们就可以做缓存的动作了。因为如果要求是完全实时的,那么缓存报表数据能做到的程度就非常的有限,但是有了这一分钟的延迟允许,缓存就可以完全地发挥出它的优势了。

现在,我们可以每隔1分钟从存储设备读取上一分钟已成交的所有注单,这就是所谓的“增量数据”,然后将其做报表分析计算,然后将计算的结果“累加”到之前的“累积的报表数据”上。这样,当用户每次来请求报表数据时,只要将当前累积的报表数据直接返回就可以了。因为我们是每隔1分钟对增量进行累加一次,所以,用户看到的报表数据的延迟最多不会超过1分钟。

 

上述这个例子很好地体现了“增量缓存”的核心思想,上面提到的“累积的报表数据”实际上就是一个增量缓存的典型实例。关于增量缓存,我们会在下一节进行详细介绍。本节我们将先介绍增量缓存会用到的一个基础组件――增量自动获取器ESBasic.ObjectManagement.Increasing.IIncreaseAutoRetriever

现在,我们将注意力集中到上述例子中关于数据增量获取的这个焦点上:

(1)增量可能需要从多个数据源获取。比如,不同类型的订单可能存放在不同的数据库中。

(2)如何体现以一天为单位进行轮转?如果要查看的是周报表,那么就需要将一周作为一轮(Round)。

(3)如果是一天为一轮,那么当经过每天的00:00:00时,增量获取器该如何完结前一天的增量,并切换到新的一天?

 

 这些都是IIncreaseAutoRetriever要解决的问题,而IIncreaseAutoRetriever很好的解决了这些问题,并以一种非常简单易用的接口提供给使用者。

    增量自动获取器的形象示意图如下:

   

 

2.适用场合:

    在满足以下这些条件时,你可以使用IIncreaseAutoRetriever

(1)需要定时从数据源获取新的增量数据。

(2)数据源可能不只一个。

(3)需要支持“轮”(Round)的概念。在Round切换时,需要能够准确识别增量断点。

(4)增量数据有某个字段是递增的。

 

3.设计思想与实现

   在正式解析IIncreaseAutoRetriever的源码之前,我们先将其会涉及到的一些重要概念说明一下。

   首先,数据源可能是多个,所以我们需要为每个数据源设置一个唯一标志(我们称之为Source Token),这标志的类型可能是一个整数,也可能是一个字符串或枚举类型等等。那么,我们可以将数据源标志的类型抽象为一个泛型参数。

   其次,上面我们提到Round,即表示增量完成累积的一个完整周期,比如,可能是一天、一周或一月,这取决于你系统的需求。同样的,我们需要每个Round都有唯一的标志(我们称之为Round ID),以将当前Round同历史的Round区分开来。Round ID的类型也是根据系统的需求来定的,所以,我们也将Round ID的类型抽象为一个泛型参数。

   再次,我们将缘起部分例子中的一分钟的时间间隔称为一个增量阶段Phase。所以,一个Round是由NPhase构成的,而且,N通常是个比较大的值。

最后,由于获取增量数据的时候,我们需要依据数据的某个key来进行判断,哪些数据是在刚过去的一个Phase中新加入进来的,这就要求key是递增的,这对从数据源中提取增量会带来极大的便利。比如,可以使用订单的产生时间作为key,如果订单的编号是递增的,也可以使用订单编号作为key。在数据源是数据库的情况下,最好是使用主键作为key,当然,这个时候主键必须是递增的。

     IIncreaseAutoRetriever增量自动获取器会每隔一段时间就从各个数据源(TSourceToken)获取上一阶段的增量数据(TObject),然后触发事件将得到的增量数据发布出去。

 

下面,我们来看IIncreaseAutoRetriever接口定义: