大规模分布式调度任务队列框架
Frame works for distributed scheduling task queue for a high scale
我需要构建一个系统,该系统每天至少需要创建/安排十万个工作岗位。
我研究了多个任务队列,但没有太多支持以分布式方式进行调度,比如石英,
一个好的解决方案似乎是芹菜(我是 java 人,我不能使用 python),
Akka(这看起来是一个很好的可扩展、持久等解决方案,但调度似乎有限制,比如我需要根据用户请求在一天的不同时间调度 1,00,000 个作业)。akka 新手如有错误请指正
我不需要分布式锁来进行调度,而是需要异步方式的并发。
请提出替代方案。
为 scala/java/javascript 作为一种语言开放。
Quartz 不可扩展(有一些严重的限制),我每天必须发送大约 3 亿条消息,这些消息将通过 1,00,000 个作业交付
如果你担心Akka调度器的准确性,一旦我遇到同样的情况,我会告诉你我的解决方案。也许对于这种情况有更好的做法,但这个对我来说效果很好。我将不胜感激任何改进和建议。我没有在很长的时间间隔内安排工作,而是创建了一个调度 actor,它会向自己发送滴答声,以便知道何时应该执行工作。假设你想安排从日期 A 到日期 B 的一些工作,并且每隔 T 执行一次单位(这可能是从毫秒到年)。然后我的 actor 所做的是安排(使用普通的 Akka 调度程序)恰好在当前时间和它应该执行第一个工作的时间之间的间隔的一半处。这基本上是一个二进制搜索。这样,演员就不会不停地滴答作响,并且会非常准确地在正确的时间执行工作。有关详细信息,请参阅下面的 Java 代码:
public class WorkScheduler extends UntypedActor {
public static Props props(final Date from, final Date to, final long every, final TimeUnit unit) {
return Props.create(new Creator<WorkScheduler>() {
private static final long serialVersionUID = 1L;
@Override
public WorkScheduler create() throws Exception {
return new WorkScheduler(from, to, every, unit);
}
});
}
// Thresholds to avoid ticking at very long (or very short) intervals
private static final long MIN_TICK_DELTA = 1000 // 1 sec.
private static final long MAX_TICK_DELTA = 21600000 // 6 hours
private class Tick extends Message {
}
private long from;
private long to;
private long dt;
private long checkpoint;
public WorkScheduler(Date from, Date to, long every, TimeUnit unit) {
this.from = from.getTime();
this.to = to.getTime();
this.dt = unit.toMillis(every);
}
@Override
public void preStart() throws Exception {
scheduleNextTick(); // The first tick
}
private void scheduleNextTick() {
long t = new Date().getTime();
// Compute next checkpoint
if (t < from) {
checkpoint = from;
} else {
long k = (t - from) / dt;
if ((t - from) % dt != 0) ++k;
checkpoint = from + k * dt;
}
if (checkpoint > to) { // All works executed. Shutdown.
getContext().stop(self());
} else { // Schedule next tick
long delta = Math.max(MIN_TICK_DELTA, Math.min((checkpoint - t) / 2, MAX_TICK_DELTA));
getContext().system().scheduler().scheduleOnce(
FiniteDuration.apply(delta, TimeUnit.MILLISECONDS),
self(),
new Tick(),
getContext().dispatcher(),
null);
}
}
@Override
public void onReceive(Object msg) throws Exception {
if (msg instanceof Tick) {
long t = new Date().getTime();
if (t >= checkpoint) {
if (t >= checkpoint + dt) // Tick came too late, due to some external delay (like system restart)
;
// execute work here, preferably spawning a new actor
// responsible for doing the work in asynchronous fashion
}
scheduleNextTick();
} else
unhandled(msg);
}
}
希望对您有所帮助))
我需要构建一个系统,该系统每天至少需要创建/安排十万个工作岗位。 我研究了多个任务队列,但没有太多支持以分布式方式进行调度,比如石英, 一个好的解决方案似乎是芹菜(我是 java 人,我不能使用 python),
Akka(这看起来是一个很好的可扩展、持久等解决方案,但调度似乎有限制,比如我需要根据用户请求在一天的不同时间调度 1,00,000 个作业)。akka 新手如有错误请指正
我不需要分布式锁来进行调度,而是需要异步方式的并发。 请提出替代方案。 为 scala/java/javascript 作为一种语言开放。
Quartz 不可扩展(有一些严重的限制),我每天必须发送大约 3 亿条消息,这些消息将通过 1,00,000 个作业交付
如果你担心Akka调度器的准确性,一旦我遇到同样的情况,我会告诉你我的解决方案。也许对于这种情况有更好的做法,但这个对我来说效果很好。我将不胜感激任何改进和建议。我没有在很长的时间间隔内安排工作,而是创建了一个调度 actor,它会向自己发送滴答声,以便知道何时应该执行工作。假设你想安排从日期 A 到日期 B 的一些工作,并且每隔 T 执行一次单位(这可能是从毫秒到年)。然后我的 actor 所做的是安排(使用普通的 Akka 调度程序)恰好在当前时间和它应该执行第一个工作的时间之间的间隔的一半处。这基本上是一个二进制搜索。这样,演员就不会不停地滴答作响,并且会非常准确地在正确的时间执行工作。有关详细信息,请参阅下面的 Java 代码:
public class WorkScheduler extends UntypedActor {
public static Props props(final Date from, final Date to, final long every, final TimeUnit unit) {
return Props.create(new Creator<WorkScheduler>() {
private static final long serialVersionUID = 1L;
@Override
public WorkScheduler create() throws Exception {
return new WorkScheduler(from, to, every, unit);
}
});
}
// Thresholds to avoid ticking at very long (or very short) intervals
private static final long MIN_TICK_DELTA = 1000 // 1 sec.
private static final long MAX_TICK_DELTA = 21600000 // 6 hours
private class Tick extends Message {
}
private long from;
private long to;
private long dt;
private long checkpoint;
public WorkScheduler(Date from, Date to, long every, TimeUnit unit) {
this.from = from.getTime();
this.to = to.getTime();
this.dt = unit.toMillis(every);
}
@Override
public void preStart() throws Exception {
scheduleNextTick(); // The first tick
}
private void scheduleNextTick() {
long t = new Date().getTime();
// Compute next checkpoint
if (t < from) {
checkpoint = from;
} else {
long k = (t - from) / dt;
if ((t - from) % dt != 0) ++k;
checkpoint = from + k * dt;
}
if (checkpoint > to) { // All works executed. Shutdown.
getContext().stop(self());
} else { // Schedule next tick
long delta = Math.max(MIN_TICK_DELTA, Math.min((checkpoint - t) / 2, MAX_TICK_DELTA));
getContext().system().scheduler().scheduleOnce(
FiniteDuration.apply(delta, TimeUnit.MILLISECONDS),
self(),
new Tick(),
getContext().dispatcher(),
null);
}
}
@Override
public void onReceive(Object msg) throws Exception {
if (msg instanceof Tick) {
long t = new Date().getTime();
if (t >= checkpoint) {
if (t >= checkpoint + dt) // Tick came too late, due to some external delay (like system restart)
;
// execute work here, preferably spawning a new actor
// responsible for doing the work in asynchronous fashion
}
scheduleNextTick();
} else
unhandled(msg);
}
}
希望对您有所帮助))