假设我想每小时运行一次任务,但是在一小时内的可变时间。它不一定是真正的随机;例如,我只是不想在每小时的最高时间做这件事。我想每小时只做一次。
这消除了几种明显的方法,例如在30到90分钟之间随机睡觉,然后再次睡觉。这项任务可以(很可能)连续几次运行,睡眠时间不超过30分钟。
我正在考虑的方法如下:每小时,哈希一小时的Unix时间戳,并将结果修改为3600.将结果添加到小时的Unix时间戳,这就是任务的时刻应该跑。在伪代码中:
while now = clock.tick; do
// now = a unix timestamp
hour = now - now % 3600;
hash = md5sum(hour);
the_time = hour + hash % 3600;
if now == the_time; then
do_the_work();
end
end
我确信这会满足我的要求,但我认为把这个问题抛出去看看其他人有什么想法会很有趣!
答案 0 :(得分:1)
在接下来的一小时内完成工作,只需在该小时内随机选择一分钟。
也就是说,选择 next 间隔的随机时间来完成工作;如果工作从前一个时间间隔结转,则可能与当前时间间隔(小时)相同(
)。“睡觉的时间”就是直到那时的时间。如果随机时间在此之前,这也可以在结转情况下“立即”执行:这将确保每个小时选择一个随机时间,除非工作时间超过一小时。 / p>
不要让它变得更复杂 - 没有理由在这里使用random
哈希或以其他方式混淆。这就是SharePoint计时器(带有每小时计划)等“企业”解决方案的工作方式。
答案 1 :(得分:0)
安排你的任务(用cron等)在每小时的顶部运行。
在任务开始时,睡眠一段随机时间,从0到(60 - (估计的任务运行时间 + 一个软糖因子< / em>))分钟。
如果您不希望任务同时运行两次,则可以使用pid文件。该任务可以在睡眠后检查此文件并等待当前正在运行的任务完成再重新启动。
答案 2 :(得分:0)
我已经部署了我建议的解决方案并且运行良好。例如,我每分钟一次从我正在监控的进程中采样一些信息,但我会在一分钟内的可变时间进行。我在Go代码中创建了一个名为RandomlyWithin的Timestamp类型的方法,如下所示:
func (t Timestamp) RandomlyWithin(dur Timestamp, entropy ...uint32) Timestamp {
intervalStart := t - t % dur
toHash := uint32(intervalStart)
if len(entropy) > 0 {
toHash += entropy[0]
}
md5hasher.Reset()
md5hasher.Write([]byte{
uint8(toHash >> 24 & 255),
uint8(toHash >> 16 & 255),
uint8(toHash >> 8 & 255),
uint8(toHash & 255)})
randomNum := binary.BigEndian.Uint32(md5hasher.Sum(nil)[0:4])
result := intervalStart + Timestamp(randomNum)%dur
return result
}