欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于SpringCloud分布式系統(tǒng)中實(shí)現(xiàn)冪等性的幾種方式

 更新時(shí)間:2023年10月02日 09:55:53   作者:Archie_java  
這篇文章主要介紹了關(guān)于SpringCloud分布式系統(tǒng)中實(shí)現(xiàn)冪等性的幾種方式,冪等函數(shù),或冪等方法,是指可以使用相同參數(shù)重復(fù)執(zhí)行,并能獲得相同結(jié)果的函數(shù),這些函數(shù)不會(huì)影響系統(tǒng)狀態(tài),也不用擔(dān)心重復(fù)執(zhí)行會(huì)對(duì)系統(tǒng)造成改變,需要的朋友可以參考下

一、概述

在開(kāi)發(fā)訂單系統(tǒng)時(shí),我們常遇見(jiàn)支付問(wèn)題,既用戶購(gòu)買商品后支付,支付扣款成功,但是返回結(jié)果的時(shí)候網(wǎng)絡(luò)異常,此時(shí)錢已經(jīng)扣了,用戶再次點(diǎn)擊按鈕,此時(shí)會(huì)進(jìn)行第二次扣款,返回結(jié)果成功,用戶查詢余額發(fā)現(xiàn)多扣錢了,流水記錄也變成了兩條。

在以前的單應(yīng)用系統(tǒng)中,我們只需要把數(shù)據(jù)操作放入事務(wù)中即可,發(fā)生錯(cuò)誤立即回滾,但是再響應(yīng)客戶端的時(shí)候也有可能出現(xiàn)網(wǎng)絡(luò)中斷或者異常問(wèn)題。如果保證一個(gè)訂單從創(chuàng)建到支付成功整個(gè)訂單生命周期中,數(shù)據(jù)是一致,不因異常而改變。這種機(jī)制就需要用到冪等性。

二、什么是冪等性

冪等是一個(gè)數(shù)學(xué)與計(jì)算機(jī)的概念,常見(jiàn)于常見(jiàn)于抽象代數(shù)中。

冪等函數(shù),或冪等方法,是指可以使用相同參數(shù)重復(fù)執(zhí)行,并能獲得相同結(jié)果的函數(shù)。這些函數(shù)不會(huì)影響系統(tǒng)狀態(tài),也不用擔(dān)心重復(fù)執(zhí)行會(huì)對(duì)系統(tǒng)造成改變。

冪等性:任意多次執(zhí)行對(duì)資源本身所產(chǎn)生的影響均與一次執(zhí)行的影響相同

接口的冪等性實(shí)際上就是接口可重復(fù)調(diào)用,在調(diào)用方多次調(diào)用的情況下,接口最終得到的結(jié)果是一致的,有些接口可以天然的冪等性,比如查詢接口,調(diào)用一次和調(diào)用多次,對(duì)系統(tǒng)得到的結(jié)果,是一樣的。并不會(huì)因?yàn)檎{(diào)用的次數(shù)改變查詢的結(jié)果。

插入(INSERT)和修改(UPDATE)方法是非冪等性的,需要通過(guò)機(jī)制在需要的場(chǎng)景處理以確保多次執(zhí)行無(wú)副作用。

刪除(delete)執(zhí)行一次或多次都是結(jié)果為空(即結(jié)果一致),并且無(wú)副作用,所以在根據(jù)主鍵ID刪除可以認(rèn)為是(偽)冪等性的,根據(jù)非主鍵刪除的如果多次執(zhí)行無(wú)副作用(都是把數(shù)據(jù)刪除),也可以認(rèn)為是(偽)冪等性。

三、冪等性需關(guān)注幾個(gè)重點(diǎn)

  • 冪等不僅僅只是一次(或多次)請(qǐng)求對(duì)資源沒(méi)有副作用(比如查詢數(shù)據(jù)庫(kù)操作,沒(méi)有增刪改,因此沒(méi)有對(duì)數(shù)據(jù)庫(kù)有任何影響)
  • 冪等還包括第一次請(qǐng)求的時(shí)候?qū)Y源產(chǎn)生了副作用,但是以后的多次請(qǐng)求都不會(huì)再對(duì)資源產(chǎn)生副作用。
  • 冪等關(guān)注的是以后的多次請(qǐng)求是否對(duì)資源產(chǎn)生的副作用,而不關(guān)注結(jié)果。
  • 網(wǎng)絡(luò)超時(shí)等問(wèn)題,不是冪等性的討論范圍。

