一樣是高併發,QQ/微博/12306的架構難度同樣嗎?

開篇數據庫

同一個用戶併發扣款時,有必定機率出現數據不一致,可使用CAS樂觀鎖的方式,在不下降吞吐量,保證數據的一致性:架構

UPDATE t_yue SET money=$new_money

WHERE uid=$uid AND money=$old_money;

不能採用直接扣減的方式併發

UPDATE t_yue SET money=money-$diff WHERE uid=$uid;

固然,更通用的方式,可使用版本號來實現CAS樂觀鎖:高併發

UPDATE t_yue SET money=$new_money,ver=$ver_new

WHERE uid=$uid AND ver=$ver_old;

對於這個CAS樂觀鎖方案,頗有朋友有疑問:當併發量高時,版本號比對會致使大量的更新失敗,這個方案不適用於高併發場景嗎? 到底是不是這樣呢?你們對高併發是否是有什麼誤解呢?今天來聊一聊這個話題。

先分析三個業務場景。 學習

1、QQ優化

QQ的一些核心業務有:ui

  • 我的:user(uid, user_info, …)orm

  • 好友:user_friends(uid, friend_id, …)cdn

  • 加入的羣:user_groups(uid, group_id, …)排序

  • 羣:group(gid, group_info, …)

  • 羣成員:group_members(gid, uid, …)

  • 我的消息:msgs_user(msg_id, uid, …)

  • 羣消息:msgs_group(msg_id, gid, …)

這些信息的讀寫有一個特色,都會帶上uid/gid/msgid屬性。

例如,拉取好友列表

select friend_id from user_friends where uid=$uid;

在用戶量很大,併發量很大時,不一樣用戶/羣/消息數據的讀寫並無鎖衝突。

畫外音:10W個用戶同時讀寫,彼此沒有鎖衝突。


只有當,同一個用戶,很短的時間內,有大量併發時,纔可能存在鎖衝突。

畫外音:例如,1個用戶,1秒鐘讀寫1W次。


2、微博微博的核心業務是feed流:

  • 發消息,寫操做

  • 刷消息,讀操做

微博業務顯然是讀多寫少的,在用戶刷消息時,本身feed流裏的消息,是由別人發出的。

查看本身主頁feed流,最樸素的實現方法是:

(1) 拉取本身關注的用戶id_list;

(2) 拉取這些用戶最近N條消息;

(3) 將這N*id_list條消息排序;

(4) 返回第一頁消息,獲得本身主頁feed流;

畫外音:這裏不展開讀擴散,寫擴散,在用戶量很大,併發量很大時,會有必定數據的讀寫鎖衝突。

畫外音:不像QQ,基本是讀寫本身的數據,微博要寫本身的數據,讀別人的數據。


3、1230612306的核心業務是:

  • 查票,讀操做

  • 買票,寫操做

stock(id, num) // 某一列車有多少張餘票

在用戶量很大,併發量很大時,有極大的鎖衝突。

畫外音:這個業務,數據量並不大。這類「秒殺」業務,若是不作特殊的優化,數據庫很容易死鎖卡死,沒有任何人能買票成功。

畫外音:要作什麼特殊的優化呢?

收尾

QQ,微博、12306,一樣是高併發業務,就數據存儲鎖衝突來講,各自的難度,數據不一致的機率是不一樣的。

畫外音:你不能說,QQ不是高併發業務吧。

回到開篇,使用CAS樂觀鎖進庫存扣減:

UPDATE t_yue SET money=$new_money,ver=$ver_new

WHERE uid=$uid AND ver=$ver_old;

只要有uid這個過濾屬性,即便10W用戶同時扣款,也不容易出現數據不一致。 只有當同一個用戶,同一秒鐘,有大量扣減時,纔有必定概率會衝撞,但也不會致使數據不一致。

畫外音:有一位很可愛的水友,說萬一PC端和APP端同時下單怎麼辦。

結論
高併發的扣款場景,可使用CAS樂觀鎖,採用select&set方式進行扣款,既可以保證吞吐量,又可以保證一致性。

歡迎關注公衆號:「Java架構師學習」

你會喜歡的!

相關文章
相關標籤/搜索