Redis Learning notes Ten: Redis as Message Queuing __redis

Source: Internet
Author: User
Tags message queue volatile

Redis can be used not only as a caching server, but also as a message queue. Its list type is inherently supported as a message queue. As shown in the following illustration:


Because the list of Redis is implemented using a two-way link, the root and tail nodes are saved, so inserting elements on both sides of the list is very fast.

So you can use the Redis list to implement Message Queuing with just a simple two instructions Lpush and Rpop or Rpush and Lpop. A simple example is as follows:

Store message side (message producer):

Package org.yamikaze.redis.messsage.queue;
Import Org.yamikaze.redis.test.MyJedisFactory;

Import Redis.clients.jedis.Jedis;

Import Java.util.concurrent.TimeUnit; /** * Message producer * @author Yamikaze/public class Producer extends Thread {public static final String Message_key =
    "Message:queue";
    Private Jedis Jedis;
    Private String Producername;

    private volatile int count;
        Public Producer (String name) {this.producername = name;
    Init ();
    private void Init () {Jedis = Myjedisfactory.getlocaljedis ();
        public void Putmessage (String message) {Long size = Jedis.lpush (message_key, message);
        System.out.println (Producername + ": Currently not processed Message Bar number is:" + size);
    count++;
    public int GetCount () {return count; @Override public void Run () {try {a while (true) {Putmessage (STRINGUTILS.G
                Enerate32str ());
    TimeUnit.SECONDS.sleep (1);        The catch (Interruptedexception e) {} catch (Exception e) {e.printstacktrace (); }} public static void Main (string[] args) throws interruptedexception{Producer = new Pro
        Ducer ("Myproducer");

        Producer.start (); for (;;)
            {System.out.println ("main: Number of messages stored:" + producer.getcount ());
        TimeUnit.SECONDS.sleep (10);
 }
    }
}

Message processing end (message consumer):

Package org.yamikaze.redis.messsage.queue;
Import Org.yamikaze.redis.test.MyJedisFactory;

Import Redis.clients.jedis.Jedis;
    /** * Message Consumer * @author Yamikaze/public class Customer extends thread{private String customerName;
    private volatile int count;

    Private Jedis Jedis;
        Public Customer (String name) {this.customername = name;
    Init ();
    private void Init () {Jedis = Myjedisfactory.getlocaljedis ();
        public void ProcessMessage () {String message = Jedis.rpop (Producer.message_key);
            if (message!= null) {count++;
        handle (message); The public void handle (String message) {System.out.println (customerName +) is processing a message that reads: "+ messages +
    "This is the first" + Count + "bar");
        @Override public void Run () {while (true) {ProcessMessage (); } public static void Main (string[] args) {Customer customer = new Customer ("YamikAze ");
    Customer.start ();
 }
}
But there is a problem with the message consumers in the above example, that is, to call the Rpop method constantly to see if a message is pending in the list. A connection is initiated once per call, which can cause unnecessary waste. Perhaps you will use Thread.Sleep () and so on to allow the consumer thread to spend some time, but there are two problems:

1, if the producer speed is greater than consumer consumption speed, message queue length will be increased, time will occupy a lot of memory space.

2, if the sleep time is too long, this can not handle some timeliness of the message, sleep time is too short, will also cause a relatively large connection overhead.

So you can use the BRPOP directive, which returns only when there are elements, and no blocks until the timeout returns null, so the consumer can change the processmessage to this way:

The public void ProcessMessage () {
    /**
     * Brpop supports multiple lists (queues)
     * Brpop Directives support queue precedence, such as in this example Message_ Key priority is greater than testkey (sequential decision).
     * If there are elements in the two list, priority will be given to the elements in the high priority list, so here's the priority return Message_key
     * 0 means that there is no limit to waiting, blocking here/
    list<string> Messages = Jedis.brpop (0, Producer.message_key, "TestKey");
    if (messages.size ()!= 0) {
        //Since the instruction can listen for multiple keys, it returns a list
        //list consisting of 2 items, 1) list name, 2 data
        String KeyName = Messages.get (0);
        If the Message_key message is returned if
        (Producer.MESSAGE_KEY.equals (KeyName)) {
            String messages = Messages.get (1);
            handle (message);
        }
    System.out.println ("=======================");
}
Then you can run the customer, empty the console, and you can see that the program has no output, blocking the brpop here. Then, on the client that opens the Redis, enter the command client list to see that there are currently two connections.

Publish/Subscribe modeIn addition to providing support for Message Queuing, Redis provides a set of commands to support the Publish/subscribe model. 1 Publish PUBLISH instructions can be used to publish a message, format PUBLISH channel messages
The return value indicates the number of subscriptions to the message. 2 The subscription SUBSCRIBE instruction is used to receive a message, the format SUBSCRIBE channel
You can see that you have entered the subscription mode with the Subscribe directive, but you have not received the message sent by publish because the subscription will not be received until the message is sent. In this mode the other instructions only see the reply. The reply is divided into three types: 1, if it is subscribe, the second value represents the subscribed channel, and the third value represents the first few subscribed channels?      (understood as serial number?) 2, if the message (messages), the second value is the channel that generates the message, the third value is message 3, if unsubscribe, the second value represents the unsubscribe channel, and the third value represents the number of subscriptions for the current client.
You can use the directive unsubscribe unsubscribe, if not the parameter, will unsubscribe all by the subscribe instruction subscription channel. Redis also supports message subscriptions based on wildcard characters, using instruction Psubscribe (pattern subscribe), for example:
Try the push message again to get the following results:
You can see that the publish instruction returns 2, and the Subscriber side receives two messages. This is because the psubscribe instruction can repeat the subscription channel. And the use of psubscribe instructions to subscribe to the channel to use the directive Punsubscribe instructions to unsubscribe, the directive can not unsubscribe subscribe subscription channels, the same unsubscribe can not unsubscribe from the Psubscribe instructions to subscribe to the channel. The punsubscribe instruction wildcard character does not expand. For example: Punsubscribe * does not match to channel.*, so to unsubscribe channel.* write Pubsubscribe channel.*.
The code model is as follows:

Package org.yamikaze.redis.messsage.subscribe;

Import Org.yamikaze.redis.messsage.queue.StringUtils;
Import org.yamikaze.redis.test.MyJedisFactory;
Import Redis.clients.jedis.Jedis;

/**
 * Message publisher
 * @author Yamikaze */public