冪等性是系統(tǒng)服務(wù)對(duì)外一種承諾(而不是實(shí)現(xiàn)),承諾只要調(diào)用接口成功,外部多次調(diào)用對(duì)系統(tǒng)的影響是一致的。聲明為冪等的服務(wù)會(huì)認(rèn)為外部調(diào)用失敗是常態(tài),并且失敗之后必然會(huì)有重試。

四、冪等性有什么用

業(yè)務(wù)開(kāi)發(fā)中,經(jīng)常會(huì)遇到重復(fù)提交的情況,無(wú)論是由于網(wǎng)絡(luò)問(wèn)題無(wú)法收到請(qǐng)求結(jié)果而重新發(fā)起請(qǐng)求,或是前端的操作抖動(dòng)而造成重復(fù)提交情況。在交易系統(tǒng),支付系統(tǒng)這種重復(fù)提交造成的問(wèn)題有尤其明顯,比如:

  • 用戶在APP上連續(xù)點(diǎn)擊了多次提交訂單,后臺(tái)應(yīng)該只產(chǎn)生一個(gè)訂單;
  • 向支付寶發(fā)起支付請(qǐng)求,由于網(wǎng)絡(luò)問(wèn)題或系統(tǒng)BUG重發(fā),支付寶應(yīng)該只扣一次錢。很顯然,聲明冪等的服務(wù)認(rèn)為,外部調(diào)用者會(huì)存在多次調(diào)用的情況,為了防止外部多次調(diào)用對(duì)系統(tǒng)數(shù)據(jù)狀態(tài)的發(fā)生多次改變,將服務(wù)設(shè)計(jì)成冪等。
  • 出庫(kù)單反復(fù)請(qǐng)求產(chǎn)生多個(gè)出庫(kù)單信息。

五、常見(jiàn)用來(lái)保證冪等的手段

5.1 MVCC方案

多版本并發(fā)控制,該策略主要使用update with condition(更新帶條件來(lái)防止)來(lái)保證多次外部請(qǐng)求調(diào)用對(duì)系統(tǒng)的影響是一致的。在系統(tǒng)設(shè)計(jì)的過(guò)程中,合理的使用樂(lè)觀鎖,通過(guò)version或者updateTime(timestamp)等其他條件,來(lái)做樂(lè)觀鎖的判斷條件,這樣保證更新操作即使在并發(fā)的情況下,也不會(huì)有太大的問(wèn)題。例如

select * from tablename where condition=#condition# //取出要跟新的對(duì)象,帶有版本versoin
update tableName set name=#name#,version=version+1 where version=#version#

在更新的過(guò)程中利用version來(lái)防止,其他操作對(duì)對(duì)象的并發(fā)更新,導(dǎo)致更新丟失。為了避免失敗,通常需要一定的重試機(jī)制。

5.2 去重表

在插入數(shù)據(jù)的時(shí)候,插入去重表,利用數(shù)據(jù)庫(kù)的唯一索引特性,保證唯一的邏輯。

這種方法適用于在業(yè)務(wù)中有唯一標(biāo)的插入場(chǎng)景中,比如在以上的支付場(chǎng)景中,如果一個(gè)訂單只會(huì)支付一次,所以訂單ID可以作為唯一標(biāo)識(shí)。這時(shí),我們就可以建一張去重表,并且把唯一標(biāo)識(shí)作為唯一索引,在我們實(shí)現(xiàn)時(shí),把創(chuàng)建支付單據(jù)和寫入去去重表,放在一個(gè)事務(wù)中,如果重復(fù)創(chuàng)建,數(shù)據(jù)庫(kù)會(huì)拋出唯一約束異常,操作就會(huì)回滾。

5.3 去重表

select for update,整個(gè)執(zhí)行過(guò)程中鎖定該訂單對(duì)應(yīng)的記錄。注意:這種在DB讀大于寫的情況下盡量少用。

5.4 select + insert

并發(fā)不高的后臺(tái)系統(tǒng),或者一些任務(wù)JOB,為了支持冪等,支持重復(fù)執(zhí)行,簡(jiǎn)單的處理方法是,先查詢下一些關(guān)鍵數(shù)據(jù),判斷是否已經(jīng)執(zhí)行過(guò),在進(jìn)行業(yè)務(wù)處理,就可以了。注意:核心高并發(fā)流程不要用這種方法。

5.5 狀態(tài)機(jī)冪等

