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>

        阿里面試官:接口的冪等性怎么設計?

        共 1948字,需瀏覽 4分鐘

         ·

        2021-07-10 22:52

        今日推薦
        SpringBean默認是單例的,高并發(fā)情況下,如何保證并發(fā)安全?
        “團隊禁止使用Lombok”,被我狠狠的反駁了!
        別去外包
        盤點 12 個 GitHub 上的高仿項目
        CTO 說了,用錯 @Autowired 和 @Resource 的人可以領盒飯了
        用鴻蒙跑了個 hello world

        一、什么是冪等?

        看一下維基百科怎么說的:

        圖片

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

        二、使用冪等的場景

        1、前端重復提交

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

        2、接口超時重試

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

        3、消息重復消費

        在使用消息中間件來處理消息隊列,且手動 ack 確認消息被正常消費時。如果消費者突然斷開連接,那么已經(jīng)執(zhí)行了一半的消息會重新放回隊列。

        當消息被其他消費者重新消費時,如果沒有冪等性,就會導致消息重復消費時結果異常,如數(shù)據(jù)庫重復數(shù)據(jù),數(shù)據(jù)庫數(shù)據(jù)沖突,資源重復等。

        三、解決方案

        1、token 機制實現(xiàn)

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

        示意圖如下:

        圖片

        具體流程步驟:

        1. 客戶端會先發(fā)送一個請求去獲取 token,服務端會生成一個全局唯一的 ID 作為 token 保存在 redis 中,同時把這個 ID 返回給客戶端

        2. 客戶端第二次調(diào)用業(yè)務請求的時候必須攜帶這個 token

        3. 服務端會校驗這個 token,如果校驗成功,則執(zhí)行業(yè)務,并刪除 redis 中的 token

        4. 如果校驗失敗,說明 redis 中已經(jīng)沒有對應的 token,則表示重復操作,直接返回指定的結果給客戶端

        注意:

        1. 對 redis 中是否存在 token 以及刪除的代碼邏輯建議用 Lua 腳本實現(xiàn),保證原子性

        2. 全局唯一 ID 可以用百度的 uid-generator、美團的 Leaf 去生成

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

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

        示意圖如下:

        圖片

        具體流程步驟:

        1. 建立一張去重表,其中某個字段需要建立唯一索引

        2. 客戶端去請求服務端,服務端會將這次請求的一些信息插入這張去重表中

        3. 因為表中某個字段帶有唯一索引,如果插入成功,證明表中沒有這次請求的信息,則執(zhí)行后續(xù)的業(yè)務邏輯

        4. 如果插入失敗,則代表已經(jīng)執(zhí)行過當前請求,直接返回

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

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

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

        該命令在設置成功時返回 1,設置失敗時返回 0。

        示意圖如下:

        圖片

        具體流程步驟:

        1. 客戶端先請求服務端,會拿到一個能代表這次請求業(yè)務的唯一字段

        2. 將該字段以 SETNX 的方式存入 redis 中,并根據(jù)業(yè)務設置相應的超時時間

        3. 如果設置成功,證明這是第一次請求,則執(zhí)行后續(xù)的業(yè)務邏輯

        4. 如果設置失敗,則代表已經(jīng)執(zhí)行過當前請求,直接返回

        總結

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

        總之,當你去設計一個接口的時候,冪等都是首要考慮的問題,特別是當你負責設計轉賬、支付這種涉及到 money 的接口,你要格外注意嘍!

        推薦文章


        1、14個項目!
        2、Spring Boot + Security + MyBatis + Thymeleaf + Activiti 快速開發(fā)平臺項目
        3、推薦幾個支付項目!
        4、寫博客能月入10K?
        5、一款基于 Spring Boot 的現(xiàn)代化社區(qū)(論壇/問答/社交網(wǎng)絡/博客)

        更多項目源碼

        1、推薦兩個項目!
        2、重磅推薦:一套開源的網(wǎng)校系統(tǒng),無論是自建網(wǎng)校還是接副業(yè)都很方便
        3、一款基于 Spring Boot 的現(xiàn)代化社區(qū)(論壇/問答/社交網(wǎng)絡/博客)
        4、13K點贊都基于 Vue+Spring 前后端分離管理系統(tǒng)ELAdmin,大愛
        5、想接私活時薪再翻一倍,建議根據(jù)這幾個開源的SpringBoot
        瀏覽 48
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        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>
            欧美亚洲中文字幕| 国产酒店自拍| 无码精品视频在线观看| 美日韩三级| 五月乱伦| 国产激情精品| 色哟哟一区二区三区四区| 亲子伦视频一区二区三区| 亚洲成人视频在线| 久久人妻无码中文字幕系列|