Home Java JavaInterview questions [Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

Jul 26, 2023 pm 02:58 PM
interview


[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

I. Introduction

Our friends should have heard enough about the message middleware MQ, such as: RabbitMQ, RocketMQ, Kafka, etc. The benefits of introducing middleware can play a role in resisting high concurrency, peaking, and business decoupling.

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

As shown above:

(1) The order service delivers messages to MQ middleware (2) The logistics service monitors MQ middleware messages for consumption

In this article, we discuss how to ensure that the order service successfully delivers the message to the MQ middleware, taking RabbitMQ as an example.

2. Analysis of the problem

Friends may have some questions about this. If the order service initiates the message service and the return is successful, wouldn’t it mean success? ? For example, the following pseudo code:

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

In the above code, messages are generally sent like this. Do you guys think there is any problem?

Let’s talk about a scenario. What will happen if the MQ server suddenly goes down? Are all the messages sent by our order service gone? Yes, generally MQ middleware will save messages in memory in order to improve the throughput of the system. If no other processing is done, once the MQ server goes down, all messages will be lost. This is not allowed by the business and will cause a great impact.

3. Persistence

Experienced friends will say that I know one way is to persist the message and send the message in RabbitMQ There will be a durable parameter that can be set. If it is set to true, it will be persistent.

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

In this case, even if the MQ server goes down, the message will be stored in the disk file after restarting, so that it will not be lost. Yes, this ensures that the message will not be lost with a certain probability.

But there will be a scenario where the message has just been saved to the MQ memory, but before it has time to be updated to the disk file, it suddenly crashes. (Holy crap, this will happen in such a short period of time. The probability is too low.) This scenario will be very common in the process of continuous large-scale message delivery.

What should we do? How can we ensure that it will be persisted to the disk?

4. Confirm mechanism

The above problem arises from the fact that no one tells us whether persistence is successful. Fortunately, many MQs have callback notification features, and RabbitMQ has a confirm mechanism to notify us whether persistence is successful?

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

Principle of the confirm mechanism:

(1) The message producer sends the message to MQ. If the reception is successful, MQ will return an ack message to the producer ;

(2) If the message reception is unsuccessful, MQ will return a nack message to the producer;

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

The above pseudocode has two ways to process the message , which are ack callback and nack callback.

Does this ensure that 100% of the messages will not be lost?

Let’s take a look at the confirm mechanism. Imagine if every time our producer sends a message, MQ must be persisted to the disk, and then initiate an ack or nack callback. In this case, the throughput of our MQ is very low, because the message must be persisted to the disk every time. Writing to disk is very slow. This is unacceptable in high concurrency scenarios, and the throughput is too low.

So the actual implementation of MQ persistent disk is processed through asynchronous calls. It has a certain mechanism. For example, when there are thousands of messages, it will be flushed to the disk at once. Instead of flushing the disk every time a message comes.

So the comfirm mechanism is actually an asynchronous listening mechanism, which is to ensure the high throughput of the system. This means that it is still not 100% guaranteed that the message will not be lost, because even if the confirm mechanism is added, the message will not be lost. MQ crashed before the memory was flushed to the disk, and it still couldn't be processed.

After saying so much, I still can’t guarantee it, so what should I do? ? ?

5. Message persistence in advance Scheduled tasks

In fact, the essential reason is that it is impossible to determine whether it is persisted? So can we make the message persistent ourselves? The answer is yes, our plan will evolve further.

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

The process in the above picture:

(1) Before the order service producer delivers the message, it should persist the message to Redis or DB. It is recommended that Redis ,high performance. The status of the message is Sending.

(2) Is the confirm mechanism monitoring message sent successfully? If the ack is successful, delete this message in Redis.

(3) If nack fails, you can choose whether to resend the message according to your own business. You can also delete this message, depending on your business decision.

(4) A scheduled task is added here to pull the message after a certain period of time. The message status is still sending. This status indicates that the order service has not received the ack success message.

(5) Scheduled tasks will deliver compensatory messages. At this time, if the MQ callback ack is successfully received, the message will be deleted in Redis.

Such a mechanism is actually a compensation mechanism. I don’t care whether MQ actually receives it or not. As long as the message status in my Redis is [Sending], it means that the message was not successfully received correctly. Delivery. Then start the scheduled task to monitor and initiate compensation delivery.

Of course, we can also add a compensation number for the scheduled task. If it is more than 3 times and the ack message is still not received, then directly set the status of the message to [Failed] and let it be checked manually. Why?

In this case, the solution is relatively perfect, ensuring that 100% of the messages are not lost (of course, it does not include the disk failure, so you can use a master-slave solution).

However, with this solution, it is possible to send the same message multiple times. It is very likely that MQ has already received the message, but there was a network failure during the callback of the ack message, and the producer did not receive it.

Then we must require consumers to ensure idempotence when consuming!

6. The meaning of idempotence

Let’s first understand what idempotence is? In distributed applications, idempotence is very important, that is, if a business is operated under the same conditions, the result will be the same no matter how many times it is performed.

6.1. Why is there such a scenario as idempotent?

Why is there such a scenario as idempotent? Because in large systems, they are all deployed in a distributed manner. For example, order business and inventory business may be deployed independently and are separate services. When a user places an order, the order service and inventory service will be called.

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

Due to distributed deployment, it is very likely that when calling the inventory service, the order service call fails due to network and other reasons, but in fact the inventory service has been processed and only appears when the processing result is returned to the order service. Exception. At this time, the system will generally make a compensation plan, that is, the order service will then place a call to the inventory service, and the inventory will be reduced by 1.

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

#There is a problem. In fact, the last call has been reduced by 1, but the order service has not received the processing result. Now it is called again, and it needs to be reduced by 1. This is not in line with the business, and it is an extra deduction.

The concept of idempotence is that no matter how many times the inventory service is called under the same conditions, the processing result will be the same. Only in this way can the feasibility of the compensation plan be ensured.

6.2. Optimistic locking scheme

Learn from the optimistic locking mechanism of the database, such as:

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?

Based on the version, that is, get the version number of the current product before operating the inventory, and then bring this version number with you when operating. Let's sort it out. When we operated the inventory for the first time, we got version 1, and when we called the inventory service, the version became 2; but there was a problem when returning to the order service. The order service initiated another call to the inventory service. When the order service passed as The version is still 1, and when the above SQL statement is executed again, it will not be executed; because the version has changed to 2, the where condition does not hold. This ensures that no matter how many times it is called, it will only be processed once.

6.3. Unique ID fingerprint code

The principle is to use the database primary key to remove duplication, and insert the primary key identification after the business is completed

[Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?
  • The unique ID is the only primary key of the business table, such as product ID

  • The fingerprint code is to distinguish the code for each normal operation. The fingerprint code is generated for each operation; the time stamp business number can be used.

The above sql statement:

  • If the return value is 0, it means no operation has been performed, then it can be done after the business operation insert into t_check (unique ID fingerprint code)

  • Return If it is greater than 0, it means the operation has been performed, then return directly

Benefits: Simple implementation

Disadvantages: Database bottleneck under high concurrency

Solution: Split databases and tables based on ID for algorithm routing

6.4, Redis atomic operation

Use the atomic operation of redis to mark the completion of the operation. This performance is better. But there will be some problems.

First: Do we need to store the business results in the database? If so, the key problem to solve is how to achieve atomicity in database and redis operations?

This means that the inventory is reduced by 1, but what should I do if it fails when the redis operation completes the mark? That is to say, we must ensure that the database drop and redis either succeed or fail together

Second: If the database is not dropped, then both are stored in the cache. How to set the scheduled synchronization strategy?

This means that the inventory is reduced by 1, and the inventory is not dropped. The redis operation is directly performed to complete the marking, and then another synchronization service is used to drop the inventory. This increases the complexity of the system and the synchronization strategy. How to set up

The above is the detailed content of [Interview] How to ensure 100% successful delivery of messages? How to ensure message idempotence?. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Let's talk about how to choose the best Node.js Docker image? Let's talk about how to choose the best Node.js Docker image? Dec 13, 2022 pm 08:00 PM

Choosing a Docker image for Node may seem like a trivial matter, but the size and potential vulnerabilities of the image can have a significant impact on your CI/CD process and security. So how do we choose the best Node.js Docker image?

How to solve cross-domain issues? A brief analysis of common solutions How to solve cross-domain issues? A brief analysis of common solutions Apr 25, 2023 pm 07:57 PM

Cross-domain is a scenario often encountered in development, and it is also an issue often discussed in interviews. Mastering common cross-domain solutions and the principles behind them can not only improve our development efficiency, but also perform better in interviews.

Golang framework interview questions collection Golang framework interview questions collection Jun 02, 2024 pm 09:37 PM

The Go framework is a set of components that extend Go's built-in libraries, providing pre-built functionality (such as web development and database operations). Popular Go frameworks include Gin (web development), GORM (database operations), and RESTful (API management). Middleware is an interceptor pattern in the HTTP request processing chain and is used to add functionality such as authentication or request logging without modifying the handler. Session management maintains session status by storing user data. You can use gorilla/sessions to manage sessions.

One article to understand the singleton pattern in JavaScript One article to understand the singleton pattern in JavaScript Apr 25, 2023 pm 07:53 PM

The JS singleton pattern is a commonly used design pattern that ensures that a class has only one instance. This mode is mainly used to manage global variables to avoid naming conflicts and repeated loading. It can also reduce memory usage and improve code maintainability and scalability.

How does JavaScript determine data type? 8 ways to share How does JavaScript determine data type? 8 ways to share Feb 16, 2023 pm 02:48 PM

How does JavaScript determine data type? This article will share with you 8 ways to use JS to determine data type, which can effectively help work and interviews. The interviewer smiled slightly after reading it.

Selected Java JPA interview questions: Test your mastery of the persistence framework Selected Java JPA interview questions: Test your mastery of the persistence framework Feb 19, 2024 pm 09:12 PM

What is JPA? How is it different from JDBC? JPA (JavaPersistence API) is a standard interface for object-relational mapping (ORM), which allows Java developers to use familiar Java objects to operate databases without writing SQL queries directly against the database. JDBC (JavaDatabaseConnectivity) is Java's standard API for connecting to databases. It requires developers to use SQL statements to operate the database. JPA encapsulates JDBC, provides a more convenient and higher-level API for object-relational mapping, and simplifies data access operations. In JPA, what is an entity? entity

Let's talk about the url module and querystring module in Node Let's talk about the url module and querystring module in Node Feb 23, 2023 pm 07:39 PM

The url module and querystring module are two very important URL processing modules. It is often used when developing node servers.

How to conduct an interview to 'hire' ChatGPT coder? How to conduct an interview to 'hire' ChatGPT coder? Apr 12, 2023 pm 10:25 PM

Translator | Planning by Zhu Xianzhong | Xu Jiecheng Unlike other software development tools that developers trust, AI tools have some unique risks in terms of training, construction, hosting, and usage. Since the release of ChatGPT at the end of 2022, the Internet has been filled with arguments supporting and doubting it in almost equal proportions. Whether you like it or not, AI is making its way into your development organization. Even if you don’t plan to develop an AI product or leverage an AI tool to write the code for you, it may still be integrated into the tools and platforms used to build, test, and run source code. AI tools present some unique risks that may impact the productivity gains from automating tasks. These risks are mainly

See all articles