使用redis設計冪等介面

2021-07-14 00:01:34 字數 2891 閱讀 6560

冪等:

冪等性是系統的介面對外一種承諾(而不是實現), 承諾只要呼叫介面成功, 外部多次呼叫對系統的影響是一致的. 宣告為冪等的介面會認為外部呼叫失敗是常態, 並且失敗之後必然會有重試

舉個例子:

有乙個訂單系統,對外提供了乙個處理介面,

如果有個訂單001是要扣除使用者的100塊錢,那麼訂單001被多次呼叫,

也只會處理成功一次,也就是只會扣除使用者100塊。

也可以理解為去除重複呼叫

訂單的狀態:

a) 無記錄

b) 正在被處理

c) 處理成功

我們需要考慮多種情況:

情況1:

a) a執行緒開始處理訂單001

b) a執行緒處理訂單001成功

c) a執行緒記錄訂單001處理成功

情況2:

a) a執行緒開始處理訂單001

b) a執行緒處理訂單001失敗,回滾

c) a執行緒刪除訂單001的記錄

情況3:

a) a執行緒已成功處理訂單001

b) b執行緒開始處理訂單001,發現訂單001已經被成功處理,放棄此次處理

情況4:

a) a執行緒開始處理訂單001,正在處理中

b) b執行緒開始處理訂單001,發現訂單001正在被處理且未超時,放棄此次處理

情況5:

a) a執行緒開始處理訂單001,且超時了釋放了訂單001的狀態

b) b執行緒開始處理訂單001,發現訂單001無人處理,那麼鎖定訂單001開始處理

我們用redis來設計處理的冪等性,但是需要注意的是,這裡冪等性的有效期依賴redis的key的生命週期:

a) 正在處理,假設5分鐘則認為處理超時(這個值需要根據程式的處理邏輯的超時時間設定)

set 訂單號                         時間戳                過期時間

set 1893505609317740 1466849127 ex 300 nx

b) 成功處理,利用set的時間戳控制設定權

set 訂單號                       成功  過期時間

set 1893505609317740 0 ex 86400 xx

c) 刪除訂單,只允許建立者刪除,利用set的時間戳控制刪除權

del 1893505609317740

上python示範**:

# -*- coding: utf-8 -*-

import time

import redis

def check_validity(orderno, del_time):

return true

def deal():

return true

if __name__ == '__main__':

# 連線redis

r = redis.strictredis(host='localhost', port=6379, db=0)

# 訂單號

orderno = "1893505609317740"

# 當前時間戳

sec = int(time.time())

# 處理超時時間

deal_timeout = 300

# 訂單狀態儲存多久,比如24小時不支付就失效了

del_time = 86400

# 是否成功處理

status = false

# 檢查訂單的有效期

if check_validity(orderno, del_time):

print "orderno is ok"

else:

print "orderno is overdue"

exit()

# 試圖鎖住訂單

res = r.set(orderno, sec, ex=deal_timeout, nx=true)

if res == true:

print "set key succeed"

else:

print "set key failed, key maybe exist, return"

exit()

# 成功處理了/失敗了

status = deal()

# 更改訂單狀態

redis_sec = r.get(orderno)

if sec != int(redis_sec):

print "check timestamp failed"

exit()

else:

print "check timestamp success"

if status == true:

# 設定訂單處理成功.設定為0

res = r.set(orderno, 0, ex=del_time, xx=true)

print "deal succeed: %s" % res

else:

# 刪除訂單

res = r.delete(orderno)

print "deal failed: %s" % res

小結:

這種設計依然有缺陷,但是能保證大部分的訂單是冪等性的,

首先要保證redis是高可用,

其次訂單的處理過期時間很重要,不能隨意設定,必須根據程式處理流程推理出來,

其次redis的儲存空間也影響了訂單的狀態儲存多久。

介面冪等設計

在系統設計時,經常會出現每次操作結果都需要一致的場景。比如典型的restful get請求 每次請求url student 1 查詢第乙個學生 結果都是一樣的。當然排除再修改學生資訊後又查詢的情況。介面冪等,通俗的定義可以為 每次同樣的請求操作該介面,得到的結果都是一樣的。先給個場景,同樣的訂單編號...

介面冪等性設計

在系統中,乙個介面執行多次,與執行一次的效果是一致的 冪等性的核心思想 通過唯一的業務單號保證冪等 update自身帶鎖。直接update不會出現併發修改問題。樂觀鎖是先查詢在修改 update 商品表 set 庫存 庫存 購買量 version 查詢version值 1 where version...

關於介面冪等性的設計

關於支付相關,訂單相關以及一些涉及費用的操作在業務上都是要求介面具有冪等性的。否則在高併發的場景下,同一筆交易請求多次,則會造成損失,這是不可忽視的錯誤。例如一筆訂單,因為網路或者操作的原因,造成同時發起了兩次申請。一般的介面設計中,對於重 起的交易都是先查詢是否存在這筆訂單,如果不存在,則繼續進行...