高併發下怎麼做餘額扣減?

時間 2021-05-06 02:46:45

1樓:瀟湘夜雨

餘額的扣減的方式通常有以下幾類:

1、基於第三方元件的分布式鎖實現

2、for update的行悲觀鎖

3、基於cas的樂觀鎖

這幾類以及效能優化前面都有說明,我補充一下第三個基於cas導致的ABA問題的解決思路:

ABA問題是由CAS衍生來的,在併發極端情況下會產生,那麼什麼是ABA問題?

標準的描述如下:

併發1(上):獲取出資料的初始值是A,後續計畫實施CAS樂觀鎖,期望資料仍是A的時候,修改才能成功

併發2:將資料修改成B

併發3:將資料修改回A

併發1(下):CAS樂觀鎖,檢測發現初始值還是A,進行資料修改。

上述併發環境下,併發1在修改資料時,雖然還是A,但已經不是初始條件的A了,中間發生了A變B,B又變A的變化,此A已經非彼A,資料卻成功修改,可能導致錯誤,這就是CAS引發的所謂的ABA問題。

舉乙個遊戲充值例子,如下:

按照業務的訴求,事務3是最終將資料庫結果值恢復為100,但是通過cas比較更新最終結果出現了40,這個就是ABA導致的問題。

我們以扣款的sql作為例子講解ABA問題如何解決?

1、資料庫表結構由(id、money)修改為(id、money、version)

2、資料庫查詢由之前的

select money from t_account where id=#

修改為select money,version from t_account where id=$

3、資料庫修改除了cas比較外,還需要版本相同,並且進行版本修改

update t_account set money=# where id=# and money=#;

修改為update t_account set money=# where id=# and money=# and version=#

2樓:程式設計師到工程師

方案不具有工程化,餘額修改前不關心餘額具體是多少,只關心到底能否修改成功,修改後可能需要關心餘額多少,一條語句可以搞定,inc balance -10 if balance gte 10,大多數資料庫這種命令都有,並且是保證了原子操作的,這樣也還是會出乙個可重入問題,比如提現,下單影響餘額的動作,下同乙個訂單不可能出現兩次餘額修改那就只有靠訂單、提現的id來標識,也就是乙個id只能執行一次餘額變化,即Inc balance -10 if balance gte 10 and billid not in allbalancebillids,即沒用事物也不用讀,只需要一次訪問,也減少資料庫壓力

3樓:Sir Chen

我的通常方案是盡可能保證正常情況下一條語句搞定updateCount = update user set money = money - 123 where user_id = 1 and money >= 123