class Publisher {public

    static final String Channel_key = "C Hannel:message ";
    Private Jedis Jedis;

    Public Publisher () {
        Jedis = Myjedisfactory.getlocaljedis ();
    }

    public void PublishMessage (String message) {
        if (Stringutils.isblank) {return
            ;
        }
        Jedis.publish (channel_key, message);

    public static void Main (string[] args) {
        Publisher publisher = new publisher ();
        Publisher.publishmessage ("Hello redis!");
    }

Simple to send a message. Message subscribers:
Package org.yamikaze.redis.messsage.subscribe;
Import Org.yamikaze.redis.test.MyJedisFactory;
Import Redis.clients.jedis.Jedis;

Import Redis.clients.jedis.JedisPubSub;

Import Java.util.concurrent.TimeUnit;
    /** * Message Subscriber Client * @author Yamikaze */public class Subscribeclient {private Jedis Jedis;

    private static final String Exit_command = "EXIT";
    Public subscribeclient () {Jedis = Myjedisfactory.getlocaljedis (); public void Subscribe (String ... channel) {if (channel = null | | channel.length <= 0) {Retu
        Rn //message processing, how to handle jedispubsub JPS = new Jedispubsub () {/** * Jedispubsub class is a No Abstract methods of abstract classes, inside the method are some empty implementation * so you can choose the required method overlay, where the use of subscribe instructions, so covered onmessage * If the psubscribe instruction is used, then overwrite ONPM Essage method * Of course, you can also choose Binaryjedispubsub, the same abstract class, but the method parameter is byte[] * * * @Override Pub
  LIC void OnMessage (String channel, String message) {              if (Publisher.CHANNEL_KEY.equals (CHANNEL)) {System.out.println ("received message: CHANNEL:" + mes
                    SAGE);
                    Exit if (exit_command.equals) {system.exit (0) after receiving the exit message;
            }}/** * * When subscribing/@Override public void Onsubscribe (String channel, int subscribedchannels) {if (Publisher.CHANNEL_KEY.equals (
                Channel)) {System.out.println ("Subscribe to Channel:" + channel);
        }
            }
        };
    You can subscribe to multiple channels the current thread will block here Jedis.subscribe (JPS, channel);
        public static void Main (string[] args) {subscribeclient client = new Subscribeclient ();
        Client.subscribe (Publisher.channel_key); There is no unsubscribe method//corresponding and no Punsubscribe method}}
Run the client first, then run Publisher to send the message and output the results:

Summary: Using the Redis list data structure can be a simple and rapid Message Queuing, while Redis provided Brpop and Blpop and other directives to solve the frequent calls Jedis Rpop and Lpop methods caused by waste of resources. In addition, Redis provides instructions for the Publish/subscribe mode, which enables message delivery, interprocess communication.
Reference to the Redis Getting Started Guide
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.