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ì)?

        共 1733字,需瀏覽 4分鐘

         ·

        2021-05-20 03:07

        點(diǎn)擊藍(lán)色“黃小斜學(xué)Java”關(guān)注我喲

        加個“星標(biāo)”,每天和你一起多進(jìn)步一點(diǎn)點(diǎn)!



        一、什么是冪等?

        看一下維基百科怎么說的:
        圖片
        冪等性: 多次調(diào)用方法或者接口不會改變業(yè)務(wù)狀態(tài),可以保證重復(fù)調(diào)用的結(jié)果和單次調(diào)用的結(jié)果一致。

        二、使用冪等的場景

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

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

        2、接口超時重試

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

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

        在使用消息中間件來處理消息隊(duì)列,且手動 ack 確認(rèn)消息被正常消費(fèi)時。如果消費(fèi)者突然斷開連接,那么已經(jīng)執(zhí)行了一半的消息會重新放回隊(duì)列。
        當(dāng)消息被其他消費(fèi)者重新消費(fèi)時,如果沒有冪等性,就會導(dǎo)致消息重復(fù)消費(fèi)時結(jié)果異常,如數(shù)據(jù)庫重復(fù)數(shù)據(jù),數(shù)據(jù)庫數(shù)據(jù)沖突,資源重復(fù)等。

        三、解決方案

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

        通過token 機(jī)制實(shí)現(xiàn)接口的冪等性,這是一種比較通用性的實(shí)現(xiàn)方法。
        示意圖如下:
        圖片
        具體流程步驟:
        1. 客戶端會先發(fā)送一個請求去獲取 token,服務(wù)端會生成一個全局唯一的 ID 作為 token 保存在 redis 中,同時把這個 ID 返回給客戶端
        2. 客戶端第二次調(diào)用業(yè)務(wù)請求的時候必須攜帶這個 token
        3. 服務(wù)端會校驗(yàn)這個 token,如果校驗(yàn)成功,則執(zhí)行業(yè)務(wù),并刪除 redis 中的 token
        4. 如果校驗(yàn)失敗,說明 redis 中已經(jīng)沒有對應(yīng)的 token,則表示重復(fù)操作,直接返回指定的結(jié)果給客戶端
        注意:
        1. 對 redis 中是否存在 token 以及刪除的代碼邏輯建議用 Lua 腳本實(shí)現(xiàn),保證原子性
        2. 全局唯一 ID 可以用百度的 uid-generator、美團(tuán)的 Leaf 去生成

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

        這種實(shí)現(xiàn)方式是利用 mysql 唯一索引的特性。
        示意圖如下:
        圖片
        具體流程步驟:
        1. 建立一張去重表,其中某個字段需要建立唯一索引
        2. 客戶端去請求服務(wù)端,服務(wù)端會將這次請求的一些信息插入這張去重表中
        3. 因?yàn)楸碇心硞€字段帶有唯一索引,如果插入成功,證明表中沒有這次請求的信息,則執(zhí)行后續(xù)的業(yè)務(wù)邏輯
        4. 如果插入失敗,則代表已經(jīng)執(zhí)行過當(dā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 不做任何動作。
        該命令在設(shè)置成功時返回 1,設(shè)置失敗時返回 0。
        示意圖如下:
        圖片
        具體流程步驟:
        1. 客戶端先請求服務(wù)端,會拿到一個能代表這次請求業(yè)務(wù)的唯一字段
        2. 將該字段以 SETNX 的方式存入 redis 中,并根據(jù)業(yè)務(wù)設(shè)置相應(yīng)的超時時間
        3. 如果設(shè)置成功,證明這是第一次請求,則執(zhí)行后續(xù)的業(yè)務(wù)邏輯
        4. 如果設(shè)置失敗,則代表已經(jīng)執(zhí)行過當(dāng)前請求,直接返回

        總結(jié)

        這幾種實(shí)現(xiàn)冪等的方式其實(shí)都是大同小異的,類似的還有使用狀態(tài)機(jī)、悲觀鎖、樂觀鎖的方式來實(shí)現(xiàn),都是比較簡單的。
        總之,當(dāng)你去設(shè)計(jì)一個接口的時候,冪等都是首要考慮的問題,特別是當(dāng)你負(fù)責(zé)設(shè)計(jì)轉(zhuǎn)賬、支付這種涉及到 money 的接口,你要格外注意嘍!
        — 【 THE END 】—
        本公眾號全部博文已整理成一個目錄,請?jiān)诠娞柪锘貜?fù)「m」獲取!

        最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊,覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫、數(shù)據(jù)結(jié)構(gòu)等等。

        獲取方式:點(diǎn)“在看”,關(guān)注公眾號并回復(fù) PDF 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

        文章有幫助的話,在看,轉(zhuǎn)發(fā)吧。

        謝謝支持喲 (*^__^*)

        瀏覽 53
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(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>
            欧美性做爰又大又粗又长 | 一级A片60分钟免费看 | 青娱乐色色 | 亚洲AV无码一区二区三区七次郎 | 日本三级中文字幕在线观看 | 夜夜春夜夜爽 | 国语对白91 | 激情四射床戏 | 五月丁香爱爱 | 男女插插视频 |