天天看點

餘額并發扣減一緻性,能否使用redis事務?

并發扣款,如何保證資料的一緻性?》

一文的核心觀點是:使用CAS樂觀鎖,在寫回餘額時加上舊餘額的比對,可以在不影響吞吐量的前提下,保證餘額的一緻性。

文章非常多朋友留言問,能不能把餘額放到reids裡,利用redis的事務性來扣減餘額。今天,就這個問題簡單的說一下。

redis如何實作事務性?本質也是樂觀鎖。

在redis用戶端執行:

$money = GET key$money = $money - $diffSET key $money

在并發量大的時候,會遇到和

《并發扣款,如何保證資料的一緻性?》

中描述的并發一緻性問題。

 redis的WATCH和EXEC可以提供類似事務的機制:

  • WATCH觀察key是否被改動
  • 如果送出時key被改動,EXEC将傳回null,表示事務失敗

上面保證一緻性的餘額扣減可能類似于這樣執行:

WATCH key$money = GET key$money = $money - $diffMULTISET key $moneyEXEC

在WATCH之後,EXEC執行之前,如果key的值發生變化,則EXEC會失敗。redis的WATCH為何能夠保證事務性,本質上,它使用的就是樂觀鎖CAS機制。

大部分情況下,redis不同的用戶端會通路不同的key,是以WATCH碰撞的機率會比較小,在秒殺的業務場景,即使使用WATCH,調用側仍然需要重試。

在CAS機制這一點上,redis和mysql相比沒有額外的優勢。

redis的性能之是以高,還是redis記憶體通路與mysql資料落盤的差異導緻的。記憶體通路的不足是,資料具備“易失性”,如果重新開機,可能導緻資料的丢失。當然redis也可以固化資料,但如果每次都刷盤,redis反而性能會下降很多。畫外音:每個工具都有自己的适用場景,不宜将緩存當資料庫用。 最後,redis用單線程來避免實體鎖,但mysql多線程也有多線程并發的優勢。畫外音:各有優劣。 結論:可以使用redis的事務性扣減餘額,但在CAS機制上比mysql沒有優勢,高性能是因為其記憶體存儲的原因,帶來的副作用是資料有丢失風險。

任何脫離業務的架構設計都是耍流氓。

本文轉自“架構師之路”公衆号,58沈劍提供。