在設(shè)計(jì)單據(jù)相關(guān)的業(yè)務(wù),或者是任務(wù)相關(guān)的業(yè)務(wù),肯定會(huì)涉及到狀態(tài)機(jī),就是業(yè)務(wù)單據(jù)上面有個(gè)狀態(tài),狀態(tài)在不同的情況下會(huì)發(fā)生變更,一般情況下存在有限狀態(tài)機(jī),這時(shí)候,如果狀態(tài)機(jī)已經(jīng)處于下一個(gè)狀態(tài),這時(shí)候來(lái)了一個(gè)上一個(gè)狀態(tài)的變更,理論上是不能夠變更的,這樣的話,保證了有限狀態(tài)機(jī)的冪等。

這種方法適合在有狀態(tài)機(jī)流轉(zhuǎn)的情況下,比如就會(huì)訂單的創(chuàng)建和付款,訂單的付款肯定是在之前,這時(shí)我們可以通過(guò)在設(shè)計(jì)狀態(tài)字段時(shí),使用int類型,并且通過(guò)值類型的大小來(lái)做冪等,比如訂單的創(chuàng)建為1000,付款成功為1。付款失敗為999。

5.6 token機(jī)制

防止頁(yè)面重復(fù)提交

業(yè)務(wù)要求:頁(yè)面的數(shù)據(jù)只能被點(diǎn)擊提交一次,

發(fā)生原因:由于重復(fù)點(diǎn)擊或者網(wǎng)絡(luò)重發(fā),或者nginx重發(fā)等情況會(huì)導(dǎo)致數(shù)據(jù)被重復(fù)提交

解決辦法

  • 集群環(huán)境:采用token加redis(redis單線程的,處理需要排隊(duì))
  • 單JVM環(huán)境:采用token加redis或token加jvm內(nèi)存

處理流程

  • 數(shù)據(jù)提交前要向服務(wù)的申請(qǐng)token,token放到redis或jvm內(nèi)存,token有效時(shí)間
  • 提交后后臺(tái)校驗(yàn)token,同時(shí)刪除token,生成新的token返回
  • token特點(diǎn):要申請(qǐng),一次有效性,可以限流

5.7 對(duì)外提供接口的api如何保證冪等

如微信提供的付款接口:需要接入商戶提交付款請(qǐng)求時(shí)附帶:source來(lái)源,seq序列號(hào)。source+seq在數(shù)據(jù)庫(kù)里面做唯一索引,防止多次付款,(并發(fā)時(shí),只能處理一個(gè)請(qǐng)求)

總結(jié): 

冪等性應(yīng)該是合格程序員的一個(gè)基因,在設(shè)計(jì)系統(tǒng)時(shí),是首要考慮的問(wèn)題,尤其是在像支付寶,銀行,互聯(lián)網(wǎng)金融公司等涉及的都是錢的系統(tǒng),既要高效,數(shù)據(jù)也要準(zhǔn)確,所以不能出現(xiàn)多扣款,多打款等問(wèn)題,這樣會(huì)很難處理,用戶體驗(yàn)也不好 。

5.8 全局唯一ID

如果使用全局唯一ID,就是根據(jù)業(yè)務(wù)的操作和內(nèi)容生成一個(gè)全局ID,在執(zhí)行操作前先根據(jù)這個(gè)全局唯一ID是否存在,來(lái)判斷這個(gè)操作是否已經(jīng)執(zhí)行。如果不存在則把全局ID,存儲(chǔ)到存儲(chǔ)系統(tǒng)中,比如數(shù)據(jù)庫(kù)、redis等。如果存在則表示該方法已經(jīng)執(zhí)行。

從工程的角度來(lái)說(shuō),使用全局ID做冪等可以作為一個(gè)業(yè)務(wù)的基礎(chǔ)的微服務(wù)存在,在很多的微服務(wù)中都會(huì)用到這樣的服務(wù),在每個(gè)微服務(wù)中都完成這樣的功能,會(huì)存在工作量重復(fù)。另外打造一個(gè)高可靠的冪等服務(wù)還需要考慮很多問(wèn)題,比如一臺(tái)機(jī)器雖然把全局ID先寫入了存儲(chǔ),但是在寫入之后掛了,這就需要引入全局ID的超時(shí)機(jī)制。

使用全局唯一ID是一個(gè)通用方案,可以支持插入、更新、刪除業(yè)務(wù)操作。但是這個(gè)方案看起來(lái)很美但是實(shí)現(xiàn)起來(lái)比較麻煩,下面的方案適用于特定的場(chǎng)景,但是實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單。

5.9 分布式鎖

在進(jìn)入方法時(shí),先去獲取鎖,假如獲取到鎖,就繼續(xù)后面的流程。假如沒(méi)有獲取到鎖,就等待鎖的釋放直到獲取到鎖。當(dāng)執(zhí)行完方法時(shí),釋放鎖。當(dāng)然,鎖要設(shè)個(gè)超時(shí)時(shí)間,防止意外沒(méi)有釋放到鎖。它用來(lái)解決分布式系統(tǒng)的冪等性,常用的實(shí)現(xiàn)方案是 redis 和 zookeeper 等工具。

