淺談冪等設計

来源:https://www.cnblogs.com/jingdongkeji/archive/2023/09/04/17677722.html
-Advertisement-
Play Games

如今隨著互聯網技術快速發展,業務越來越複雜,系統的高併發和關鍵數據的場景越來越多。在分散式系統中,機器宕機和消息丟失也是需要重點關註的問題,其中的一個典型就是冪等性問題。 ...


1 冪等性

一句話,冪等就是一個執行操作,無論執行多少次,產生的效果和返回的結果都是一樣的。

2 為什麼要實現冪等性?

如今隨著互聯網技術快速發展,業務越來越複雜,系統的高併發和關鍵數據的場景越來越多。

在分散式系統中,機器宕機和消息丟失也是需要重點關註的問題,其中的一個典型就是冪等性問題。

想想看,一個對外暴露的介面會面領很多次請求,如果不能保證冪等性會帶來什麼樣的後果?

微信進行一次扣款操作,應該只扣用戶一次錢,當遇到網路故障或系統bug,如果沒有實現冪等性扣多了你會不會直接“C語言”投訴?

當然,有些介面是天然保證冪等性的,比如查詢操作、刪除操作。有些對數據的修改是一個常量,無其他操作,也是具有冪等性的。修改操作可能冪等可能不冪等。

SELECT col1 FROM tab1 WHERE col2 = 2UPDATE tab1 SET col1 = 1 WHERE col2 = 2UPDATE tab1 SET col1 = col1 + 1 WHERE col2 = 2

這三個sql只有第三個不是冪等的。

POST請求天生就不是一個冪等操作,每次調用都會在系統中產生新的資源,想要冪等就必須在業務中實現。

需要避免的是,冪等性和併發安全不是一回事。當同一筆訂單即使你不停的提交支付,如果扣了不止一次錢,就說明該操作不冪等。

而有多筆訂單同時進行支付,最後扣除的金額不是這麼多筆金額的總和,說明該操作有併發安全問題。這是兩個維度的問題,應該分開討論解決。

3 如何實現冪等性?

(1)資料庫防重

利用數據表唯一索引的特性,當併發時新增報錯時,再查詢一次,數據已經存在,就避免了臟數據的新增。但註意,不要將uuid作為索引欄位,其大小和類型對於索引而言都會導致速度非常慢。

常見的場景,比如博客/微博系統點贊,一個用戶對一個微博點贊,就把用戶id與該博文id綁定,後續該用戶再對該博文點贊就無法插入。再比如金融賬戶,可以通過在賬戶表中增加唯一索引來存儲用戶id,即使重覆操作一個用戶也只能擁有一個賬戶。

(2)token令牌機制

token機制是適用範圍最廣泛的一種冪等設計。雖然實現方式有很多種,但核心思想就是每次操作都生成一個唯一token憑證,伺服器通過這個唯一憑證確保同樣的操作不會被執行多次。

具體可以分為兩個階段,獲取token和使用token。每次介面請求前先獲取一個token,然後在下次請求時在請求的header體中加上這個token,後端進行校驗,如果驗證通過則刪除token,下次請求再次判斷token。如果在redis緩存的幫助下,流程圖如下:

(3)分散式鎖

資料庫防重表可以通過分散式鎖代替,相比去重表,將放併發做到了緩存中,效率更高。局限性都是同一時間只能完成一次請求。

比如某些業務處理流程很長,要求不能併發執行,可以在流程執行之前根據某個標誌(用戶ID+尾碼等)獲取分散式鎖,其他流程執行時獲取鎖就會失敗,也就是同一時間該流程只能有一個能執行成功,執行完成後,釋放分散式鎖。

4 冪等的優缺點

優點:

業務需要

缺點:

(1)客戶端處理邏輯得以簡化,但服務端控制冪等邏輯變得更加複雜;

(2)把併發執行變成改為串列執行,降低了執行效率。

5 擴展

分散式自增ID可以借鑒Snowflake演算法,優點是高性能、低延遲、按時間有序;缺點是需要獨立的開發和部署。

