我正在设计一个系统,该系统应该分析大量的用户交易并产生汇总的度量值(例如趋势等)。
该系统应运行迅速,功能强大且可扩展。
系统基于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键值存储(我以前从未使用过)。

    谢谢你的帮助

    最佳答案

    我已经使用过redis了很多。因此,我将评论您对使用Redis的想法

    #3有3个要求

  • 每个用户的缓冲区
  • 10个任务的缓冲区
  • 应该每5分钟过期一次

  • 1.每个用户的缓冲区:
    Redis只是一个关键值存储。尽管它支持各种各样的datatypes,但它们始终是映射到STRING键的值。因此,如果需要每个用户缓冲区,则应决定如何唯一地标识用户。因为在redis中,当您覆盖键新值时,您将永远不会出错。一种解决方案是在写之前检查其存在。

    2. 10个任务的缓冲区:您显然可以在redis中实现queue。但是限制它的大小留给您。例如:使用LPUSHLTRIM或使用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中对数据建模

    07-26 09:36