1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        京東面試官:接口的冪等性怎么設(shè)計(jì)?

        共 1896字,需瀏覽 4分鐘

         ·

        2021-09-21 20:40

        互聯(lián)網(wǎng)架構(gòu)師后臺(tái)回復(fù) 2T 有特別禮包
        上一篇:深夜看了張一鳴的微博,讓我越想越后怕

        什么是冪等?


        看一下維基百科怎么說(shuō)的:



        冪等性:多次調(diào)用方法或者接口不會(huì)改變業(yè)務(wù)狀態(tài),可以保證重復(fù)調(diào)用的結(jié)果和單次調(diào)用的結(jié)果一致。


        使用冪等的場(chǎng)景


        1、前端重復(fù)提交


        用戶注冊(cè),用戶創(chuàng)建商品等操作,前端都會(huì)提交一些數(shù)據(jù)給后臺(tái)服務(wù),后臺(tái)需要根據(jù)用戶提交的數(shù)據(jù)在數(shù)據(jù)庫(kù)中創(chuàng)建記錄。如果用戶不小心多點(diǎn)了幾次,后端收到了好幾次提交,這時(shí)就會(huì)在數(shù)據(jù)庫(kù)中重復(fù)創(chuàng)建了多條記錄。這就是接口沒(méi)有冪等性帶來(lái)的 bug。


        2、接口超時(shí)重試


        對(duì)于給第三方調(diào)用的接口,有可能會(huì)因?yàn)榫W(wǎng)絡(luò)原因而調(diào)用失敗,這時(shí),一般在設(shè)計(jì)的時(shí)候會(huì)對(duì)接口調(diào)用加上失敗重試的機(jī)制。如果第一次調(diào)用已經(jīng)執(zhí)行了一半時(shí),發(fā)生了網(wǎng)絡(luò)異常。這時(shí)再次調(diào)用時(shí)就會(huì)因?yàn)榕K數(shù)據(jù)的存在而出現(xiàn)調(diào)用異常。


        3、消息重復(fù)消費(fèi)


        在使用消息中間件來(lái)處理消息隊(duì)列,且手動(dòng) ack 確認(rèn)消息被正常消費(fèi)時(shí)。如果消費(fèi)者突然斷開(kāi)連接,那么已經(jīng)執(zhí)行了一半的消息會(huì)重新放回隊(duì)列。


        當(dāng)消息被其他消費(fèi)者重新消費(fèi)時(shí),如果沒(méi)有冪等性,就會(huì)導(dǎo)致消息重復(fù)消費(fèi)時(shí)結(jié)果異常,如數(shù)據(jù)庫(kù)重復(fù)數(shù)據(jù),數(shù)據(jù)庫(kù)數(shù)據(jù)沖突,資源重復(fù)等。


        解決方案


        1、token 機(jī)制實(shí)現(xiàn)


        通過(guò)token 機(jī)制實(shí)現(xiàn)接口的冪等性,這是一種比較通用性的實(shí)現(xiàn)方法。


        示意圖如下:

        具體流程步驟:


        1. 客戶端會(huì)先發(fā)送一個(gè)請(qǐng)求去獲取 token,服務(wù)端會(huì)生成一個(gè)全局唯一的 ID 作為 token 保存在 redis 中,同時(shí)把這個(gè) ID 返回給客戶端
        2. 客戶端第二次調(diào)用業(yè)務(wù)請(qǐng)求的時(shí)候必須攜帶這個(gè) token
        3. 服務(wù)端會(huì)校驗(yàn)這個(gè) token,如果校驗(yàn)成功,則執(zhí)行業(yè)務(wù),并刪除 redis 中的 token
        4. 如果校驗(yàn)失敗,說(shuō)明 redis 中已經(jīng)沒(méi)有對(duì)應(yīng)的 token,則表示重復(fù)操作,直接返回指定的結(jié)果給客戶端


        注意:


        1. 對(duì) redis 中是否存在 token 以及刪除的代碼邏輯建議用 Lua 腳本實(shí)現(xiàn),保證原子性
        2. 全局唯一 ID 可以用百度的 uid-generator、美團(tuán)的 Leaf 去生成


        2、基于 mysql 實(shí)現(xiàn)


        這種實(shí)現(xiàn)方式是利用 mysql 唯一索引的特性。


        示意圖如下:

        具體流程步驟:


        1. 建立一張去重表,其中某個(gè)字段需要建立唯一索引
        2. 客戶端去請(qǐng)求服務(wù)端,服務(wù)端會(huì)將這次請(qǐng)求的一些信息插入這張去重表中
        3. 因?yàn)楸碇心硞€(gè)字段帶有唯一索引,如果插入成功,證明表中沒(méi)有這次請(qǐng)求的信息,則執(zhí)行后續(xù)的業(yè)務(wù)邏輯
        4. 如果插入失敗,則代表已經(jīng)執(zhí)行過(guò)當(dāng)前請(qǐng)求,直接返回


        3、基于 redis 實(shí)現(xiàn)


        這種實(shí)現(xiàn)方式是基于 SETNX 命令實(shí)現(xiàn)的


        SETNX key value:將 key 的值設(shè)為 value ,當(dāng)且僅當(dāng) key 不存在。若給定的 key 已經(jīng)存在,則 SETNX 不做任何動(dòng)作。


        該命令在設(shè)置成功時(shí)返回 1,設(shè)置失敗時(shí)返回 0。


        示意圖如下:

        具體流程步驟:



        總結(jié)


        這幾種實(shí)現(xiàn)冪等的方式其實(shí)都是大同小異的,類似的還有使用狀態(tài)機(jī)、悲觀鎖、樂(lè)觀鎖的方式來(lái)實(shí)現(xiàn),都是比較簡(jiǎn)單的。


        總之,當(dāng)你去設(shè)計(jì)一個(gè)接口的時(shí)候,冪等都是首要考慮的問(wèn)題,特別是當(dāng)你負(fù)責(zé)設(shè)計(jì)轉(zhuǎn)賬、支付這種涉及到 money 的接口,你要格外注意嘍!



        感謝您的閱讀,也歡迎您發(fā)表關(guān)于這篇文章的任何建議,關(guān)注我,技術(shù)不迷茫!小編到你上高速。

            · END ·
        最后,關(guān)注公眾號(hào)互聯(lián)網(wǎng)架構(gòu)師,在后臺(tái)回復(fù):2T,可以獲取我整理的 Java 系列面試題和答案,非常齊全。


        正文結(jié)束


        推薦閱讀 ↓↓↓

        1.不認(rèn)命,從10年流水線工人,到谷歌上班的程序媛,一位湖南妹子的勵(lì)志故事

        2.如何才能成為優(yōu)秀的架構(gòu)師?

        3.從零開(kāi)始搭建創(chuàng)業(yè)公司后臺(tái)技術(shù)棧

        4.程序員一般可以從什么平臺(tái)接私活?

        5.37歲程序員被裁,120天沒(méi)找到工作,無(wú)奈去小公司,結(jié)果懵了...

        6.IntelliJ IDEA 2019.3 首個(gè)最新訪問(wèn)版本發(fā)布,新特性搶先看

        7.這封“領(lǐng)導(dǎo)痛批95后下屬”的郵件,句句扎心!

        8.15張圖看懂瞎忙和高效的區(qū)別!

        一個(gè)人學(xué)習(xí)、工作很迷茫?


        點(diǎn)擊「閱讀原文」加入我們的小圈子!

        瀏覽 45
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美高清无码 | 国产久久精品视频 | 高潮喷水HDXXXXXX | 中文字幕激情无码 | www.91aiai | 经典素人-熊猫成人网 | 国产精品国产三级国语电影有那些 | 欧美11aaa | 91香蕉视频在线播放 | 深夜成人黄色内射免费 |