window.location.href如何多次请求_RabbitMQ如何保证幂等性?
冪等性是分布式系統(tǒng)設(shè)計(jì)中的一個(gè)重要概念,是在做系統(tǒng)或者接口設(shè)計(jì)時(shí)要著重考慮的問(wèn)題,尤其像支付寶、銀行、互聯(lián)網(wǎng)金融等涉及錢的系統(tǒng),既要高效,數(shù)據(jù)也要準(zhǔn)確,絕對(duì)不能出現(xiàn)多扣款,多打款等問(wèn)題,冪等性的設(shè)計(jì)就顯得更為重要了。
本文我們就先來(lái)解釋一下什么是冪等性?然后再看一下在MQ中怎么保證冪等性?01PART什么是冪等?冪等性的實(shí)質(zhì)是:對(duì)于一個(gè)資源,不管你請(qǐng)求一次還是請(qǐng)求多次,對(duì)該資源本身造成的影響應(yīng)該是相同的,不能因?yàn)橹貜?fù)的請(qǐng)求而對(duì)該資源重復(fù)造成影響。注意關(guān)注的是請(qǐng)求操作對(duì)資源本身造成的影響,而不是請(qǐng)求資源返回的結(jié)果。如select * from t_user where id>10這條語(yǔ)句,假如在一次查詢后數(shù)據(jù)庫(kù)進(jìn)行了insert或update操作,那么第二次再查時(shí)返回的結(jié)果可能與第一次不同,但這個(gè)操作是冪等性的,因?yàn)槲覀冋f(shuō)過(guò)關(guān)注的是對(duì)資源本身的影響,不是返回的結(jié)果,雖然兩次查詢的返回結(jié)果不同,但select不管執(zhí)行多少次,對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)資源本身都不會(huì)產(chǎn)生任何影響。
冪等性包括:① 一次或多次請(qǐng)求,對(duì)資源均不會(huì)造成影響,比如select操作;② 第一次請(qǐng)求對(duì)資源產(chǎn)生了影響,后面再發(fā)出多個(gè)相同的請(qǐng)求,與發(fā)出單個(gè)請(qǐng)求具有相同的效果,不會(huì)重復(fù)對(duì)資源產(chǎn)生影響。比如支付寶轉(zhuǎn)賬,手抖重復(fù)提交了2次,第一次扣款成功,余額減少100元,第二次就不能再重復(fù)扣款了。③ 需要說(shuō)明的是網(wǎng)絡(luò)超時(shí)、服務(wù)宕機(jī)等問(wèn)題,不是冪等的范圍。
冪等性是系統(tǒng)服務(wù)對(duì)外的一種承諾。比如我寫了一個(gè)接口,我承諾我的接口是符合冪等性的,就是說(shuō)外部的多次調(diào)用對(duì)我系統(tǒng)造成的影響都是相同的,不會(huì)因?yàn)槎啻握{(diào)用而對(duì)系統(tǒng)重復(fù)造成影響。聲明為冪等的服務(wù)認(rèn)為調(diào)用失敗是常態(tài),并且允許在調(diào)用失敗后重試。
02PARTRabbitMQ的冪等性那我們回到RabbitMQ中,RabbitMQ中的冪等性又是什么意思呢?我們先來(lái)看看在RabbitMQ中,哪些情況可能導(dǎo)致非冪等?
① consumer接收到消息處理完成后,在給Broker返回ack途中網(wǎng)絡(luò)中斷,Broker未收到確認(rèn)信息,根據(jù)RabbitMQ的重試補(bǔ)償機(jī)制,則會(huì)把這條消息再重發(fā)給其他的消費(fèi)者或等網(wǎng)絡(luò)重連后再發(fā)送給該消費(fèi)者,造成了消息的重復(fù)消費(fèi)。② 在開啟生產(chǎn)者confirm模式下,生產(chǎn)者已經(jīng)把消息發(fā)送到Broker,但在Broker回傳ack確認(rèn)時(shí)網(wǎng)絡(luò)中斷,生產(chǎn)者也會(huì)重新發(fā)送剛才的消息,造成Broker收到了重復(fù)的消息,最終將兩條重復(fù)的消息發(fā)送到消費(fèi)端,造成了消息的重復(fù)消費(fèi)。通過(guò)以上兩種場(chǎng)景我們看出,其實(shí)MQ的冪等性保障應(yīng)該在消費(fèi)端,要保證MQ的冪等性,就要保證消費(fèi)者不會(huì)重復(fù)消費(fèi)相同的消息。※ 如何避免消息的重復(fù)消費(fèi)問(wèn)題?全局唯一ID + Redis生產(chǎn)者在發(fā)送消息時(shí),為每條消息設(shè)置一個(gè)全局唯一的messageId,消費(fèi)者拿到消息后,使用setnx命令,將messageId作為key放到redis中:setnx(messageId,1),若返回1,說(shuō)明之前沒(méi)有消費(fèi)過(guò),正常消費(fèi);若返回0,說(shuō)明這條消息之前已消費(fèi)過(guò),拋棄。※ setnx命令的含義,若給定的key不存在,執(zhí)行set操作,返回1,若給定的Key已存在,不做任何操作,返回0。
> 生產(chǎn)者代碼
public void sendMessageIde() { MessageProperties properties = new MessageProperties(); properties.setMessageId(UUID.randomUUID().toString()); Message message = new Message("Hello RabbitMQ".getBytes(), properties); rabbitTemplate.convertAndSend("durable-exchange", "rabbit.long.yuan", message);}> 消費(fèi)者代碼
@RabbitListener(queues = "durable-queue")@RabbitHandlerpublic void processIde(Message message, Channel channel) throws IOException { if (stringRedisTemplate.opsForValue().setIfAbsent(message.getMessageProperties().getMessageId(),"1")){ // 業(yè)務(wù)操作... System.out.println("消費(fèi)消息:"+ new String(message.getBody(), "UTF-8")); // 手動(dòng)確認(rèn) channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); }}以上就是在RabbitMQ中保障冪等性的一個(gè)簡(jiǎn)單demo,冪等性在系統(tǒng)接口設(shè)計(jì)中尤為重要,尤其在金融、互聯(lián)網(wǎng)系統(tǒng),在做系統(tǒng)設(shè)計(jì)時(shí)需要著重考慮。
總結(jié)
以上是生活随笔為你收集整理的window.location.href如何多次请求_RabbitMQ如何保证幂等性?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python适合找哪方面工作_学习pyt
- 下一篇: visualstudio开始调试不执行_