我正在设计一个系统,该系统应该分析大量的用户交易并产生汇总的度量值(例如趋势等)。
该系统应运行迅速,功能强大且可扩展。
系统基于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条记录,因此我想到了使用Storm Field Grouping(这意味着对同一用户调用同一任务)并跟踪任务中10条用户记录的收集,我当然计划要执行多个任务,每个任务只能处理一部分用户。
#3我需要您的帮助。
设计此类组件的最佳实践是什么?
显然,每个用户需要维护10条记录的数据。
键值映射可能会有所帮助,最好在任务本身中或使用分布式缓存来管理该映射?
例如Redis键值存储(我以前从未使用过)。
谢谢你的帮助
最佳答案
我已经使用过redis了很多。因此,我将评论您对使用Redis的想法
#3有3个要求
1.每个用户的缓冲区:
Redis只是一个关键值存储。尽管它支持各种各样的datatypes,但它们始终是映射到STRING键的值。因此,如果需要每个用户缓冲区,则应决定如何唯一地标识用户。因为在redis中,当您覆盖键新值时,您将永远不会出错。一种解决方案是在写之前检查其存在。
2. 10个任务的缓冲区:您显然可以在redis中实现queue。但是限制它的大小留给您。例如:使用
LPUSH
和LTRIM
或使用LLEN
检查长度并决定是否触发您的过程。与该队列关联的密钥应该是您在第1部分中确定的密钥。3.缓冲区在5分钟内过期:这是最困难的任务。在redis中,每个键无论其值具有何种底层数据类型,都可以具有
expiry
。但是到期过程是静默的。您不会在任何密钥到期时收到通知。因此,如果使用此属性,您将无声地丢失缓冲区。解决此问题的一种方法是拥有索引。意味着,索引会将时间戳映射到所有需要在该时间戳值处过期的键。然后在后台,您可以每分钟读取一次索引,并从redis中手动删除[读取后]键,并使用缓冲区数据调用所需的过程。要获得这样的索引,可以查看Sorted Sets。其中timestamp是您的score
,设置的member
将是您希望在该时间戳上删除的键[在第1部分中,每个用户确定的唯一键(映射到队列)。您可以执行zrangebyscore
以读取具有指定时间戳记的所有set成员总体:
使用Redis List实现队列。
使用LLEN来确保您没有超过10个限制。
每当您创建新列表时,都应在索引[Sorted Set]中输入一个条目,其中Score为
Current Timestamp + 5 min
,Value为该列表的键。当LLEN达到10时,切记要读取然后从索引[sorted set]和数据库[删除密钥->列表]中删除密钥。然后使用数据触发您的过程。
每隔一分钟,生成一个当前时间戳,读取索引,对于每个键,读取数据,然后从db中删除键并触发您的进程。
这可能是我实现它的方式。可能还有其他更好的方法来在Redis中对数据建模