日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
并發(fā)扣款一致性,冪等性問題,這個(gè)話題還沒聊完?。?!

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

創(chuàng)新互聯(lián)建站堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:做網(wǎng)站、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的鋼城網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

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

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

 
 
 
 
  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;

這樣是否可行?畫外音:額,撇開業(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)論,不冪等。畫外音:說(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.          }
  12. }

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

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

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

你會(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é)果相同,才符合冪等性。

畫外音: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 result= RegisterUser(uid,name);
  9.          //預(yù)期注冊(cè)成功,對(duì)結(jié)果進(jìn)行斷言判斷
  10.          Assert(result,true);
  11.          //返回測(cè)試結(jié)果
  12.          return result;
  13. }

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

寫請(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í)行呢?

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

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

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

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

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

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

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

畫外音:

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

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

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

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

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

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

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


分享文章:并發(fā)扣款一致性,冪等性問題,這個(gè)話題還沒聊完!??!
網(wǎng)站URL:http://www.dlmjj.cn/article/cciisgg.html