if (updateCount == 0) {rollback// 餘額不足

如果這個滿足不了

1先嘗試優化業務減少這個請求

2拆庫拆表

3還是不行就用非同步模式,比如先寫一條日誌,最後非同步通過批處理日誌來決定是否成功(訊息同理)

4樓:

運營商從業,強答

首先這個是乙個系統問題,單方面的優化效果不理想,一般都會是使用記憶體資料庫並且更新操作為增量更新。

業務場景上

大多數個人使用者的併發場景極少,對於個人業務,一般是會加鎖處理,使用者也很難感知

集團業務不能加鎖,否則會導致集團成員需要序列訪問資源,這個一般就是允許賬本扣負或者使用後付費的方式(你可以理解為記賬,後面給錢),固定時間出賬,這樣也能夠繞過併發的問題

5樓:會飛的左輪

菜逼先匿了但還是想弱弱的假設幾句.

前提只是針對簡單的操作,複雜的事務在合併的時候,= = 要加補償機制,複雜度比較高.

冷資料直接操作,

熱點資料,公升級為彙總提交.check到臨界條件(比如2ms或者1000條或者餘額為臨界值) ,commit.最後喚醒當前熱點賬戶執行緒.

這個彙總的出入都要控制數量.並確保時效.感覺就像synchronized的公升級.

持久化使用nosql. redis的sentinel模式,開啟aof.確保HA.

redis中儲存部分餘額,跟上面某位大佬所說的凍結一樣的道理.

總體設計思路是,

當底層元件的效能無法滿足你的需求的時候.改做批量.在記憶體中基於業務做批量的優化操作.

----差.. 忘記點匿了, 居然不能重新匿刪了還不能新增....

6樓:原子筆

乙個賬戶乙個表,主鍵自增id..每個表最新一行插入時(緩)存前面行的sum,插入的條件就是原來的sum(就是id最大那行的快取)大於等於現在的扣費。

總之在行上做快取吧,如果你不想設計外源的快取方案。

7樓:朱涵俊

看有人說不用餘額,或許交易時候快了,但是查詢餘額不是比交易更頻繁的操作。

如果僅僅要避免扣成負數 sql where那裡新增判斷即可,update members set amount=amount-100 where sid=1 and amount>=100

剩下就是錢的問題。

8樓:jilen

可以看看cqrs或者說event sourcing那種思路,全程可事件溯源,最新狀態在記憶體中計算快照,只有插入沒有更新,甚至可以批量插入大幅度提公升效能。沒錯我說的是akka persistence,你值得擁有

9樓:公尺修的生活

優化嘛,都是根據情況一步步來,先用update 行鎖,如果效能下降了,分析是不是資料庫,如果是,想辦法提高到應用層解決,時效要求高不高,不高的話,事件佇列乙個個搞,高的話試試大家提到的redis和記憶體,在不行再考慮改設計,分布式,一步步來,簡單搞定沒定能稱個1年,下次再出問題了,再來搞(當然在不在這個專案或公司都是個問題。。。。),這就是傳說中的挖坑模式。。哈哈哈

10樓:Raynor

1. 盡早解決問題

把資料表查出來做快取,在快取中進行數值運算2. 分而治之

用分布式雜湊等方法把資料分為多個節點處理,降低單點壓力。

如果有雜湊節點故障,可以用一致性雜湊重定向節點。

3. 熱點降溫

降低資料快取更新到資料庫的頻率,做好binlog。

11樓:徐雙雙

寫操作一般不可能稱為瓶頸(尤其是update餘額,還不需要更新索引),除非出現死鎖。

既然是行級鎖,那麼update操作只針對乙個使用者的話,使用者的操作頻率肯定達不到爭奪鎖資源的地步,乙個使用者不可能在1秒內完成10次不同的消費。

然後就是多使用者併發問題,即100萬使用者同時update,那確實可能出現磁碟IO問題。這個時候就要做讀寫分離和分庫分表。

讀寫分離的作用是不要讓寫等待讀,讀的過程一般是比較慢的,如果讀的過程占用磁碟IO,那麼寫也會變得很慢。

而分庫分表則是乙個通用的分攤壓力的方案,不同使用者水平分割到不同的資料庫。同時採用SSD硬碟之類。

12樓:蘇佳

主要看併發到底有多高。不同層次的併發會有不同的設計方案。

舉個例子,

銀行在處理個人賬戶扣款,那Update操作基本問題不大的。因為乙個使用者不可能併發處理乙個賬戶。

當然作為借貸平衡的角度來看,有可能需要有另外乙個關聯賬戶,那麼這個時候會去借貸某乙個公共賬戶,為了避免這個賬戶的鎖的問題,這個賬戶通常被設計為以分行為單位,而且不同型別的交易使用不同的分行賬戶,那麼相同賬戶的併發率相對就很低了。

再比如代發工資,這種操作往往是用非同步批處理的方式執行,執行完一條記錄,執行第二條,那麼也不會發生併發的問題。

13樓:

mark 下明天來寫答案

今天已經是明天了。

高頻更新當中,一般來講,有幾個現成的解決方案。

第一,記住,任何效能問題,都可以用錢來解決,硬體加強,上更好的伺服器,更好的資料庫,更好的中介軟體總是能解決的,足夠大的硬體,加上記憶體資料庫,減少IO,總是能解決的。這點上,我們是窮人,我們先跳過

第二,我們嘗試從架構上解決這個問題,那麼,高頻更新的情況,如何做?你現在是單錶單字段,鎖表或者鎖行是避免不了的,最好的結果也是鎖行,當然你可以採用一些索引,消極鎖來一定程度上加快,但是效果有限。那麼有什麼更好的解決方案?

這點上大學本科教科書已經給出了答案:空間換時間。首先,高頻操作你要做精算分析,比如1秒響應10萬次,那麼單次最低扣減額根據正態分佈需要大約不超過總餘額的十萬分之一,否則有很大的概率幾秒就扣減完了,那你就這個高頻也沒有意義了。

這點上,題目並沒有明確寫出,所以我們只做理論研究,假設餘額足夠大,扣減能維持在高頻下極大時間。

那麼具體怎麼做?將你的扣減字段拆分,假設你原來的字段為T1.F1,那麼現在我們設定Tx.

F1,令 sum(T2.F1:Tx.

F1)=T1.F1看到這裡,你已經懂了,既然我扣減都發生在乙個欄位上,為什麼我不把這個欄位拆分成多個字段?比如我10個人用勺去乙個桶裡舀水,為什麼我不把這桶水分成5個子桶?

這樣的話,我原來10個序列操作,就變成了5個並行的2步序列,速度就會快上大於4倍,小於五倍。為什麼不是等於五倍?因為你的子桶每次更新以後,如果小於0,那麼還需要去總桶裡申請金額。

假設你的餘額有100K,你設定10個分表,那麼你的每個分表設定多少餘額?最簡單的做法是10K,然後扣減,扣減的操作隨機fit到這10個分表,任何分表扣減額度小於等於零,那麼再隨機向某一大於零的分表offset,並且關閉這個分表,直到最後乙個分表用完。這個架構還可以改進優化,這裡留給你做一道思考題。

簡單提示2點,1,操作不應該隨機fit分表,2,完全並行不如星型結構好

好,空間換時間是一種方案,我們還有另外一種方案,假設由於種種理由資料庫並不能分,那麼我們有什麼辦法?有,上一種方法,是高頻訪問單一資源,所以我們增加資源,那麼這一種方法,我們降頻。降頻的情況很簡單,我們考慮到,比如每X次扣減,當總額小於餘額的時候,扣減一次餘額和扣減X次餘額業務含義是一樣的。

這很好理解,你去超市買東西,不會每件東西給一次錢,而是加總給錢的,所以我們不必每次扣減都運算元據庫,你可以band扣減,在餘額尚足的情況下,你總是能成功的,如果你band100次扣減為乙個單位,你的效能就提公升了大約90倍。那麼如何處理某一次導致餘額不足的扣減呢?你這麼聰明,看到這裡已經懂了這是第二個思考題了,思路是一樣的。

如果你把這兩種方案組合起來用,會有什麼效果?

眼壓高怎麼做近視手術?

眼壓高一般不建議近視手術,除非近視手術能夠改變你的命運,比如為了通過公務員體檢。眼壓高是做不了近視手術的,需要先檢查看是什麼原因導致的眼壓高,眼壓控制後再來考慮近視手術。先去降眼壓唄,等壓眼壓穩定了,醫生覺得符合手術條件了,在考慮做近視手術吧。眼壓高建議使用降眼壓的藥物控制,等眼壓降到21 11正常...

負債高,徵信查詢過多怎麼做銀行低息產品過度?

忙季忙納 如果負債,要看負債率怎麼樣。但徵信花是很難再做信貸產品的。即便是銀行抵押也會參考徵信,不過相對信貸來說,條件還是寬鬆很多的。可以去銀行信貸部門問問,有沒有信貸新產品或者做抵押貸款的要求。有一點就是銀行是盈利機構,即使能做,利息相對徵信正常的客戶也會貴些。 廣州融資邱生 如果徵信逾期多 負債...

高富帥和白富美如果舍二選一,怎麼做選擇

郭大路 選帥和美啊,哈哈哈哈。錢可以再賺,但天生的帥哥美女多麼難得。而且既然叫帥哥,那肯定也不能矮到哪去啊 既然是美女,那黑珍珠也沒什麼不好的。 沒有 嘿,是個好問題,提供了乙個做白日夢的機會。如果是男的,我覺得高和富比較重要,我都富了,難道不是該輪到美女撲向我?高嘛,能高點當然好的。如果是女的,我...