原文:Ted Dziuba 編譯:伯樂線上 – 唐尤華
大約在一年前,我的程式設計師生涯遇到了一次轉折,起因是我閱讀了Eric S. Raymond(後文簡稱ESR)寫的《UNIX程式設計藝術》一書。雖然該書寫作的時候Web應用程式還未開始流行,但是其中的原則至今仍然適用。ESR在書中試圖以UNIX的設計思想與程式設計師交流,如果你讀過之後能夠理解,你會在那時發出“啊哈”的感嘆,並且對所有的知識瞬間領悟。這種感覺就像你第一次使用煙霧彈發現所有人和物體都變成了微粒,或者像你第一次知道如何使用磁鐵一樣。
接下來,這種頓悟自然消失了,然後你花費很長時間試圖重新找回這種感覺。
對於web程式設計師,如果你不喜歡閱讀,你也可以直接採用 “Single Point of Truth”(後文簡稱SPOT)規則,即“在系統中每個概念都必須具有唯一的、沒有歧義的、權威的表示“。如果你設計的系統違反了這條原則,你會使自己陷入無盡的麻煩和災難中。
你需要避免的做法
在Web開發領域,有一些違反了SPOT規則的情形,它們基本上都來自對資料庫概念的誤解。不,等一下,我突然想到了。我看到的幾乎所有違反SPOT的情形,幾乎都是以某種方式使用MySQL時遇到的錯誤。事實上,幾乎所有的NoSQL災難都是向MySQL輸入錯誤SQL造成的後果,但這不是我這裡要說的重點。
1. 使用Solr來搜尋資料庫 / Using Solr to Search a Database
我敢說你們肯定有過這樣的想法,而我不止一次想過這麼做。當你需要在web網站後臺資料庫進行搜尋時會決定使用Apache Solr。你會建立一個“索引管道”用做從資料庫週期地提取資訊並交給 Solr 處理,或者在為更新資料庫建立“插入/更新”入口點的同時也為Solr提供一個入口點。
問題在於你的應用程式不知道到什麼才是真實的資料。如果是 Solr 執行返回的結果,你會按照搜尋索引的格式顯示資料嗎?你會用索引行ID查詢資料然後顯示資料庫後臺的資料嗎?無論你如何試圖解決這個問題,結果都是令人痛苦的。看在上帝的份上,如果你的索引連線程式發生錯誤結果又會怎樣?你需要多長時間才能發現這樣的錯誤已經發生在你的系統中呢?
解決辦法:不要那麼做。PostgreSQL本身就帶有很好的全文搜尋功能。你可以在此基礎上根據你的要求進行調整;這並不違反SPOT規則。該死,如果 Solr 可以滿足需求,你甚至可以將Solr作為資料庫使用。
2. 將SQL查詢結果預存到一個NoSQL系統 / Precaching SQL Results in a NoSQL System
這種情況不大常見,但還是會發生。你將一個很大的物件關係模型的所有資料存到了MySQL中,但是從你的Web應用程式查詢這些資料需要3到4個JOIN操作,這會使MySQL遇到效能瓶頸。一直以來都沒有好的解決辦法。所以為了解決這個問題,你預先計算了一些資料結構並且儲存在類似Memcached或者Redis這樣的NoSQL系統。
如果資料發生變化要怎麼辦?你會在程式執行的同時重新計算這些資料結構嗎?會在之後的某個時刻更新NoSQL以及SQL寫操作佇列嗎?你可以通過配置來讓這種機制奏效,但是當你的“同步”指令碼失效的時候,你會發現事情搞糟了,因為你不能確定哪一種才是有效的資料表示。
解決辦法:如果你授權的DB執行速度過於緩慢,請不要試圖重新組織你的資料模型或者將資料庫改變成需要的形式。如果你確實需要為你的應用程式新增一個資料緩衝層,最好加在Web伺服器前面最外層。以我的經驗來看,任何試圖在表示層下面加上資料緩衝都會帶來資料同步災難。另外,在應用程式的邊緣增加資料快取也比較容易:你可以使用Squid或者某個商用的內容提交網路。
3. Frankendatabases 問題
是的,我已經說了很多關於MySQL的事。最近我遇到了這樣的設計難題:你希望在一個資料庫中進行查詢,但這些資料卻分散在多個資料庫中。如果你和老式系統打過交道,你應該能理解我在說什麼。編寫同步指令碼實現從資料庫A和資料庫B中提取資料然後更新到你的資料庫中,這樣的工作只會讓你的脾氣變得糟糕。
你會讓自己陷入這樣的邏輯:
1 2 3 4 5 |
my_record = query("SELECT * FROM records WHERE id = x") if not my_record: insert_into_my_db(their_record) elif their_record != my_record: update_my_db(their_record) |
此外,這會給你帶來資料一致性的夢魘。假設同步的指令碼執行中斷,諸如此類,這時你往資料庫裡寫入新的記錄,如果接下來有人需要做和你類似的事情,情況會變得更糟。當然,通常這會在資料更新時觸發大批查詢操作。
解決辦法:你已經猜到了:請不要那麼做。儘量規範地整理資料庫。有些情況並不適合老式系統,所以請你儘可能地避免合併資料庫–直接查詢資料庫A和資料庫B。如果你不那麼去做,那麼就不要怕難堪。
事情已出錯的跡象
總而言之,如果你發現自己在編寫一些跨越多個應用層的程式碼,或者“更新”指令碼,後者你的crontab指令碼超過了10行程式碼,你很有可能已經犯了錯誤並且在架構的某個地方違反了SPOT規則。寫出那樣的程式碼是枯燥和痛苦的,這種痛苦往往預示著你不能再繼續下去了。所以,停下來不要繼續犯錯。
原文:Ted Dziuba 編譯:伯樂線上 – 唐尤華
【如需轉載,請標註並保留原文連結、譯文連結和譯者等資訊,謝謝合作!】