redis pub sub和/或列表来实现数据收集器

时间:2016-09-28 13:13:36

标签: java redis queue

我正在研究一个需要按计划从第三方系统收集数据的模块,比如每5分钟一次。

启动数据收集的触发器来自多租户UI。因此,10个租户可以告诉该模块同时开始收集数据。

我开始使用一个简单的redis队列,来自UI的所有启动请求都被发布到队列中,模块充当工作者,获取作业并运行它们。

问题是我们需要在1分钟内完成一个数据收集周期,如果有100个工作岗位,如果我们连续上传,我们将花费超过一分钟的时间。数据收集需要按计划进行。因此,用户界面说每5分钟运行一次数据收集,直到我说停止!

因此,我们添加了另一个可以开始减轻负载的工作者。

我的问题是:如何在不将状态(预定线程执行程序)保留在其中一个工作程序中的情况下实现常规计划?

我是否在考虑这个问题,这可以用更简单的方式完成吗?

我的设计现在有一种cron作业,每隔1分钟从数据库中读取数据收集请求,然后将它们放在工作人员拿起它的队列中。

2 个答案:

答案 0 :(得分:1)

在这种情况下,使用beanstalkd可能是比使用Redis更好的选择。

Beanstalkd与Redis有许多共同点:易于部署,简单,轻便,快速,默认情况下在内存中,通过简单的文本协议完成通信,很多clients in various languages ......但它是专用的对任务管理来说,它不是一个数据库。您可以动态添加或删除工作程序,而无需在beanstalkd方面进行任何配置。

你将工作放入"管#34; (队列的beanstalkd名称),然后工作者可以一次保留它们。一旦它保留了一个工作,一个工人有一个最长的时间来完成它(称为TTR -Time To Run),否则该工作由beanstalkd释放,再次放入管中,因此可能由另一个工人处理。

工作只是一个字符串;例如,它可以是描述要执行的任务的序列化Json。

如果我对您的问题的理解是正确的,那么UI租户可以创建具有正常优先级的作业来开始数据收集,并将它们放入一个独特的管中。一个或几个工人将保留" (拿)这个管子的工作,处理它,删除它以告知beanstalkd它完成了,然后保留另一个工作,等等。

put reserve delete -----> [READY] ---------> [RESERVED] --------> *poof*

(此架构的来源:beanstalkd&#39协议文档)

对于每5分钟重复处理一个没有任何调度程序的作业,你可以说每当一个工人消耗一份工作时,它会创建一个新工作,并使用" put with delay"将豆秆放入管中时的特征。因此,只有在延迟到期时才会向工人展示工作(在您的情况下为5分钟)。

当UI想要取消剩余的作业时,它可以从管中选择和删除所有作业。或者,如果您希望工作人员删除它们,则UI可以将具有比数据收集作业更高优先级的取消作业(将其视为消息)放入管中。你也可以使用另一个管,假设你在另一个线程中听它而不是专门用于数据收集的线程。

我对您的问题的了解和理解显然有限,但您当然可以完善这些想法以解决您的确切问题。

答案 1 :(得分:0)

您的任务可以通过Redisson完成。它提供了由Redis支持的SchedulerService。它还支持cron表达式。用法示例:

public class RunnableTask implements Runnable {

    @RInject
    private RedissonClient redissonClient;

    private Object param;

    public RunnableTask() {
    }

    public RunnableTask(Object param) {
        this.param = param;
    }

    @Override
    public void run() {
        // ... 
    }

}

RScheduledExecutorService executorService = redisson.getExecutorService("myExecutor");
schedule(new RunnableTask(), CronSchedule.of("10 0/5 * * * ?"));

您可以在应用程序中直接运行worker,也可以在独立的Redisson Node中运行它。