2014-10-03 41 views
0

我經常在面試中詢問有關諸如電影票或旅遊網站等網絡應用程序競賽條件的問題。策略處理競爭條件與regrads到web應用程序後端?

問題是這樣的。

對於公共汽車或飛機票網站來說,只剩下座位。兩臺(或極端情況下的多臺)用戶在不同的計算機上同時登錄到該網站,看到剩下一個座位。他們都繼續前進,選擇該位置並下訂單。

現在有兩個要求我們必須處理。對於第一個請求,我們將預訂票,但是對於第二個請求,我們必須排除錯誤並向最終用戶顯示錯誤消息,表明座位不可用。 說數據庫模式是一些,事情是這樣的:

bus_id,SEAT_ID,is_taken

所以對於第一個要求,我們做出相應的bus_id is_taken,SEAT_ID 1。然後第二請求,is_taken = 0將不會有任何seat_id,因此我們不會預訂票證。

但是,在我看來,我們已經設定了一個限制,即一次只能處理一個請求;只有在第一個請求完成後才能處理第二個請求。

然而,這是不實際的,因爲我們可能有一個巨大的網站負載的流量和應用程序並行運行在幾臺服務器上。我們必須並行處理請求。

因爲我在處理這些多線程Web應用程序中的競爭條件方面沒有太多經驗,所以我無法完全弄清楚,解決這個問題的正確方法是什麼。

什麼是正確的(即使基本)方法/設計模式來解決這些情況?

回答

1

在某些時候,必須有某種同步。 由於您使用的數據庫無論如何都是瓶頸,因此您可以讓它處理競爭條件。

您只需要自動更新該行。請求仍然可以由應用程序並行處理。

SQL的僞代碼:

DECLARE @success = false; 

UPDATE bus_seats 
SET is_taken = 1, success = true 
WHERE seat_id = @seat_id AND is_taken=0 

return @success; 
+0

謝謝您的回答。你能否通過'自動更新行'來解釋你的意思? – Dude 2014-10-03 09:14:06

+0

@Dude基本上,以線程安全的方式更新行。我的僞代碼顯示了一種方法:1)檢查座位是否被佔用; 2)如果*尚未佔用,則取*; 3)返回操作是否成功。確保操作的另一種方式是原子使用鎖,就像Abhijith所建議的那樣,但我認爲不必使用鎖就可以逃脫。 – dcastro 2014-10-03 10:21:51

1

Web應用程序必須是多線程的。有兩種解決方法。

  1. 應用級(不推薦) 我不知道您使用的構建應用程序的編程語言是。但是,用於構建網站的所有編程語言都會有「synchornize」之類的內容,從而可以防止兩個線程同時訪問同一代碼塊。 這不是首選,因爲此解決方案不可橫向擴展。當您決定通過運行另一個Web應用程序實例來增加容量時,此解決方案將失敗。

  2. 數據庫級別 這是首選解決方案。更新之前,您可以獲取數據庫中記錄的鎖定。 SQL提供了一個用於選擇更新記錄的選項。

    SELECT * FROM BUS_SEATS WHERE BUS_ID = 1 FOR UPDATE;

    上面的SQL是獲得鎖的一種方式。所有的數據庫都提供這種功能。使用此功能,您可以鎖定所需的行並執行更新並確保數據庫中的一致性。