六、總結(jié)

冪等性增加了額外控制冪等的業(yè)務(wù)邏輯,復(fù)雜化了業(yè)務(wù)功能,把并行執(zhí)行的功能改為串行執(zhí)行,降低了執(zhí)行效率。

冪等性雖然復(fù)雜化了業(yè)務(wù)功能和降低了執(zhí)行效率,但為了保證系統(tǒng)的正確性,是必要的。就上面更新 X 的例子,在單臺(tái)服務(wù)器上,給那段代碼加上鎖,并給 X 設(shè)為 volatile,就保證來(lái)數(shù)據(jù)的正確性了。

在分布式環(huán)境下并且 X 是從數(shù)據(jù)庫(kù)或者文件里查詢出來(lái)的,用上面加鎖的方式實(shí)現(xiàn)就不能保證數(shù)據(jù)的正確性了,這時(shí)候就需要用到分布式鎖了。所以,保證方法或接口的冪等性是非常有必要的,因?yàn)閿?shù)據(jù)是不能出現(xiàn)任何問(wèn)題的。

到此這篇關(guān)于關(guān)于SpringCloud分布式系統(tǒng)中實(shí)現(xiàn)冪等性的幾種方式的文章就介紹到這了,更多相關(guān)SpringCloud中實(shí)現(xiàn)冪等性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實(shí)現(xiàn)游戲抽獎(jiǎng)算法

    Java實(shí)現(xiàn)游戲抽獎(jiǎng)算法

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)游戲抽獎(jiǎng)算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • Java 字節(jié)數(shù)組類型(byte[])與int類型互轉(zhuǎn)方法

    Java 字節(jié)數(shù)組類型(byte[])與int類型互轉(zhuǎn)方法

    下面小編就為大家?guī)?lái)一篇Java 字節(jié)數(shù)組類型(byte[])與int類型互轉(zhuǎn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-02-02
  • 在Java的Struts中判斷是否調(diào)用AJAX及用攔截器對(duì)其優(yōu)化

    在Java的Struts中判斷是否調(diào)用AJAX及用攔截器對(duì)其優(yōu)化

    這篇文章主要介紹了在Java的Struts中判斷是否調(diào)用AJAX及用攔截器對(duì)其優(yōu)化的方法,Struts框架是Java的SSH三大web開(kāi)發(fā)框架之一,需要的朋友可以參考下
    2016-01-01
  • java遞歸讀取目錄下所有文件的方法

    java遞歸讀取目錄下所有文件的方法

    這篇文章主要為大家詳細(xì)介紹了java遞歸讀取目錄下所有文件的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • Spring Boot如何使用HikariCP連接池詳解

    Spring Boot如何使用HikariCP連接池詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot如何使用HikariCP連接池的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用springboot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • java中this的n種使用方法

    java中this的n種使用方法

    this可能是幾乎所有有一點(diǎn)面向?qū)ο笏枷氲恼Z(yǔ)言都會(huì)引用到的變量,this有多少種用法。下面小編給大家?guī)?lái)了java中this的n種使用方法,感興趣的朋友一起看看吧
    2018-08-08
  • idea?springBoot項(xiàng)目自動(dòng)注入mapper為空?qǐng)?bào)錯(cuò)的解決方法

    idea?springBoot項(xiàng)目自動(dòng)注入mapper為空?qǐng)?bào)錯(cuò)的解決方法

    這篇文章主要介紹了idea?springBoot項(xiàng)目自動(dòng)注入mapper為空?qǐng)?bào)錯(cuò)的解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-03-03
  • Spring動(dòng)態(tài)多數(shù)據(jù)源配置實(shí)例Demo

    Spring動(dòng)態(tài)多數(shù)據(jù)源配置實(shí)例Demo

    本篇文章主要介紹了Spring動(dòng)態(tài)多數(shù)據(jù)源配置實(shí)例Demo,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-01-01
  • java內(nèi)部類的定義與分類示例詳解

    java內(nèi)部類的定義與分類示例詳解

    這篇文章主要給大家介紹了關(guān)于java內(nèi)部類的定義與分類的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • java之向linux文件夾下寫文件無(wú)權(quán)限的問(wèn)題

    java之向linux文件夾下寫文件無(wú)權(quán)限的問(wèn)題

    這篇文章主要介紹了java之向linux文件夾下寫文件無(wú)權(quán)限的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09

最新評(píng)論