从MySQL中选择项目以获得有效的状态更新,同时考虑可能的垃圾邮件

时间:2014-08-20 22:23:17

标签: php mysql algorithm sorting memcached

我正在创建一个"状态更新"用户可以发布可以被其他用户查看的一般消息的Feed(想想facebook,twitter推文等中的状态更新)。首先,在创建帖子并将其保存到数据库时,为每个帖子分配一个等级分数。该等级分数与时间衰减函数相结合用于分配"真实等级"生成订阅源并呈现给用户时每个帖子。这个真正的排名是项目最终排序的方式。

引入战略以打击“垃圾邮件”时出现了复杂性。 (我们不希望用户能够非常快速地发布并且在饲料中占据最高点)。策略是跟踪用户在过去一小时内发布的次数。对于在过去一小时内添加的每个后续帖子,分配的排名分数将受到惩罚。用户在过去一小时内发布的帖子越多,排名得分惩罚越大。这里的想法是将潜在的垃圾邮件进一步推送到Feed中,同时仍然给它一个显示的机会。

以下说明如果我们不考虑垃圾邮件,如果相同的用户快速发布了四个项目后如何对Feed进行排序。

Item 1: Posted 1 min ago. True Rank = 0.99. user_id = 666.
Item 2: Posted 2 min ago. True Rank = 0.98. user_id = 666. SPAM.
Item 3: Posted 3 min ago. True Rank = 0.97. user_id = 666. SPAM.
Item 4: Posted 4 min ago. True Rank = 0.96. user_id = 666. SPAM.
Item 5: Posted 5 min ago. True Rank = 0.95. user_id = 100.
Item 6: Posted 6 min ago. True Rank = 0.94. user_id = 100.

以下是您所期望的。请注意,user_id = 666的帖子会在第一篇帖子后落在Feed上。

Item 1: Posted 1 min ago. True Rank = 0.99. user_id = 666.
Item 5: Posted 5 min ago. True Rank = 0.95. user_id = 100.
Item 6: Posted 6 min ago. True Rank = 0.94. user_id = 100.
Item 2: Posted 2 min ago. True Rank = 0.88. user_id = 666. SPAM.
Item 3: Posted 3 min ago. True Rank = 0.77. user_id = 666. SPAM.
Item 4: Posted 4 min ago. True Rank = 0.66. user_id = 666. SPAM.

问题

我有这样做的策略。如上所述,我跟踪每个用户每小时的帖子数量,并在必要时从排名分数中扣除。这没问题。

当我们考虑如何在每次为用户准备Feed时有效地从数据库中选择项目时,就会出现问题。这是关于性能的。我想一次选择1000个Feed项(最初为1000个,如果用户请求更多,则每个后续获取1000个)。但是如果前1000个项目都是垃圾邮件呢?选择所有项目然后准备Feed在技术上可行,但系统中的项目数量可能非常大。

我很难创建一种算法来为Feed选择项目,而不需要一次大量提取,并且每个Feed项目都有机会显示在Feed上,即使它的排名是非常低。

让用户每小时只发布n个项目的人工解决方案不是一种选择。

对于它的价值,我可以使用的工具是MySQL,Memcached和PHP。

提前感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我认为使读取真正有效的方法是找出何时在INSERT时排除帖子(可能有一个单独的通知表并使用一些速率限制,例如漏桶算法,以确定哪些要排除)。

要做一些接近你想要做的事情,你现在可以做这样的事情http://sqlfiddle.com/#!2/c20ac/8

它说的是“每个帖子中只允许每个用户显示一个帖子”。您必须调整N值(示例中为5)以获得您拥有的数据速率,但它可以很好地处理数据。

功能方面一个更好的版本可能是(如果你存储帖子的时间戳)根据帖子的时间进行划分,以及现在的时间和帖子的时间之间的差异。我认为这会慢一些,因为你要在派生列上进行分组。