2016-06-01 68 views
-2

运行一个C#.net应用程序,每隔30秒从100个客户端接收数据,然后将数据存储在数据库中。数据是针对每个客户端的两个参数。我需要为每个客户每小时确定每个参数的总和,并根据结果做出决定。决策算法将以滑动窗口的方式为最后一小时的数据做出决定。我最初的想法是保留100个客户端的字典,其中关键是客户端IP,价值是一个总计。但是1)如果我的应用程序在半小时或59分钟的时候重新开始,我就失去了所有这些温暖的运行总数。 2)如果更多的客户端开始发送数据,字典将消耗更多的内存,3)如果将来2个参数变为100,字典增长更大4)使运行总值总是反映一小时的最近数据值不是直截了当。从传入流计算随时间变化的值的最佳方法

我应该考虑哪些不同的方法?最佳实践?设计模式?

+2

这是非常广阔的,但这里有我的两分钱:1店在数据库中的数据,2 *键值为客户端IP *非常糟糕的主意,两个不同的客户端可以具有相同的外部IP(流量通过代理, nat,其他)。 2,在客户端生成GUID并将其存储在客户端上,然后当客户端连接发送ID,这样你会毫不含糊地identfy每个客户端,甚至可以有多个用户在同一台​​机器上。 – Gusman

+0

谢谢。 IP是一个坏主意,我同意。我将使用GUID。对于数据库存储,我将在传入数据到达时进行存储。决策逻辑在存储之前在数据上运行。还是你的意思是,存储它,然后决定逻辑定期工作的数据库?我试图避免这种情况,因为它可能无法在数据库读取和常量写入方面表现良好。 – sOltan

+0

是的,我打算在存储的数据上间隔运行它。关于性能,你说你将有100个客户端,你希望每个客户端创建多少个寄存器?任何实际的数据库都将工作得足够快,以支持每秒数千次写入,因此根据事务量可能足够快或不足。 – Gusman

回答

0

很广,但我会尝试定义结构:

  1. 确定每个客户端连续8个字节的整数,UID。不是GUID,甚至没有顺序的GUID。 4字节的整数是一个选项,但我会坚持8字节。种子从十万。

  2. 用连续的8字节整数CID识别来自用户的每个呼叫。不是GUID,甚至没有顺序的GUID。 4字节的整数是一个选项,但我会坚持8字节。我将从1970-01-01T00:00:00开始以CID为单位进行微秒数。

  3. 将所有数据存储在存档数据库表REPORT_ARCHIVE中,UID + CID是复杂的PK。 CID散列上的簇表使其变得矮胖(每年/每次录制1个文件)。

  4. 在操作数据库表REPORT_OPER中存储最后N条记录(N取决于您的时间窗口,应该是您的配置值),UID + CID是复杂的PK。 UID散列上的群集(8-16个文件)。

  5. 将所有传入的调用像队列一样管理到内存结构中。异步处理代理应该抓取队列中的记录。通过大块抓取,使用数据块分块(SQL Server和Oracle支持)保存到DB中。保存到REPORT_OPER表中,在INSERT上设置触发器以将数据从REPORT_OPER推送到REPORT_ARCHIVE。

  6. 运行所有的工作对REPORT_OPER查询(总结等),您的分析可以运行在REPORT_ARCHIVE。

  7. 对于类似于最新的X报告的SUM,我会在使用UID作为关键字的ConcurrentDictionary的内存中缓存SUM。重要提示:缓存请求呼叫(管理员要求总计),而不是插入呼叫(用户在30秒间隔内呼入)。为此,您需要就SLA达成一致 - 报告总计可接受的延迟是多少。如果客户希望接近实时 - 协商调用频率来计算缓存命中/未命中。

祝你好运。