自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

并發(fā)扣款一致性,冪等性問(wèn)題,這個(gè)話題還沒(méi)聊完?。?!

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

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

[[276190]]

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

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

  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; 

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

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

這樣是否可行?畫(huà)外音:額,撇開(kāi)業(yè)務(wù)不談,這個(gè)SQL用列做運(yùn)算,其實(shí)是不好的,建議使用:

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

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

  1. bool RegisterUser($uid, $name){ 
  2.          //查看uid是否已經(jīng)存在 
  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.          } 

有一個(gè)測(cè)試工程師,對(duì)該接口寫(xiě)了一個(gè)測(cè)試用例:

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

這是不是一個(gè)好的測(cè)試用例?這個(gè)用例存在什么問(wèn)題?

你會(huì)發(fā)現(xiàn),相同條件下,這個(gè)測(cè)試用例執(zhí)行兩次,得到的結(jié)果不一樣:

  • 第一次執(zhí)行,第一次造數(shù)據(jù),調(diào)用接口,注冊(cè)成功;
  • 第二次執(zhí)行,又造了一次相同的數(shù)據(jù),調(diào)用接口,注冊(cè)會(huì)失敗;這不是一個(gè)好的測(cè)試用例,多次執(zhí)行結(jié)果不同。

什么是冪等性?

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

畫(huà)外音:Google一下,比我解釋得更好,但意思應(yīng)該說(shuō)清楚了。

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

只需要加一行代碼:

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

這樣,在相同條件下,不管這個(gè)用例執(zhí)行多少次,得到的測(cè)試結(jié)果都是相同的。 是不是對(duì)冪等性有點(diǎn)感覺(jué)了。 讀請(qǐng)求,一般是冪等的。

寫(xiě)請(qǐng)求,視情況而定:

  • insert x,一般來(lái)說(shuō)不是冪等的,重復(fù)插入得到的結(jié)果不一定一樣
  • delete x,一般來(lái)說(shuō)是冪等的,刪除多次得到的結(jié)果仍相同
  • 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; 

不是冪等操作。

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

重試。 重試,是異常處理里很常見(jiàn)的手段。

你在寫(xiě)業(yè)務(wù)的時(shí)候有沒(méi)有寫(xiě)過(guò)這樣的代碼:

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

當(dāng)然,又會(huì)有朋友抬杠了,我從來(lái)不重試!!!

畫(huà)外音:額,這是合格,還是不合格呢?

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

  • 站點(diǎn)框架有沒(méi)有自動(dòng)重試?
  • 服務(wù)框架有沒(méi)有自動(dòng)重試?
  • 服務(wù)連接池,數(shù)據(jù)庫(kù)連接池有沒(méi)有自動(dòng)重試?

畫(huà)外音:

  • 服務(wù)化分層的架構(gòu)中,建議只入口層重試,服務(wù)層不要重試,防止雪崩;
  • dubbo底層,調(diào)用超時(shí)是默認(rèn)重試的,這個(gè)設(shè)計(jì)不好;

因此,在有重試的架構(gòu)體系里,冪等性是需要考慮的一個(gè)問(wèn)題。

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

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

畫(huà)外音:充了100電話費(fèi),怎么多了200塊?

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

【本文為51CTO專(zhuān)欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】

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

 

責(zé)任編輯:趙寧寧 來(lái)源: 51CTO
相關(guān)推薦

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ā)場(chǎng)景悲觀鎖

2022-08-11 07:55:05

數(shù)據(jù)庫(kù)Mysql

2024-04-11 13:45:14

Redis數(shù)據(jù)庫(kù)緩存

2024-11-14 07:10:00

2016-11-29 09:00:19

分布式數(shù)據(jù)一致性CAS

2017-07-25 14:38:56

數(shù)據(jù)庫(kù)一致性非鎖定讀一致性鎖定讀

2022-09-06 15:30:20

緩存一致性

2022-12-14 08:23:30

2019-02-13 11:04:42

系統(tǒng)緩存軟件

2019-09-18 08:41:53

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

2021-04-24 16:58:03

數(shù)據(jù)庫(kù)工具技術(shù)

2023-04-13 08:15:47

Redis緩存一致性

2023-12-01 13:51:21

數(shù)據(jù)一致性數(shù)據(jù)庫(kù)

2021-02-05 08:00:48

哈希算法?機(jī)器

2019-03-27 13:56:39

緩存雪崩穿透

2021-02-02 12:40:50

哈希算法數(shù)據(jù)

2025-03-10 09:20:00

庫(kù)存異常Redis架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)