淺談冪等設計

来源: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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...