我正在设计一个系统,该系统应分析大量用户事务并生成汇总度量(如趋势等)。 系统应该快速,稳健和可扩展。 System是基于java的(在Linux上)。
数据从生成用户事务的日志文件(基于CSV)的系统到达。 系统每分钟生成一个文件,每个文件包含不同用户的事务(按时间排序),每个文件可能包含数千个用户。
CSV文件的示例数据结构:
10:30:01,用户1,...
10:30:01,用户1,...
10:30:02,用户78,...
10:30:02,用户2,...
10:30:03,用户1,...
10:30:04,用户2,...
。
。
我计划的系统应该处理文件并实时进行一些分析。 它必须收集输入,将其发送到多个算法和其他系统,并将计算结果存储在数据库中。数据库不保存实际输入记录,而只保留有关事务的高级聚合分析。例如趋势等。
我计划使用的第一个算法要求最佳操作至少10个用户记录,如果5分钟后找不到10条记录,它应该使用可用的数据。
我想使用Storm来实现,但我更愿意尽可能地将这个讨论留在设计层面。
系统组件列表:
每分钟监视传入文件的任务。
读取文件,解析文件并使其可用于其他系统组件和算法的任务。
用于缓冲用户的10条记录(不超过5分钟)的组件,当收集10条记录或5分钟后,是时候将数据发送到算法进行进一步处理。 由于要求为算法提供至少10条记录,我想到使用Storm Field Grouping(这意味着为同一个用户调用相同的任务)并跟踪任务中10个用户记录的集合,当然,我计划完成其中的几项任务,每项任务都处理一部分用户。
还有其他组件可以处理单个事务,对于它们,我计划创建其他任务,在解析每个事务时(与其他任务并行)接收每个事务。
我需要你的帮助#3。
设计此类组件的最佳做法是什么? 很明显,它需要为每个用户维护10条记录的数据。 键值映射可能会有所帮助,是否可以在任务本身或使用分布式缓存中管理映射? 例如Redis是一个键值存储(之前从未使用过它)。
感谢您的帮助
答案 0 :(得分:5)
我曾经使用过redis。所以,我会评论你使用redis的想法
#3有3个要求
每个用户的缓冲区
10个任务的缓冲区
应该每5分钟过期
<强> 1。每个用户缓冲区: Redis只是一个重要的超值商店。虽然它支持各种datatypes,但它们始终是映射到STRING键的值。因此,您应该决定如何识别每个用户缓冲区所需的唯一用户。因为在重写中,当您覆盖键新值时,永远不会出现错误。一种解决方案可能是在写入之前检查存在。
<强> 2。适用于10个任务的缓冲区:您显然可以在redis中实现queue。但限制它的大小留给你。例如:使用LPUSH
和LTRIM
或使用LLEN
检查长度并决定是否触发您的流程。与此队列关联的密钥应该是您在第1部分中决定的密钥。
第3。缓冲区在5分钟后到期:这是一项最艰巨的任务。在redis中,无论其值具有什么基础数据类型,每个键都可以有expiry
。但到期过程是沉默的。任何密钥到期时您都不会收到通知。因此,如果您使用此属性,您将默默地丢失缓冲区。解决这个问题的一个方法就是拥有一个索引。意味着,索引会将时间戳映射到所有需要在该时间戳值处过期的键。然后在后台,您可以每分钟读取索引并手动删除[读取]后的密钥,并使用缓冲区数据调用所需的进程。要拥有这样的索引,您可以查看Sorted Sets。如果时间戳为score
,则设置member
将是您希望在该时间戳删除的键[在第1部分中确定的映射到队列的每个用户的唯一键]。您可以zrangebyscore
读取具有指定时间戳的所有集成员
<强>总体:强>
使用Redis List实现队列。
使用LLEN确保您不超过10限制。
每当您创建一个新列表时,请输入索引[Sorted Set],其中Score为Current Timestamp + 5 min
,Value为列表的键。
当LLEN达到10时,记得阅读然后从索引[sorted set]和db [delete the key-&gt; list]中删除密钥。然后使用数据触发您的流程。
每一分钟,生成当前时间戳,读取索引和每个键,读取数据然后从数据库中删除密钥并触发您的过程。
这可能是我实现它的方式。可能还有其他更好的方法来在redis中建模数据
答案 1 :(得分:0)
根据您的要求1&amp; 2:[Apache Flume或Kafka]
根据您的要求#3:[Storm里面的Esper Bolt。在Redis中完成此操作,您将不得不重写Esper Logic。]