Algorithm 如何实施";趋势计数器“;用滑动窗口数词?

Algorithm 如何实施";趋势计数器“;用滑动窗口数词?,algorithm,redis,distributed-computing,word-count,sliding-window,Algorithm,Redis,Distributed Computing,Word Count,Sliding Window,我有多个计算单词的过程。例如,我有多个卡夫卡使用者,使用单个卡夫卡主题的不同分区。主题上的每条消息都是一个单词(字符串)。这个词是我的卡夫卡主题的关键和价值所在。 消费者将消费一条消息,并将该单词的计数器增加1 我希望能够查询过去5分钟内最流行的10个单词。 一旦一个单词不再出现在当前窗口中,我就不想计算它了。 假设我们使用处理时间作为时间戳 最好的方法是什么 语言不可知您可以为每分钟维护一个Redis排序集,例如计数器:YYYYMMDDHHmm 插入 当您获得一个新项目时,使用处理时间构造计数

我有多个计算单词的过程。例如,我有多个卡夫卡使用者,使用单个卡夫卡主题的不同分区。主题上的每条消息都是一个单词(字符串)。这个词是我的卡夫卡主题的关键和价值所在。 消费者将消费一条消息,并将该单词的计数器增加1

我希望能够查询过去5分钟内最流行的10个单词。 一旦一个单词不再出现在当前窗口中,我就不想计算它了。 假设我们使用处理时间作为时间戳

最好的方法是什么


语言不可知

您可以为每分钟维护一个Redis
排序集
,例如
计数器:YYYYMMDDHHmm

插入 当您获得一个新项目时,使用处理时间构造计数器的键,并调用
ZINCRBY
增加计数器

// Now it's 2019/11/19 01:14, and you get a word: `hello`
ZINCRBY counter:201911190114 1 hello

// You get another word in the same minute: `word`
ZINCRBY counter:201911190114 1 hello

// Time passed by...

// Now it's 2019/11/19 01:20, and you get a word: 'hi', insert the word in another counter
ZINCRBY counter:201911190120 1 hi
搜寻 如果要查询过去5分钟内最流行的10个单词,请按当前时间计算这5个计数器的键,然后调用
ZUNIONSTORE
将结果合并为新的合并结果。最后,调用
ZREVRANGE
获取新排序集的前10个成员

// Now it's 2019/11/19 02:05, search for the last 5 minutes' counters
ZUNIONSTORE dest 5 counter:201911190204 counter:201911190203 counter:201911190202 counter:201911190201 counter:201911190200

// Get top 10 words
ZREVRANGE dest 0 9

此外,您可能需要为这些计数器设置过期时间,以避免达到内存限制。

RedisBloom有一个Top-K解决方案,它可能适合您的用例,以防流中有大量不同的字需要计数

在(by me:)中,您可以看到Top-K在执行时间和内存需求方面都优于排序集。在我的工作台上,对于
k=10
,内存消耗小于10kb,而对于一个排序集,内存消耗为6mb。数据集是《战争与和平》一书,共有约500000个单词

我的建议是保留几个Top-K密钥,并在5分钟后将其退役。关键点的数量取决于所需的分辨率


Top-K的另一个很好的特性是,当元素从Top-K列表中被逐出时,您会得到元素。这允许您跟踪趋势。该特性不适用于<代码>排序集 .< /P>该解决方案应该起作用,但是如果您具有高的文本吞吐量并保持所有的字计数器在内存上可能太多,那么您可能需要考虑使用SoeTeSET代替TopK之类的子线性内存概率解决方案。