iT邦幫忙

0

負載平衡的運作模式

  • 分享至 

  • xImage

請教一個問題 AWS Load Balance 的問題
這樣的架構 如果公有子網1的web (簡稱A伺服器) 與 公有子網2的web (簡稱B伺服器)
同時對同一筆資料 進行了修改
(只有一台RDS)

有沒有可能發生以下情況

A伺服器 先得到修改 Row1:name=2 的request
B伺服器 然後得到修改 Row1:name=3 的request

但是A伺服器跑 修改name=2 的functionA 程式比較多 跑得比較慢
B伺服器跑 修改name=3 的functionB 程式比較少 跑得比較快

最後導致結果先執行name=3 再執行 name=2
會有這種情況嗎?
有的話該如何解決?

或者有什麼網路架構可以避免這種情況
可以的話可以幫我畫一下就更好了(包括 EC2 RDS S3 EBS) 謝謝大神

Load Balance 要考量的問題很多,不是只有網路端,應用端兩台伺服器怎麼工作和溝通也是大學問。一般在服務(應用)端有做到 Load Balance ,不論是主、被動式或者分流,只要設定完善,都不會有你說的問題。
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

6
Ray
iT邦大神 1 級 ‧ 2022-12-12 04:56:14
最佳解答

多工使用當然會遇到這個現象, 這就是 DB 的 Race Condition.
通常是負責設計資料庫的 DBA (資料庫管理師) 要出面解決.

他跟有沒有:負載平衡, 有沒有上雲, 有幾台主機...等等都沒有關係,
並不是 Infra 用了甚麼神奇的網路架構, 就會自動解決掉這個問題.
就只是多人存取資料庫的時候, 需要用到的交易設計規劃與處理技巧,
所以才說是 DBA 要出面來解決, 因為這是 DBA 職務的日常工作之一.

(大學的資訊相關科系, 應該都會在學程中講授這個 DB 問題與解法)

其成因與解決方法可先參考別人的筆記:
https://hackmd.io/@Burgess/SkDnHKMNr

詳細整理:


DB 的 Race Condition 會有五種不同情境:

https://medium.com/@chester.yw.chu/%E8%A4%87%E7%BF%92%E8%B3%87%E6%96%99%E5%BA%AB%E7%9A%84-isolation-level-%E8%88%87%E5%B8%B8%E8%A6%8B%E7%9A%84%E4%BA%94%E5%80%8B-race-conditions-%E5%9C%96%E8%A7%A3-16e8d472a25c

  • 1.Dirty Read: 讀取到其他 transaction 尚未 commit 的資料
  • 2.Non-repeatable reads: 同一個 transaction 中,執行多次相同的 query 條件,讀取欄位的資料不同
  • 3.Phantom reads: 同一個 transaction 中,執行多次相同的 query 條件,取出的資料數目不同
  • 4.Write Skew: 不同的 transactions 執行某樣 query 條件操作驗證,然後再去做新增/修改動作,卻造成資料衝突
  • 5.Lost Update: 同時進行 Item A 的操作, 但 Transaction B 直接把 A 的更新覆蓋掉了

要解決以上的 Race Condition, 會因為 DBMS (資料庫管理系統) 的 Isolation Level 而有不同的解法, 萬一你用的 DB Engine 沒辦法解掉你的應用情境, 就要自己在程式裡面寫排隊機制去排解:

Isolation Levels 有四種等級,各家資料庫皆會宣稱支援到何種等級? 一般需要 transaction 情境至少會要求到 Repeatable Read 的等級。

DBA 在規劃選擇 DB System 時, 要考量其支援的 Isolation Levels 能否解決應用情境? 否則就要自行用程式處理 race condition 問題。

DB 的 Isolation Level 種類如下 (各廠牌方法各不相同):

1.Read Uncommitted:
代表 transaction 可以讀到別的 transaction 尚未 commit 的資料,在這個等級中 race condition 所有問題都沒有被解決。

2.Read Committed:
代表 transaction 只能讀到別的 transaction 已經 commit 的資料,沒有 commit 的話就不會讀到,在這個等級解決了 Dirty Read 的問題,但是其他四個現象還是有可能發生。

3.Repeatable Read:
代表每次 transaction 要讀取特定欄位的資料時,只要 query 條件相同,讀取到的資料內容就會相同。在這個等級解決了 Non-repeatable reads 的問題。依照實作的方法不同,有的 Repeatable Read Isolation 還可以避免 Lost Update 或 Phantom 現象。

4.Serializable:
代表在多個 transaction 同時執行時,只要 transaction 的順序相同時,得到的結果一定相同。比如說 Transaction A 先執行了,接下來再執行 Transaction B,在同樣的條件下,每次執行都會得到一樣的結果。在這個等級下連同 Phantom reads 也會一併被解決。

這四種 Isolation 對應以上五種 Race Condition 的解決程度 (綠底代表安全解決):

註(1): 其他三個 Isolation Level 我們都可以很清楚的知道,它們分別避免哪些 Race Conditions,唯獨 Repeatable Read Isolation 的行為,則依照每個資料庫廠商的實作方式不同, 而有各別差異。

註(2): Serializable 通常被認為是最嚴格的 Isolation Level,可以避免上述全部五種現象,但是因為必須犧牲一些 Concurrency,導致效能較差。


MYSQL 的 InnoDB Engine 為例
(MySQL 在 Create Table 時可以選擇: MyISAM 或 InnoDB...等不同的引擎):
InnoDB 預設 Isolation Level 為 Repeatable Read (MySQL InnoDB 只能避免 Phantom Read,UPDATE 和 DELETE 等 DML 的寫入的操作則無法避免 Phantom 現象, 也無法避免 Lost Update)

但若換成 PostgreSQL 的話:
PostgreSQL 預設是 Read Committed 的 isolation level (PostgreSQL 可以完全避免 Phantom 和 Lost Update)

而 AWS 的 DynamoDB 則是:
遇 race condition 情形會直接拋回 TransactionConflictException 的例外錯誤, 可能要視情況, 自行在應用程式內實作出 auto-retries 機制


這裡有一個用 PostgreSQL 實作的 Race Condition 展示:
https://blog.kennycoder.io/2020/03/06/RDBMS-%E4%B8%8D%E5%90%8C%E7%9A%84Isolation-Level-Race-Condition%E7%A4%BA%E7%AF%84/

這是 RoR 寫的概念驗證:
https://riverye.medium.com/day22-ruby-on-rails-%E4%B8%AD%E7%9A%84-race-condition-645a838a0174

這是 PHP Laravel 的展示:
https://blog.scottchayaa.com/post/2019/01/09/how-to-handle-the-high-concurrency-on-laravel/

後記: 因樓主只說用了 AWS RDS, 卻沒講是用了 RDS 裡面的哪一種 DB Engine, 所以請自行查閱所選的 DB Engine, 才能得知你目前所使用的 Isolation 種類.
believeil iT邦新手 5 級 ‧ 2022-12-12 09:50:26 檢舉

謝謝 很詳盡的回答 也有很多有用的參考與測試資料

0
chuway
iT邦新手 2 級 ‧ 2022-12-10 08:20:45

如果程式自己開發,使用資料庫的RAW LOCK
不要使用dirty read

我要發表回答

立即登入回答