其結構如下:

  • 最高位是符號位,始終為0,不可用。
  • 41位的時間序列,精確到毫秒級,41位的長度可以使用 (1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年。時間位還有一個很重要的作用是可以根據時間進行排序。註意,41位時間截不是存儲當前時間的時間截,而是存儲時間截的差值(當前時間截 - 開始時間截) 後得到的值,這裡的的開始時間截,一般是我們的id生成器開始使用的時間,由我們程式來指定的。
  • 10位的機器標識,10位的長度最多支持部署1024個節點。
  • 12位的計數序列號,序列號即一系列的自增id,可以支持同一節點同一毫秒生成多個ID序號,12位的計數序列號支持每個節點每毫秒產生4096個ID序號。

加起來剛好64位,為一個Long型。這個演算法很簡潔,但依舊是一個很好的ID生成策略。

參考文獻:

[1] 分散式系統互斥性與冪等性問題的分析與解決

https://zhuanlan.zhihu.com/p/22820761

[2] 高併發下介面冪等性解決方案

https://blog.csdn.net/u011635492/article/details/81058153

[3] 冪等性問題和解決方法

https://blog.csdn.net/qq_32020035/article/details/105448889

[4] 雪花演算法

https://www.cnblogs.com/grasp/p/12309726.html

[5] 聊聊開發中冪等問題

https://segmentfault.com/a/1190000018808510

作者:京東零售 李澤陽

來源:京東雲開發者社區 轉載請註明來源


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • # Redis 文章內容主要參考b站 運維實戰課程 的redis視頻:[redis的課程介紹_嗶哩嗶哩_bilibili](https://www.bilibili.com/video/BV1cP4y1D7yh?p=1) ## 簡介 1.Redis是一個緩存資料庫,主要是做緩存。什麼是緩存?也就是緩 ...
  • [toc] # Linux運維工程師面試題(6) > 祝各位小伙伴們早日找到自己心儀的工作。 > 持續學習才不會被淘汰。 > 地球不爆炸,我們不放假。 > 機會總是留給有有準備的人的。 > 加油,打工人! ## 1 資料庫事務的四個特性及含義 資料庫事務的4個特性:原⼦性、持久性、⼀致性、隔離性 - ...
  • 哈嘍大家好,我是鹹魚 我們知道字典是 Python 中最重要且最有用的內置數據結構之一,它們無處不在,是語言本身的基本組成部分 我們可以使用字典來解決許多編程問題,那麼今天我們就來看看**如何在 Python 中遍歷字典** 全文內容:https://realpython.com/iterate-t ...
  • 寶塔Linux面板是提升運維效率的伺服器管理軟體,目前使用免費的版本功能齊全,已經足夠使用了。 [西瓜程式猿]使用阿裡雲伺服器網以CentOS操作系統為例,安裝寶塔Linux面板,先遠程連接到雲伺服器,然後執行寶塔面板安裝命令,系統會自動安裝寶塔面板,安裝完成後會返回面板地址、賬號和密碼 。 ...
  • 本篇文章探索了文件系統的功能規劃,著重討論了文件存儲、索引節點和目錄項的管理、緩存策略以及文件數據的存儲等方面。文件系統作為電腦系統中重要的組成部分,對於實現高效、可靠的文件管理與訪問機制至關重要。通過深入瞭解文件系統的基本單位、元信息記錄和目錄結構,我們可以更好地理解文件系統的工作原理,本文旨在... ...
  • ![](https://img2023.cnblogs.com/blog/3076680/202309/3076680-20230904164459431-1322523641.png) # 1. 儘管SQL標準指定了部分函數,但資料庫廠商並沒有遵循這些函數規範 # 2. 字元串 ## 2.1. c ...
  • 1. SQL語句類型 1. DDL(Data Definition Language,數據定義語言): DDL語句用於定義資料庫對象(如表、索引、視圖等)。常見的DDL語句包括: CREATE:用於創建資料庫對象,如創建表、索引、視圖等。 ALTER:用於修改資料庫對象的結構,如修改表的列、添加約束 ...
  • Redis OSS的邏輯資料庫,無論是自部署還是作為ElastiCache等托管服務啟動,其目的都是通過減少管理需求並提供一系列的預設設置來簡化開發人員的工作。然而,在實際生產中,當您的功能和操作需求發生變化時,單個Redis實例可能不再足夠。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...