使用Redis的简单消息队列

在本文中,我们将使用列表命令将Redis用作简单的消息队列。

假设我们有一个允许用户上传照片的应用程序。 然后在应用程序中,我们以不同大小显示照片,例如Thumb,Medium和Large。

在第一个实现中,我们可以承担在同一请求中处理上载图像的任务。 由于这是一项昂贵的任务,因此会使我们的请求变慢。

一个可能的解决方案是使用消息队列(MQ)使该处理异步进行,有许多众所周知的MQ,例如ActiveMQ,RabbitMQ,IBM MQ等。 在下面的示例中,我们将使用LIST结构将Redis用作消息队列。

这个想法是要有一个LIST,生产者将在其中放置要处理的消息,而某些消费者将观看LIST以处理发送的消息。

基本上,生产者将使用“ RPUSH队列消息 ”将消息添加到列表的末尾,而消费者将使用“ LPOP队列 ”将列表开头的消息配置为FIFO处理。

客户端将一直在寻找新消息,为此,我们将使用BLPOP命令,该命令是LPOP命令的阻止版本。 基本上会有一个while循环调用BLPOP来处理新消息。

考虑到图像上传的示例,假设我们有一个ImageUploader类,负责将图像上传到服务器,它将在队列中添加一条新消息,指示有要处理的图像,消息可能是JSON字符串像这样:

{“imagePath”:”/path/to/image”, “user”:”userid”}

ImageUploder类可能是这样的:

public class ImageUploader {

  public void uploadImage(HttpServletRequest request){

    String imagePath = saveImage(request);
    String jsonPayload = createJsonPayload(request, imagePath);
    jedis.rpush("queue", jsonPayload);
    //... keep with the processing
  }

  //.... other methods in the class
}

这只是生产者如何工作的一个例子。 在这种情况下,我们已经将图像处理与ImageUploader类分离了。 我们只是在队列中创建一条新消息,以便使用者处理它们。

消息使用者可能是这样的:

package br.com.xicojunior.redistest;

import java.util.List;

import redis.clients.jedis.Jedis;

public class MessageConsumer 
{
    public static void main( String[] args )
    {
        Jedis jedis = new Jedis("localhost");   
        List<String> messages = null;
        while(true){
          System.out.println("Waiting for a message in the queue");
          messages = jedis.blpop(0,"queue");
          System.out.println("Got the message");
          System.out.println("KEY:" + messages.get(0) + " VALUE:" + messages.get(1));
          String payload = messages.get(1);
          //Do some processing with the payload
          System.out.println("Message received:" + payload);
        }

    }
}

此使用者代码可以在不同的进程甚至不同的机器上运行。 这个使用者代码是可运行的,我们可以编译它并使用eclipse或java命令运行它。

对于此代码,我们使用jedis.blpop方法,它返回包含2个字符串的列表,(0)–关键字,(1)–返回的值。 该方法还接收一个整数,它表示超时。 我们传递了0表示没有超时。

当我们运行此代码并且列表中没有值时,在控制台中,我们将仅看到消息

"Waiting for a message in the queue".

然后,如果客户在“队列”列表中添加元素,我们的消费者类将获得其价值。 我们可以通过使用redis-cli或什至另一个将在队列中添加元素的类来模拟测试,如下所示:

package br.com.xicojunior.redistest;

import redis.clients.jedis.Jedis;

public class MessageProducer {

  public static void main(String[] args) {
    Jedis jedis = new Jedis("localhost");

    jedis.rpush("queue", "Value 1");
    jedis.rpush("queue", "Value 2");
    jedis.rpush("queue", "Value 3");

  }

}

如果我们在MessageConsumer类已经运行之后运行MessageProducer类,我们将在控制台中看到以下输出:

Waiting for a message in the queue
Got the message
KEY:queue VALUE:Value 1
Message received:Value 1
Waiting for a message in the queue
Got the message
KEY:queue VALUE:Value 2
Message received:Value 2
Waiting for a message in the queue
Got the message
KEY:queue VALUE:Value 3
Message received:Value 3
Waiting for a message in the queue

因此,消息队列将是Redis的另一个可能的用例。 在redis之上建立了一些队列,如RestMQResque – Job Queue等。

参考: XICO JUNIOR'S WEBLOG博客中来自JCG合作伙伴 Francisco Ribeiro Junior的使用Redis的简单消息队列

翻译自: https://www.javacodegeeks.com/2014/01/simple-message-queue-using-redis.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值