在前幾天,藝人江蕙的演唱會售票服務擁塞,造成訂票民眾難以訂到票的新聞事件,引起了社會普遍的關注。

在過去,江蕙每次的演唱會售票總是在很短的時間內即被搶購一空,而在這次,因為是告別隱退的最後一場,更造成了搶購者更勝於以往的情況。

除了新聞媒體持續多日的追蹤報導之外,這個事件也在軟體開發圈子裡引起了許多的討論。

「如何設計售票系統」成了臺灣軟體架構師這幾天以來最熱門的話題。

事實上,這還不是近日來唯一一件和「售票系統」有關的新聞事件,在稍早,藝人張惠妹的演唱會網路售票服務,也遭遇到了類似的情況。總計十二萬張票,在十二分鐘內全部售光。雖然主辦單位有備而來,宣稱已投入四百萬元的預算擴增伺服器及頻寬,但是仍然有眾多的消費者抱怨網路買票時的諸般問題。也正因為連續的兩個關於網路售票系統的新聞事件,讓臺灣的軟體開發者引發相當熱烈的討論。

在這一回裡,也不免俗的來趕一下流行,只不過我希望探討更高階一些的設計議題。

並非只看伺服器效能,而要看能否增加大量伺服器與網路頻寬

首先,我們來看看所謂的「規模可擴充性(scalability)」的問題。系統有沒有規模可擴充性,看的不是單一計算節點上跑多快,而是當你增加計算資源(例如機器、頻寬)時,能不能透過增加計算資源,來換取更大規模的處理能力。如果一臺伺服器、一定的頻寬不足以支持所要服務的規模,但是透過增加伺服器、增加頻寬的手段,可以讓服務的規模變大,那就是具備了規模可擴充性,反之則否。

以張惠妹這次演唱會售票的例子來看,若真如主辦單位所言,投入了不少預算,但仍存在系統的瓶頸,使得售票服務仍有擁塞的情況,那可能就是系統的規模可擴性不夠好。很多時候我們在設計系統時,關心的不只是在單一個伺服器上能夠執行的有多快,而是當需要服務的規模變大時,能否透過投入更多的計算資源來支持想服務的規模。花錢增加計算資源,還不是最難的事,最難的是,花了錢都無法提升服務規模。此即是系統規模可擴充性的重要性。

臺灣現有的部份售票系統,架構看起來是在多年前所設計,當時人們透過網路購票的風氣不若今日之盛,在設計系統時所瞄準的服務規模,和現在所會遭遇到的「短時間內、大交易量」的購票情況不相稱,而本身也不具規模可擴充性,使得即使有意增加伺服器及頻寬,都不見得能因應實際的購票服務壓力。

不過,這兩個問題,可以說是最不應該發生問題的環節,因為它們是最容易擴充規模的,因為只需要增加伺服器數量、增加對外的網路頻寬,應該就可以解決。

尤其現在諸如 AWS EC2 之類的雲端計算平臺,允許很彈性的隨時增加伺服器,而且幾乎完全不需要考慮頻寬的問題,同時也能依據實際佔用的頻寬來計費。若是卡在這樣的問題上,可以說是很初級的情況。

資料庫作業很容易過於集中,需克服這麼做所導致的存取瓶頸

下一個可能遭遇到的問題是比較關鍵的,即資料庫的存取及操作。關聯式資料庫並不像網頁伺服器本身那麼容易擴充規模,原因是關聯式資料庫通常傾向於集中化。

為什麼關聯式資料庫傾向於集中化?

因為資料庫在操作時會需要做鎖定(locking)資料,以及進行交易(transaction),當你有多部資料庫伺服器時,在多伺服器間必須達到資料的同步,而在進行資料鎖定或交易時,也都必須以分散式的方式來達到多部伺服器間的鎖定及交易。

只要一做鎖定、做交易,即使系統中有多部資料伺服器,仍然還是一個集中式的個體,不會因為系統中有多部伺服器,而讓使用者 A 鎖定資料,此時,另一個系統所服務的使用者 B,繼續仍可操作該資料。

因此,當鎖定發生時,不論有幾部伺服器,所有的使用者都必須等待,直至鎖定解除。

任何集中化的組成,都會傷害規模可擴充性,因為集中化的部份很容易成為效能瓶頸,當你增加更多的計算資源時,集中化的部份,並不容易伴隨著加入更多的伺服器、更多的頻寬,而顯著地提高能服務的使用規模。

因為許多人習慣直接利用關聯式資料庫來操作資料,而事實上,關聯式資料庫也的確是個夠高階、夠有威力的資料操作工具。但是,它容易集中化的天性,也的確使得它成了提高規模可擴充性時的重要關鍵。

而它所提供的是很通用、很高階的資料操作,這也使得它在資料操作上的額外負擔比較高。因此,在前幾年,NoSQL 的風潮興起,有一部份原因,即在提高資料操作時的規模可擴充性。

關聯式資料庫並非不能用,問題是在於如何使用,而使用其他資料存取方案時亦然。最重要的關鍵原則之一,應該是盡量避免資料鎖定。當資料勢必要鎖定時,也要盡力的降低它所影響的範圍及時間。以演唱會的例子來看,透過資料存取的規畫,可以提高一些規模可擴充性。基本上,我的看法是這樣子的。

設法分而治之,不要集中,避免讓資料庫鎖定的範圍擴大

以新聞中的案例來看,演唱會其實是一系列的場次,如果所有的演唱會場次資料都在同一部(或資料同步的同一群)資料庫伺服器上來操作,那麼每個使用者的操作即使他們位在不同的場次裡,也都可能受到資料鎖定所影響。

若是在前端就依使用者所選的場次,將它們分流到不同的資料庫伺服器上,而不同的資料庫伺服器各自負擔特定場次的演唱會資料,彼此之間互不相影響。

即使發生了鎖定,受到鎖定影響的範圍也變小,形同將單一資料庫伺服器要服務的規模降低。

假設每個資料庫伺服器可以服務的使用者規模是 x ,而總使用者規模是 n,只要 x 的規模可以做到起碼服務單一場次的需求,那麼大約最多使用 n/x 部資料庫伺服器,就可以服務整個規模。

因為透過這個規畫方式,將一個大問題拆分成為多個互不影響的小問題,而獨立的解決這些小問題是可行的前提之下,將會使得解決整個大問題也成為可行。

雖然資料庫伺服器本身天性是集中的,但是透過資料規畫的方式,使其得以分散開來運作,就可以藉此得到規模可擴充性,而這就是提高規模可擴充性的常見手法之一――試著將集中化的部份,拆分成為互不相影響的多個部份。

至於怎麼設計資料的存取模式,使得被拆分後彼此互不相影響(即一部鎖定時不會波及其他部份),則可視應用的本質而定。

資料庫部份只是可能成為瓶頸的一個地方,而像以售票系統來說,像所使用的金流系統的吞吐量,也可能成為瓶頸。

但無論如何,整體系統設計的原則,就是使其能夠分散式的運作,因此帶了增加計算資源就能處理更大規模的能力,也就是規模可擴充性。

專欄作者

熱門新聞

Advertisement