最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如果淘寶的七天自動(dòng)確認(rèn)收貨讓你設(shè)計(jì)你用Java怎么實(shí)現(xiàn)

 更新時(shí)間:2021年09月16日 15:11:25   作者:Java_aoe  
在面試的時(shí)候如果面試官問淘寶的七天自動(dòng)確認(rèn)收貨讓你設(shè)計(jì),你會(huì)怎么具體實(shí)現(xiàn)呢?跟著小編看一下下邊的實(shí)現(xiàn)過程,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值

目前常見的應(yīng)用軟件都有消息的延遲推送的影子,應(yīng)用也極為廣泛,例如:

  • 淘寶七天自動(dòng)確認(rèn)收貨。在我們簽收商品后,物流系統(tǒng)會(huì)在七天后延時(shí)發(fā)送一個(gè)消息給支付系統(tǒng),通知支付系統(tǒng)將款打給商家,這個(gè)過程持續(xù)七天,就是使用了消息中間件的延遲推送功能。
  • 12306 購票支付確認(rèn)頁面。我們?cè)谶x好票點(diǎn)擊確定跳轉(zhuǎn)的頁面中往往都會(huì)有倒計(jì)時(shí),代表著 30 分鐘內(nèi)訂單不確認(rèn)的話將會(huì)自動(dòng)取消訂單。其實(shí)在下訂單那一刻開始購票業(yè)務(wù)系統(tǒng)就會(huì)發(fā)送一個(gè)延時(shí)消息給訂單系統(tǒng),延時(shí)30分鐘,告訴訂單系統(tǒng)訂單未完成,如果我們?cè)?0分鐘內(nèi)完成了訂單,則可以通過邏輯代碼判斷來忽略掉收到的消息。

在上面兩種場(chǎng)景中,如果我們使用下面兩種傳統(tǒng)解決方案無疑大大降低了系統(tǒng)的整體性能和吞吐量:

  1. 使用 redis 給訂單設(shè)置過期時(shí)間,最后通過判斷 redis 中是否還有該訂單來決定訂單是否已經(jīng)完成。這種解決方案相較于消息的延遲推送性能較低,因?yàn)槲覀冎?redis 都是存儲(chǔ)于內(nèi)存中,我們遇到惡意下單或者刷單的將會(huì)給內(nèi)存帶來巨大壓力。
  2. 使用傳統(tǒng)的數(shù)據(jù)庫輪詢來判斷數(shù)據(jù)庫表中訂單的狀態(tài),這無疑增加了IO次數(shù),性能極低。
  3. 使用 jvm 原生的 DelayQueue ,也是大量占用內(nèi)存,而且沒有持久化策略,系統(tǒng)宕機(jī)或者重啟都會(huì)丟失訂單信息。

消息延遲推送的實(shí)現(xiàn)

在 RabbitMQ 3.6.x 之前我們一般采用死信隊(duì)列+TTL過期時(shí)間來實(shí)現(xiàn)延遲隊(duì)列,我們這里不做過多介紹。

在 RabbitMQ 3.6.x 開始,RabbitMQ 官方提供了延遲隊(duì)列的插件,可以下載放置到 RabbitMQ 根目錄下的 plugins 下。

面試官問:淘寶七天自動(dòng)確認(rèn)收貨,讓你設(shè)計(jì),可以怎么實(shí)現(xiàn)?

圖片

首先我們創(chuàng)建交換機(jī)和消息隊(duì)列,application.properties 中配置與上一篇文章相同。

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import java.util.HashMap;
import java.util.Map;
 
@Configuration
public class MQConfig {
 
    public static final String LAZY_EXCHANGE = "Ex.LazyExchange";
    public static final String LAZY_QUEUE = "MQ.LazyQueue";
    public static final String LAZY_KEY = "lazy.#";
 
    @Bean
    public TopicExchange lazyExchange(){
        //Map<String, Object> pros = new HashMap<>();
        //設(shè)置交換機(jī)支持延遲消息推送
        //pros.put("x-delayed-message", "topic");
        TopicExchange exchange = new TopicExchange(LAZY_EXCHANGE, true, false, pros);
        exchange.setDelayed(true);
        return exchange;
    }
 
