自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

系統(tǒng)
自己最近負(fù)責(zé)的幾個(gè)接口,都涉及到了冪等性的操作,抽空總結(jié)了一下,這也是面試官比較愛(ài)問(wèn)的問(wèn)題。

 [[377084]]

大家好,我是狂聊。

自己最近負(fù)責(zé)的幾個(gè)接口,都涉及到了冪等性的操作,抽空總結(jié)了一下,這也是面試官比較愛(ài)問(wèn)的問(wèn)題。

一、什么是冪等?

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


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

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

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

用戶(hù)注冊(cè),用戶(hù)創(chuàng)建商品等操作,前端都會(huì)提交一些數(shù)據(jù)給后臺(tái)服務(wù),后臺(tái)需要根據(jù)用戶(hù)提交的數(shù)據(jù)在數(shù)據(jù)庫(kù)中創(chuàng)建記錄。如果用戶(hù)不小心多點(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. 客戶(hù)端會(huì)先發(fā)送一個(gè)請(qǐng)求去獲取 token,服務(wù)端會(huì)生成一個(gè)全局唯一的 ID 作為 token 保存在 redis 中,同時(shí)把這個(gè) ID 返回給客戶(hù)端
  2. 客戶(hù)端第二次調(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é)果給客戶(hù)端

注意:

  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. 客戶(hù)端去請(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。

示意圖如下:


具體流程步驟:

  • 客戶(hù)端先請(qǐng)求服務(wù)端,會(huì)拿到一個(gè)能代表這次請(qǐng)求業(yè)務(wù)的唯一字段
  • 將該字段以 SETNX 的方式存入 redis 中,并根據(jù)業(yè)務(wù)設(shè)置相應(yīng)的超時(shí)時(shí)間
  • 如果設(shè)置成功,證明這是第一次請(qǐng)求,則執(zhí)行后續(xù)的業(yè)務(wù)邏輯
  • 如果設(shè)置失敗,則代表已經(jīng)執(zhí)行過(guò)當(dāng)前請(qǐng)求,直接返回

總結(jié)

這幾種實(shí)現(xiàn)冪等的方式其實(shí)都是大同小異的,類(lèi)似的還有使用狀態(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 的接口,你要格外注意嘍!

責(zé)任編輯:姜華 來(lái)源: 狂聊Java
相關(guān)推薦

2023-09-01 15:27:31

2023-11-27 08:32:02

元素HashMap

2021-09-27 07:11:18

MySQLACID特性

2021-11-05 10:07:13

Redis哈希表存儲(chǔ)

2019-11-21 08:40:44

面試官優(yōu)化性能

2021-01-18 14:34:59

冪等性接口客戶(hù)端

2022-11-06 18:17:43

Java核心系統(tǒng)鏈路

2024-03-13 15:18:00

接口冪等性高并發(fā)

2022-11-25 17:29:27

分布式事務(wù)

2023-11-06 17:39:35

JavaArrayList線程

2021-01-13 11:23:59

分布式冪等性支付

2020-07-15 08:14:12

高并發(fā)

2025-02-26 08:20:18

2020-02-25 16:56:02

面試官有話想說(shuō)

2023-11-29 08:00:53

JavaTreeMap底層

2022-03-22 07:57:42

Java多線程并發(fā)

2025-03-17 08:07:11

2021-09-08 08:06:57

Redis原子性數(shù)據(jù)類(lèi)型

2021-07-04 15:16:14

索引B+數(shù)據(jù)庫(kù)

2021-03-28 09:45:05

冪等性接口數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)