Meituan Interviewer: How to realize the function that the order will be automatically closed if the order is not paid for a period of time after the order is generated? The more detailed the better~

Business scene

Let's take the order function as an example to illustrate: the order will be automatically closed if it is not paid for a period of time after the order is generated. The simplest idea is to set up polling for timed tasks, but the creation time of each order is different, and the rules for timed tasks cannot be set. If the execution interval of timed tasks is set too short, it will affect efficiency too much. Another idea is to judge the time to perform related operations when the user enters the order interface. There may be many ways, here is a way to monitor the expiration time of Redis key-value pairs to automatically close the order. Compile a complete PDF of the Java Interview Collection

Realization idea

When generating an order, add a KV key-value pair to Redis, where K is the order number, to ensure that an order in the database can be located through K, and V can be any value. Suppose that when the order is generated, K is the order number and V is the key-value pair of the order number, and the expiration time is set to 30 minutes. If the key-value pair expires after 30 minutes, a notification can be sent to the program, or Implement a method, then the order closing problem can be solved. Implementation: It is implemented by monitoring the expiration queue provided by Redis. After monitoring the expiration queue, if a KV key-value pair in Redis expires, then a message will be sent to the listener, and the listener can get the K of the key-value pair. Note , V cannot be obtained because it has expired. This is the reason mentioned above, why it is necessary to ensure that the order can be located through K, and V can be any value. After getting K, locate the order through K and determine its status. If it is unpaid, update it to closed or cancel the status.

Enable Redis key expiration reminder

Modify the configuration of redis related events. Find the redis configuration file redis.conf, check the notify-keyspace-events configuration item, if not, add notify-keyspace-events Ex, if there is a value, add Ex, the related parameters are described as follows:

  • K: keyspace event, the event is published with keyspace@ as the prefix

  • E: keyevent event, the event is published with keyevent@ as the prefix

  • g: general, non-specific commands, such as del, expire, rename, etc.

  • $: string specific commands

  • l: List specific commands

  • s: set specific commands

  • h: Hash specific commands

  • z: ordered set specific commands

  • x: Expiration event, which will be generated when a key expires and is deleted

  • e: eviction event, when a key is deleted due to maxmemore strategy, this event is generated

  • A: alias of g$lshzxe, so "AKE" means all events

Introduce dependencies

Add org.springframework.boot:spring-boot-starter-data-redis dependency in pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Related configuration

Define and configure RedisListenerConfig to monitor the expiration time of Redis key

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

@Configuration
public class RedisListenerConfig {

    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        return container;
    }
}

Define the listener RedisKeyExpirationListener, implement the KeyExpirationEventMessageListener interface, check the source code, and find that the interface listens to all db expired events keyevent@*:expired " Completed a full version of the Java Interview Book PDF

import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

/**
 * 监听所有db的过期事件__keyevent@*__:expired"
 */
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    /**
     * 针对 redis 数据失效事件,进行数据处理
     * @param message
     * @param pattern
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {

        // 获取到失效的 key,进行取消订单业务处理
        String expiredKey = message.toString();
        System.out.println(expiredKey);
    }
}

Guess you like

Origin blog.51cto.com/14975073/2596535