    @Bean
    public Queue lazyQueue(){
        return new Queue(LAZY_QUEUE, true);
    }
 
    @Bean
    public Binding lazyBinding(){
        return BindingBuilder.bind(lazyQueue()).to(lazyExchange()).with(LAZY_KEY);
    }
}

我們?cè)?Exchange 的聲明中可以設(shè)置exchange.setDelayed(true)來開啟延遲隊(duì)列,也可以設(shè)置為以下內(nèi)容傳入交換機(jī)聲明的方法中,因?yàn)榈谝环N方式的底層就是通過這種方式來實(shí)現(xiàn)的。

//Map<String, Object> pros = new HashMap<>();
        //設(shè)置交換機(jī)支持延遲消息推送
        //pros.put("x-delayed-message", "topic");
        TopicExchange exchange = new TopicExchange(LAZY_EXCHANGE, true, false, pros);

發(fā)送消息時(shí)我們需要指定延遲推送的時(shí)間,我們這里在發(fā)送消息的方法中傳入?yún)?shù) new MessagePostProcessor() 是為了獲得 Message對(duì)象,因?yàn)樾枰柚?Message對(duì)象的api 來設(shè)置延遲時(shí)間。

import com.anqi.mq.config.MQConfig;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
import java.util.Date;
 
@Component
public class MQSender {
 
    @Autowired
    private RabbitTemplate rabbitTemplate;
 
    //confirmCallback returnCallback 代碼省略,請(qǐng)參照上一篇
 
    public void sendLazy(Object message){
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setConfirmCallback(confirmCallback);
        rabbitTemplate.setReturnCallback(returnCallback);
        //id + 時(shí)間戳 全局唯一
        CorrelationData correlationData = new CorrelationData("12345678909"+new Date());
 
        //發(fā)送消息時(shí)指定 header 延遲時(shí)間
        rabbitTemplate.convertAndSend(MQConfig.LAZY_EXCHANGE, "lazy.boot", message,
                new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //設(shè)置消息持久化
                message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
                //message.getMessageProperties().setHeader("x-delay", "6000");
                message.getMessageProperties().setDelay(6000);
                return message;
            }
        }, correlationData);
    }
}

我們可以觀察 setDelay(Integer i)底層代碼,也是在 header 中設(shè)置 x-delay。等同于我們手動(dòng)設(shè)置 header

message.getMessageProperties().setHeader("x-delay", "6000");
/**
 * Set the x-delay header.
 * @param delay the delay.
 * @since 1.6
 */
public void setDelay(Integer delay) {
    if (delay == null || delay < 0) {
        this.headers.remove(X_DELAY);
    }
    else {
        this.headers.put(X_DELAY, delay);
    }
}

消費(fèi)端進(jìn)行消費(fèi)

import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.stereotype.Component;
 
import java.io.IOException;
import java.util.Map;
 
@Component
public class MQReceiver {
 
    @RabbitListener(queues = "MQ.LazyQueue")
    @RabbitHandler
    public void onLazyMessage(Message msg, Channel channel) throws IOException{
        long deliveryTag = msg.getMessageProperties().getDeliveryTag();
        channel.basicAck(deliveryTag, true);
        System.out.println("lazy receive " + new String(msg.getBody()));
 
    }
    ```
 
## 測(cè)試結(jié)果[#](https://www.cnblogs.com/haixiang/p/10966985.html#3724420099)
 
```java
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
 
@SpringBootTest
@RunWith(SpringRunner.class)
public class MQSenderTest {
 
    @Autowired
    private MQSender mqSender;
 
    @Test
    public void sendLazy() throws  Exception {
        String msg = "hello spring boot";
 
        mqSender.sendLazy(msg + ":");
    }
}

果然在 6 秒后收到了消息 lazy receive hello spring boot:

到此這篇關(guān)于如果淘寶的七天自動(dòng)確認(rèn)收貨讓你設(shè)計(jì)你用Java怎么實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java 七天自動(dòng)確認(rèn)收貨內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 5個(gè)并發(fā)處理技巧代碼示例

