偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

并發(fā)扣款一致性,冪等性問題,這個話題還沒聊完!??!

開發(fā) 開發(fā)工具
《并發(fā)扣款,如何保證數據的一致性?》,分享了同一個用戶并發(fā)扣款時,有一定概率出現數據不一致,可以使用CAS樂觀鎖的方式,在不降低吞吐量,并且只有少量修改的情況下,保證數據的一致性。

并發(fā)扣款,如何保證數據的一致性?》,分享了同一個用戶并發(fā)扣款時,有一定概率出現數據不一致,可以使用CAS樂觀鎖的方式,在不降低吞吐量,并且只有少量修改的情況下,保證數據的一致性。

[[276190]]

文章發(fā)布不到24小時,就有近200的評論。

其中,問的比較多的是ABA問題,這個問題已經在《并發(fā)扣款一致性優(yōu)化,CAS下ABA問題,這個話題還沒聊完!!!》中擴展。 其次,問的比較多的是作業(yè)題,為什么一定要用select&set的方式進行余額寫回:

  1. UPDATE t_yue SET money=$new_money WHERE uid=$uid AND money=$old_money;  

為什么不能采用直接扣減的方法:

  1. UPDATE t_yue SET moneymoney=money-$diff WHERE uid=$uid; 

很人說,在并發(fā)情況下,會將money扣成負數。 為了保證余額不被扣成負數,再加一個where條件:

  1. UPDATE t_yue SET moneymoney=money-$diff WHERE uid=$uid AND money-$diff>0; 

這樣是否可行?畫外音:額,撇開業(yè)務不談,這個SQL用列做運算,其實是不好的,建議使用:

  1. UPDATE t_yue SET moneymoney=money-$diff WHERE uid=$uid AND money>$diff; 

很遺憾,仍然不行。原因在《并發(fā)扣款,如何保證數據的一致性?》一文里點贊最多的評論,不冪等。畫外音:說明絕大部分同學,能夠回答正確作業(yè)。 聊冪等性之前,先看另一個測試用例的case。 假設有一個服務接口,注冊新用戶:

  1. bool RegisterUser($uid, $name){ 
  2.          //查看uid是否已經存在 
  3.          select uid from t_user where uid=$uid; 
  4.          //不是新用戶,返回失敗 
  5.          if(rows>0)return false; 
  6.          else{ 
  7.                    //把新用戶插入用戶表 
  8.                    insert into t_user values($uid, $name); 
  9.                    //返回成功 
  10.                    return true; 
  11.          } 

有一個測試工程師,對該接口寫了一個測試用例:

  1. bool TestCase_RegisterUser(){ 
  2.          //造一些假數據 
  3.          long uid=123
  4.          String name='shenjian'
  5.          //調用被測試的接口 
  6.          bool resultRegisterUser(uid,name); 
  7.          //預期注冊成功,對結果進行斷言判斷 
  8.          Assert(result,true); 
  9.          //返回測試結果 
  10.          return result; 

這是不是一個好的測試用例?這個用例存在什么問題?

你會發(fā)現,相同條件下,這個測試用例執(zhí)行兩次,得到的結果不一樣:

  • 第一次執(zhí)行,第一次造數據,調用接口,注冊成功;
  • 第二次執(zhí)行,又造了一次相同的數據,調用接口,注冊會失敗;這不是一個好的測試用例,多次執(zhí)行結果不同。

什么是冪等性?

相同條件下,執(zhí)行同一請求,得到的結果相同,才符合冪等性。

畫外音:Google一下,比我解釋得更好,但意思應該說清楚了。

如何將上面的測試用例改為符合“冪等性”的測試用例呢?

只需要加一行代碼:

  1. bool TestCase_RegisterUser(){ 
  2.          //造一些假數據 
  3.          long uid=123
  4.          String name=’shenjian’; 
  5.          //先刪除這個偽造的用戶 
  6.          DeleteUser(uid); 
  7.          //調用被測試的接口 
  8.          bool resultRegisterUser(uid,name); 
  9.          //預期注冊成功,對結果進行斷言判斷 
  10.          Assert(result,true); 
  11.          //返回測試結果 
  12.          return result; 

這樣,在相同條件下,不管這個用例執(zhí)行多少次,得到的測試結果都是相同的。 是不是對冪等性有點感覺了。 讀請求,一般是冪等的。

寫請求,視情況而定:

  • insert x,一般來說不是冪等的,重復插入得到的結果不一定一樣
  • delete x,一般來說是冪等的,刪除多次得到的結果仍相同
  • set a=x是冪等的
  • set a=a-x不是冪等的

因此,這么扣減余額:

  1. UPDATE t_yue SET money=$new_money WHERE uid=$uid AND money=$old_money; 

是冪等操作。

要是這么扣減余額:

  1. UPDATE t_yue SET moneymoney=money-$diff WHERE uid=$uid AND money-$diff>0; 

不是冪等操作。

聊到這里,或許有朋友要抬杠了,測試用例會重復執(zhí)行,扣款怎么會重復執(zhí)行呢?

重試。 重試,是異常處理里很常見的手段。

你在寫業(yè)務的時候有沒有寫過這樣的代碼:

  1. result = DoSomething(); 
  2. if(false==result || TIMEOUT){ 
  3.          //錯誤,或者超時,重試一次 
  4.          resultDoSomething(); 
  5. return result; 

當然,又會有朋友抬杠了,我從來不重試!!!

畫外音:額,這是合格,還是不合格呢?

你可以決定業(yè)務代碼怎么寫,你不能決定底層框架代碼怎么寫:

  • 站點框架有沒有自動重試?
  • 服務框架有沒有自動重試?
  • 服務連接池,數據庫連接池有沒有自動重試?

畫外音:

  • 服務化分層的架構中,建議只入口層重試,服務層不要重試,防止雪崩;
  • dubbo底層,調用超時是默認重試的,這個設計不好;

因此,在有重試的架構體系里,冪等性是需要考慮的一個問題。

現在該懂了,為啥扣款和充值業(yè)務,一般使用:select&set,配合CAS方案

而不使用:set money-=X方案

畫外音:充了100電話費,怎么多了200塊?

知其然,知其所以然,希望大家有收獲。

【本文為51CTO專欄作者“58沈劍”原創(chuàng)稿件,轉載請聯系原作者】

戳這里,看該作者更多好文

 

責任編輯:趙寧寧 來源: 51CTO
相關推薦

2019-09-05 08:54:38

一致性CASABA

2022-10-19 12:22:53

并發(fā)扣款一致性

2019-08-30 12:46:10

并發(fā)扣款查詢SQL

2024-01-10 08:01:55

高并發(fā)場景悲觀鎖

2022-08-11 07:55:05

數據庫Mysql

2024-04-11 13:45:14

Redis數據庫緩存

2024-11-14 07:10:00

2016-11-29 09:00:19

分布式數據一致性CAS

2017-07-25 14:38:56

數據庫一致性非鎖定讀一致性鎖定讀

2022-12-14 08:23:30

2022-09-06 15:30:20

緩存一致性

2021-04-24 16:58:03

數據庫工具技術

2019-09-18 08:41:53

并發(fā)扣減一致性redis

2023-12-01 13:51:21

數據一致性數據庫

2019-02-13 11:04:42

系統(tǒng)緩存軟件

2023-04-13 08:15:47

Redis緩存一致性

2021-02-05 08:00:48

哈希算法?機器

2021-02-02 12:40:50

哈希算法數據

2019-03-27 13:56:39

緩存雪崩穿透

2025-03-10 09:20:00

庫存異常Redis架構
點贊
收藏

51CTO技術棧公眾號