reference
[1]
對單個資料的更新,可以使用cas(compare-and-swap)指令。
夥計們的操作變成下面這個過程:
夥計a看了下總賬戶餘額是1200,然後記住這個數字,回來計算1200+50=1250,回去修改,一看總賬戶餘額還是1200,於是成功修改為1250;
夥計b看了下總賬戶餘額是1200,然後記住這個數字,回來計算1200-50=1150,回去修改,一看總賬戶餘額是1250,不是原來的1200,說明資料被修改了,需要重新計算,於是記住新的值1250,回去重新計算1250-50=1200,在回去修改,一看總賬戶餘額是1250,於是成功修改為1200。
上面的操作過程就是運用了cas指令,修改之前先對比,資料沒變化說明沒有被修改過,這時候才能進行更新。
但是cas操作時,還有乙個aba的問題。
例如:夥計a動作很快,改了一筆1200->1250,又改了一筆1250->1200;這時候夥計b回來改,看到的1200雖然數量沒變,但是已經被改動兩次了。
雖然上面的這種情況aba問題不會有什麼影響,但是有時候還是會出問題。
例如:總賬戶餘額是每天記錄乙個數。
夥計a在今天的總賬戶餘額上面改了一筆1200->1250,掌櫃過來翻了一下總賬戶,翻到了昨天那頁,而那頁的總賬戶餘額剛好是1200;
夥計b過來更新資料,一看還是1200,就改成了1150,這個改動是有問題的,因為夥計b改的是昨天的總賬戶餘額。
要怎麼解決這種aba問題呢?
只需要在之前的資料基礎上,再增加乙個日期資料,檢查的時候,需要同時檢查總賬戶餘額的資料和日期的資料,都沒有變化才可以成功更新。
引入佇列,讓乙個任務專門來做資料的更新,避免並行運算。
這時候,就是讓掌櫃乙個人來更新總賬戶餘額,夥計們只需要把自己的每一筆業務結果記錄在總賬戶下面。
夥計a有一筆業務是存50兩,則在總賬戶下面記錄上+50;
夥計b有一筆業務是取50兩,則在總賬戶下面記錄上-50;
而掌櫃只需要從總賬戶裡面,順序的把+50,-50的操作更新到總賬戶餘額就可以了。
這種方法的好處是,避免夥計並行更新總賬戶餘額,發生衝突時的等待,既提高了夥計的效率也保證了資料更新的安全。
還是需要有鎖的操作,但是讓運算的過程更快,減少鎖衝突的頻率和時間。
前面是夥計先上鎖,然後看總賬戶餘額,再回去運算,再回來更新和解鎖。
把這個過程改一下,夥計帶著算盤過來,先上鎖,然後現場運算,更新後解鎖,再回去。
這樣一來,整個的讀寫時間變短了,鎖的衝突時間也就減少了,效率和效能也就能有所提高。
能否進一步減少鎖的衝突時間,比如:將讀、寫的鎖分開考慮,畢竟大部分業務中讀的次數會遠多於寫的次數。
a 使用讀寫鎖而不是互斥鎖,可以提高併發讀的效率,減少讀時候的鎖衝突。
例如:大量的業務都需要檢視總賬餘額才可以做決定,那麼就會有大量的讀需求。而多個人一起讀不衝突,只是在需要寫的時候才獨佔總賬餘額的鎖。
b 將大的資料分拆為多段的小資料,這樣通過多個鎖分別作用在小資料上,避免乙個鎖作用在大的資料中,減少衝突的概率。
例如:對總賬餘額的每一位設定單獨的鎖,而不是對整個數設定乙個鎖。這樣的話,+50只需要得到十位數的鎖,-3只需要得到個位的鎖,如果是+55則要個位和十位兩個鎖。
c 讀的時候不需要鎖,而寫入的時候序列化同時只能乙個人更新
高併發解決辦法
1.資料庫優化 以mysql資料庫為例,當資料量達到100萬以上時,mysql效能有明顯的降低,訪問速度變慢。常見的優化措施 主從同步複製,主節點用來提供修改,刪除,增加等操作,從節點提供查詢功能。但資料量達到千萬級的時候,複製同步開銷直線上公升,建議將表分割槽,根據業務分割槽。2.頁面靜態化 對系...
高併發解決思路
今日看到一位大佬所寫的文章,感覺思路很清晰,所以記錄下來,以作後看。一 秒殺帶來了什麼?秒殺或搶購活動一般會經過 預約 搶訂單 支付 這3個大環節,而其中 搶訂單 這個環節是最考驗業務提供方的抗壓能力的。搶訂單環節一般會帶來2個問題 2 超賣 任何商品都會有數量上限,如何避免成功下訂單買到商品的人數...
幾種報錯的解決辦法
呼叫google api,缺失庫報錯 importerror no module named google 解決方案 出現這個錯誤,就是因為沒有安裝google api相應的庫,按照如下命令安裝即可,把庫名換成你所需要的相應的庫名即可 pip install google cloud speech ...