    5個(gè)并發(fā)處理技巧代碼示例

    這篇文章主要介紹了5個(gè)并發(fā)處理技巧代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • 解決import包時(shí)報(bào) Java 程序包不存在的問題

    解決import包時(shí)報(bào) Java 程序包不存在的問題

    你是否也有過在import包時(shí)idea報(bào)錯(cuò)說這個(gè)包不存在,可是這個(gè)包我們看得到確實(shí)存在的情況,不要慌,今天這篇文章帶你徹底告別這個(gè)問題
    2021-10-10
  • 去掉 IDEA 中 mybatis配置文件的局部背景顏色(圖解)

    去掉 IDEA 中 mybatis配置文件的局部背景顏色(圖解)

    這篇文章通過圖文并茂的形式給大家介紹了去掉IntelliJ IDEA 中 mybatis配置文件的局部背景顏色及mybatis 對(duì)應(yīng)的 xml 文件警告的方法圖解,需要的朋友可以參考下
    2018-09-09
  • SpringBoot整合websocket實(shí)現(xiàn)即時(shí)通信聊天

    SpringBoot整合websocket實(shí)現(xiàn)即時(shí)通信聊天

    這篇文章主要介紹了SpringBoot整合websocket實(shí)現(xiàn)即時(shí)通信聊天,實(shí)時(shí)通信是一個(gè)實(shí)時(shí)通信系統(tǒng),允許兩人或多人使用網(wǎng)絡(luò)實(shí)時(shí)的傳遞文字消息、文件、語音與視頻交流,需要的朋友可以參考下
    2022-05-05
  • 使用springCloud+nacos集成seata1.3.0搭建過程

    使用springCloud+nacos集成seata1.3.0搭建過程

    這篇文章主要介紹了使用springCloud+nacos集成seata1.3.0搭建過程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • 淺談MyBatis3 DynamicSql風(fēng)格語法使用指南

    淺談MyBatis3 DynamicSql風(fēng)格語法使用指南

    這篇文章主要介紹了淺談MyBatis3 DynamicSql風(fēng)格語法使用指南,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Java 讀取excel 文件流代碼實(shí)例

    Java 讀取excel 文件流代碼實(shí)例

    這篇文章主要介紹了Java 讀取excel 文件流代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • 關(guān)于Mybatis實(shí)體別名支持通配符掃描問題小結(jié)

    關(guān)于Mybatis實(shí)體別名支持通配符掃描問題小結(jié)

    MyBatis可以使用簡(jiǎn)單的 XML 或注解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對(duì)象)映射成數(shù)據(jù)庫中的記錄,這篇文章主要介紹了Mybatis實(shí)體別名支持通配符掃描的問題,需要的朋友可以參考下
    2022-01-01
  • idea生成WebServices接口的完整流程步驟

    idea生成WebServices接口的完整流程步驟

    因?yàn)楣ぷ餍枰?數(shù)據(jù)傳輸部分需要使用webservice實(shí)現(xiàn),經(jīng)過兩天的研究,實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的例子,這篇文章主要給大家介紹了關(guān)于idea生成WebServices接口的完整流程步驟,需要的朋友可以參考下
    2024-08-08
  • IDEA2020.3創(chuàng)建web工程的完整步驟

    IDEA2020.3創(chuàng)建web工程的完整步驟

    這篇文章主要給大家介紹了關(guān)于IDEA2020.3創(chuàng)建web工程的完整步驟,文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評(píng)論

五莲县| 延寿县| 峨眉山市| 壤塘县| 乌拉特后旗| 栾城县| 佛山市| 铅山县| 金川县| 柯坪县| 万载县| 荆门市| 庆城县| 丘北县| 泰来县| 永丰县| 桃源县| 微博| 麦盖提县| 阿瓦提县| 集贤县| 康保县| 西峡县| 剑河县| 同德县| 辉县市| 汾阳市| 图木舒克市| 上虞市| 延边| 锦屏县| 集安市| 怀来县| 夏津县| 永康市| 韶山市| 江华| 定襄县| 卢湾区| 深圳市| 天峻县|