議程8 - Use API Gateway and Go service to achieve HTTP idempotencier - Gaston Chiu

tags: GopherDay2024 Agenda
HackMD Error: 403 error

Slido 連結

[投影片連結]

key question: 解決 server/client behavior 不一致導致重複操作

案例:
client 請求下單扣款,server 已經完成扣款,responce 時封包丟失等等,導致 client 認為 request failed,嘗試重送,導致重複扣款。

解決方法:
透故前後端約定好的 unique key 作為交易 idempotencier,當 server 收到同樣的 idempotencier 且 payload hash 相同,直接回 success(2xx)。

POST 比較需要 idenpotency key,GET, PUT, DELETE 不需要因為可以多執行幾次

實作上參考 RFC

如果 body/header hash 跟上一次同一個 idempotency key 對應的 body/header hash 不同,就回 422 Unprocessable

Solution

  1. 用 url, body, whitelisted header 算出 request fingerprint
  2. Lock idempotency key
  3. 看這個 key + fingerprint 是否已經有 cached response
  4. 沒有再去 process、set to cache

不同 microservice 的統一

  • 寫一個 Kong gateway plugin
  • 把 idempotency 相關邏輯拆成一個 service,由 Gateway Plugin 呼叫

Idempotency service

  • Request lock: idempotency key and lock duration
    • 前提:透過 redis 做 lock server & cache server
    • random value: unlock 時會用到,保證 lock & unlock 的人是同一個
    • 使用 redsync

Lock Storage

  • Redis replication: easy to setup, but may lose data
    • 當 master 還有廣播到 replica 就被 kill,新成為 master 的 node 的 memory 中並沒有這筆資料(沒有任何 persistance value)
  • Redlock: redis distributed lock 演算法
  • ddia 作者 Martin Kleppmann:遇到 GC 時長超過 timeout 時,redlock 也會失效
  • AWS MemoryDB for Redis: 把 redis 加上 transaction log,確保 failover 時不會造成 data loss

最終決定是採用 Redis replication,且可能會 migrate 到 MemoryDB for Redis

Select a repo