Message queue and delayed message queue

Application scenarios

1. Commodity spike

Explosive user requests occur in a short period of time. If relevant measures are not taken, the server will be overwhelmed, and the response timeout problem will lead to service suspended animation, and at worst, the server will go down directly.

At this time, a message queue is added. After the server receives all requests from the user, it first writes all these requests into the message queue and then queues them for processing, so that it will not cause multiple requests to be processed at the same time; if the message queue length exceeds The maximum number that can be carried, then we can abandon the current user’s request and notify the front-end user of "the page has gone wrong, please refresh" and other prompts, so that there will be a better interactive experience.

2. System decoupling

After using the message queue, we can modularize the business functions of the system and realize the decoupling of the system.

Product requirements are constantly changing. At this time, we thought of using message queues to achieve system decoupling. The realization of each function is independent. Only a subscribe or unsubscribe switch is needed. When you need to add features, you only need to open it. Just subscribe to the "complete user information" queue. If you don't use it in two days, just turn off the subscription switch.

3. Logging

General practice: user request-(handle user request, record log (to be completed))-reply to the front desk

Use message queue: user request-processing user request-put in the message queue, directly reply to the front desk

Messaging Middleware-RabbitMQ

At present, the most commonly used MQ (Message Queue, message queue) middleware on the market are RabbitMQ, Kafka, RocketMQ. If it is a lightweight message queue, you can use the message queue provided by Redis.

Important concepts

Producer: The creator of the message, responsible for creating and pushing data to the server

Consumer: The recipient of the message, used to process data and confirm the message

Agent: RabbitMQ service itself, it is used to play the role of "express", because it does not produce messages, but only plays the role of "express", temporary storage and delivery of messages.

Processing flow chart

Insert picture description here

advantage:

Supports persistence, RabbitMQ supports disk persistence function to ensure that messages will not be lost;
high concurrency, RabbitMQ uses Erlang development language, Erlang is a language developed for telephone exchanges, it is born with high parallel light ring and high availability features;
support distribution Because of the implementation of Erlang language, RabbitMQ cluster deployment is also very simple. You only need to start each node and use --link to add the node to the cluster, and RabbitMQ supports automatic master selection and automatic disaster recovery;
Support multiple languages, such as Java, .NET, PHP, Python, JavaScript, Ruby, Go, etc.;
support message confirmation, support message consumption confirmation (ack) to ensure that each message can be consumed normally;
it supports many plug-ins, such as web pages The console message management plug-in, message delay plug-in, etc., RabbitMQ has many plug-ins and they are very convenient to use.

Message type:

direct (default type) mode, this mode is a one-to-one sending mode, that is, a message will only be sent to one consumer; the
headers mode allows you to match the header of the message instead of the routing key (RoutingKey), in addition The use of headers and direct is exactly the same, but because the performance of header matching is very poor, it is almost never used;
fanout mode, which is a multicast method, will distribute a message to all subscribers;
topic mode, which is topic subscription The pattern allows the use of wildcards (#, *) to match one or more messages. I can use "cn.mq.#" to match multiple messages with the prefix "cn.mq.xxx", such as "cn. mq.rabbit", "cn.mq.kafka" and other messages.

Custom message queue

We can use Queue to implement message queues. Queues can be roughly divided into the following three categories:

Deque

It is a subclass of Queue and a supplementary class of Queue. The head and tail support the insertion and acquisition of elements

Blocking queue refers to the element operation (add or delete), if it is not successful, it will block waiting for execution. For example, when adding an element, if the queue element is full, the queue will block and wait until there is a space to insert;
non-blocking Queue, in contrast to blocking queue, will directly return the result of the operation, instead of blocking waiting operation, deque also belongs to non-blocking queue.

Custom message queue code block

import java.util.LinkedList;
import java.util.Queue;

public class CustomQueue {
    
    
    private static Queue<String> queue=new LinkedList<>();

    public static void main(String[] args) {
    
    
        producer();
        consumer();
    }
    //生产者
    public static void producer(){
    
    
        queue.add("first-message");
        queue.add("second-message");
        queue.add("third-message");
    }
    //消费者
    public static void consumer(){
    
    
        while (!queue.isEmpty())
        {
    
    
            System.out.println(queue.poll());
        }
    }
}

first-message
second-message
third-message

Custom delay queue

import lombok.Getter;
import lombok.Setter;

import java.text.DateFormat;
import java.util.Date;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class CustomDelayQueue {
    
    
    private static DelayQueue queue=new DelayQueue();

    public static void main(String[] args) throws InterruptedException {
    
    
        producer();
        consumer();
    }
    //生产者
    public static void producer(){
    
    
        queue.add(new MyDelay(3000,"first-message"));
        queue.add(new MyDelay(1000,"second-message"));

    }
    //消费者
    public static void consumer() throws InterruptedException {
    
    
        System.out.println("开始执行时间:"+DateFormat.getDateTimeInstance().format(new Date()));
        while (!queue.isEmpty())
        {
    
    
            System.out.println(queue.take());
        }
        System.out.println("结束执行时间:"+DateFormat.getDateTimeInstance().format(new Date()));
    }
    //

    static class MyDelay implements Delayed{
    
    
        long delayTime=System.currentTimeMillis();

        @Getter
        @Setter
        private String msg;

        public MyDelay(long delayTime,String msg)
        {
    
    
            this.delayTime=(this.delayTime+delayTime);
            this.msg=msg;
        }

        @Override
        public long getDelay(TimeUnit unit) {
    
    
            return unit.convert(delayTime-System.currentTimeMillis(),TimeUnit.MILLISECONDS);
        }

        @Override
        public int compareTo(Delayed o) {
    
    
           if(this.getDelay(TimeUnit.MILLISECONDS)>o.getDelay(TimeUnit.MILLISECONDS))
               return 1;
           else if(this.getDelay(TimeUnit.MILLISECONDS)<o.getDelay(TimeUnit.MILLISECONDS))
               return -1;
           else return 0;
        }

        @Override
        public String toString() {
    
    
            return this.msg;
        }
    }
}

Start execution time: 2020-12-28 19:41:20
second-message
first-message
End execution time: 2020-12-28 19:41:23

Guess you like

Origin blog.csdn.net/tangshuai96/article/details/111874370