【问题标题】:Is there a way to simulate python random.shuffle of a queue using a pseudorandom sequence or hash function?有没有办法使用伪随机序列或散列函数模拟队列的 python random.shuffle?
【发布时间】:2012-07-26 14:26:20
【问题描述】:

我正在构建一个基于任务队列的应用程序:它为多个异步连接的客户端提供一系列任务。不同的是,任务必须以随机顺序提供

我的问题是我现在使用的算法计算量很大,因为它依赖于许多大型查询和数据库传输。我有一种强烈的预感,有一种更便宜的方法可以达到相同的结果,但我看不到解决方案。你能想出一个聪明的办法来解决这个问题吗?

这是我现在使用的(计算成本高的)算法:

当客户端查询新任务时...

  1. 在数据库中查询“未完成”任务
  2. 将所有任务放在一个列表中
  3. 随机播放列表(使用 random.shuffle)
  4. 将第一个任务标记为“进行中”
  5. 将任务参数发送给客户端完成

当客户端完成任务时...

6a。记录结果并将任务标记为“已完成”。

如果客户未能在某个截止日期前完成任务...

6b。将任务重新标记为“未完成”。

似乎我们可以通过将步骤 1、2 和 3 替换为伪随机序列或哈希函数来做得更好。但我无法完全弄清楚整个解决方案。想法?

其他注意事项:

  • 如果它很重要,我将使用 python 和 mongodb 来完成所有这些。 (Mongodb 没有一些巧妙的“使用 find_one 有效地返回随机匹配条目”的用法,是吗?)
  • “队列”一词有点误导。所有任务都存储在 mongodb 中单个集合的子字段中。集合中的长度(任务总数)在一开始就已知且固定。
  • 如有必要,可以多次分配同一任务,只要这种情况很少发生。但这种情况需要非常少见,因为完成每项任务的成本都很高。
  • 我拥有每个客户的身份信息,因此我们可以准确地知道每个任务请求的发起人。

【问题讨论】:

  • 如果是列表,为什么不生成一个介于 0 和列表大小之间的随机数并将其用作随机索引呢?这样你就不会洗牌。另外,我不确定 mongodb 是否在这方面,但也许您甚至可以通过以下两种方式之一仅查询单个元素:如果 mongodb 支持它,让它随机选择一个。如果没有,请获取列表中的所有标识符并随机选择一个(也许您可以缓存它以缓解数据库压力?)。
  • 这适用于第一个任务,但在第二个任务中,随机数有可能与之前选择的随机数相同。随着越来越多的任务被完成,冗余拣货的概率越来越高。
  • 数据库是否为每个任务分配一个唯一的数值,每个值都必须分配(有点像数组)?例如。长度为 5 的列表将具有索引 0-4(如果您的数组基于 1,则索引为 1-5)
  • 我不知道您到底指的是什么,但是您不能将查询限制为仅完成的查询吗?并从您保留的任何列表中删除对已完成的引用的引用(例如,如果您创建 ID 缓存,则删除已完成的 ID,可以使用列表轻松完成)。

标签: python algorithm mongodb random hash


【解决方案1】:

一种从 MongoDB 获取随机文档的简单方法!

Random record from MongoDB

如果您不希望某个任务被选中两次,您可以将该任务标记为活动而不选择它。

【讨论】:

  • 哦哦哦!它是否适用于文档的子元素?在我的 mongodb 模式中,我有一个“队列”集合;每个队列都是一个文档;每个任务都是一个子文档。
  • 有些答案可能。但是重读您的帖子,就会出现一个问题:为什么任务必须以随机顺序执行?
  • 好问题。这是一个安全问题:并非我所有的客户都值得信赖。在某些情况下,通过比较来自不同客户端的相关任务来验证任务。以随机顺序服务任务使得不同客户端很难串通返回无效结果。
  • 这个解决方案并不完美,从阅读 cmets 可以看出。看起来 MongoDB 团队最终可能会实现随机匹配的查询功能。
【解决方案2】:

啊,根据我错过的 cmets,您可以按照以下方式做一些事情:

import random
available = range(lengthofdatabase)
inprogress = []
while len(available) > 0:
    taskindex = available.pop(random.randrange(0, len(available)))
    # I'm not sure of your implementation, but you said something 
    # along these lines was possible
    task = GetTask(taskindex)
    inprogress.append(taskindex)

我不确定您使用的任何功能 - 这只是一种算法。

编码愉快!

【讨论】:

    猜你喜欢
    • 2013-05-20
    • 1970-01-01
    • 2014-04-12
    • 2016-10-17
    • 1970-01-01
    • 2012-09-09
    • 2015-12-22
    • 2021-07-14
    • 2010-09-09
    相关资源
    最近更新 更多