發表文章

目前顯示的是 九月, 2017的文章

MongoDB:Big query or Small queries

一件事情,要用 Big query 還是 Small queries 好呢?也就是用一個很複雜的 Query,還是拆成幾個小 Query 呢? 一件事情要用 Big Query 還是很多 Small Query (small queries),有很多因素要考慮。但擔心篇幅太多,僅供幾個引子,讓大家去想一下。 Connection pool Lock Thread model MongoDB 是 single thread model,也就是大多時候只會用到一顆 CPU,而 Query 會 Read lock, Insert / Remove / Update 還會加上 Write lock。 所以若是 MMAPv1 引擎,collection-level locking 會讓 Query 只能在單一 collection 中處理 (Read lock),再加上沒有 MVCC 以及天生的 single thread model,所以無法有效處理高併發。這時候通常 Big Query 會比 Small queries 來得好。 反之若是 WiredTiger,document-level locking 加上 MVCC 設計,比較能處理高併發。這時候通常 Small queries 會比 Big Query 來得好。 可是事事無絕對,還是要看什麼樣的 Query。例如多大的 Query、是不是跨 Collections 的 Query 等。 但無論哪個引擎,都會受限在 MongoDB 天生是 single thread model 的設計,無法善用多核 CPU。所幸 MongoDB 天生擁有良好的 Sharding 技術,可以跑多個 MongoDB instances 並採用 Sharding 技巧,還是可以盡量壓出機器的效能。 單機跑多 instances 可以參考官方文件 http://docs.mongodb.org/manu…/tutorial/deploy-shard-cluster/

MongoDB 的髒讀及偽讀

若依資料庫 CAP 理論來分,MongoDB 屬於 “CP"。與大家熟知的 PostgreSQL/MySQL 的 "CA” 不一樣,因為 MongoDB 不是 RDBMS 而傾向於 NoSQL。不管 “CP” 或 “CA",其中的 "C” 即 “consistency” (資料一致性)。無論用戶端怎麼讀取,都要能夠正確讀取最新的資料。 但最後附上的【參考來源】文章指出,事實並不如 MongoDB 官方網站中所聲明般,Write consistency 與 Read consistency 能夠達到真的 “consistency"。作者實測中顯示,MongoDB 會發生髒讀 (Dirty read) 及偽讀 (Stale read) 的問題。 髒讀 (Dirty read):當某資料把值從 X 寫為 Y 時,因為異常而事務回滾發生時,該資料應該退回 X 而不是 Y。可是用戶端讀取時卻是 Y。 偽讀 (Stale read):當某資料把值從 X 寫為 Y 時,即使沒有任何異常,用戶端讀取時是 X 而不是 Y。 因此,MongoDB 並不如它宣稱般能夠達到 "CP"。而如果不能做到其中的 "C” 時,很多業務場景就不能用 MongoDB,例如金融業。只要是資料敏感的行業,不管是髒讀或是偽讀,都是天災。 開始點名 於是,外國鄉民就開始點名了。第一個點到的就是 Stripe (金流服務,連 Paypal 創辦人都投資的公司)。Stripe 就是大量 (聽說內部全使用 MongoDB) 使用 MongoDB 的金流公司之一。 另外,被 Facebook 買下的 Parse 也是使用 MongoDB。 參考來源Call me maybe: MongoDB stale reads

MongoDB 遇到障礙

MongoDB 的預設讀寫引擎 (MMAPv1) 感覺不適合當資料庫。原因是資料庫常見的兩大應用場景 OLTP 及 OLAP ,MMAPv1 在達到某個階段時都很容易遇到障礙。 OLTP OLTP 面對的是高併發的寫入及更新。可是 MMAPv1 天性就容易造成大量的記憶體碎片,進而產生大量的硬碟空間碎片 (資料寫回硬碟)。 記憶體碎片會造成記憶體的浪費,也意謂著 Cache hit rates 很低。硬碟空間碎片會造成硬碟容量浪費,也意謂著需要耗用更多 IO 來處理資料 (即浪費硬碟儲存不必要的資料,也浪費硬碟 IO,導致需要更多硬碟來應付需求)。 而當資料庫的容量超過記憶體時,系統勢必要花費額外的 CPU 及 IO 來交換,如此更加快 MongoDB 增機擴展的需求。 但 MongoDB 最擅長的增機擴展 (如 Sharding) 又面臨資料的偏性而不穩定,若處理的資料天性偏向集中於某處,那麼 hotspot 就會集中在集群中的某幾台機器,使得增機擴展無法線性成長,等同於要浪費更多的機器來補足,最終達到瓶頸而無法處理。 再加上 MMAPv1 沒有自動清理碎片的機制(它依賴作業系統),也沒有資料壓縮功能,這兩種其它資料庫常見處理碎片的手法它都不支援。 不過 MongoDB 有提供手動清理碎片的方式,只是非常耗系統資源,且效能可能會掉至原本的四分之三不到,而這通常不是 24x7 線上服務能接受的。 OLAP MongoDB 因引入 Mapreduce 而宣稱進入 Big data 行列。不過至今其 Mapreduce 仍然是 read-lock 及 write-lock。也就是若 MongoDB 在處理 Mapreduce 時,無法有任何其它的讀寫操作,包括其它的 Mapreduce。 即使利用 Sharding 緩解,每個 Sharding 也都各自是 read-lock 及 write-lock 而難以完全發揮性能。所以你會看到很多奇奇怪怪的加快 Mapreduce 的技巧,這都是因為 MongoDB 的缺陷而讓程式設計師不得不 workaround。 而且 MongoDB 是單執行緒(single-thread)又無法跨進程溝通,所以無法引入目前最常見的 MVCC 無鎖設計,無疑讓問題雪上加霜。

好的架構源於不停地衍變,而非設計

好的架構源於不停地衍變,而非設計 好的架構不是設計出來的,而是演進出來的 對很多創業公司而言,很難在初期就預估到流量十倍、百倍以及千倍以後網站架構會是什麼樣的一個狀況。同時,如果系統初期就設計一個千萬級並發的流量架構,很難有公司可以支撐這個成本。
因此,這裡主要會關注架構的眼花。在每個階段,找到對應該階段網站架構所面臨的問題,然後在不斷解決這些問題,在這個過程中整個架構會一直演進。
在建立之初,站點的流量非常小,可能也就是十萬級別,這也就意味著,平均每秒鐘也就是幾次的訪問,此時網站架構的特點是:請求量比較低,數據量比較小,代碼量也比較小。這個時候的站點可以被幾個工程師輕易搞定,因此根本沒什麼“架構”可言。 就像一個單機系統,所有的東西都部署在一台機器上,包括站點、數據庫、文件等等。而工程師每天的核心工作就是CURD,前端傳過來一些數據,然後業務邏輯層拼裝成一些CURD訪問數據庫,數據庫返回數據,數據拼裝成頁面,最終返回到瀏覽器。相信很多創業團隊初期都面臨一個與之類似的情況,每天寫代碼,寫SQL、接口參數、訪問數據等等。 如果可以重來?那麼會選擇LAMP 很多創業的同學可能會想,初期什麼樣的一個架構合適?如果重來,站在現在這個角度上會選擇LAMP,為什麼?首先是無須編譯,而且快速發布功能強大,從前端到後端、數據庫訪問、業務邏輯處理等等全部可以搞定,最重要都是成熟的開源產品,完全免費的。如果使用LAMP搭建一個論壇,兩天的時間就足夠了。所以,如果在創業初期,就盡量不要再使用Windows。 在這個階段面臨的主要問題是什麼?其實就是招人,最初工程師寫CURD都容易出錯。當時引進了DAO和ORM,從而避免直接面對CURD語句,而是面對工程師比較擅長的是面向對象,能夠極大的提高工作效率,降低出錯率。
中等規模:流量跨過十萬的階段,數據庫成為瓶頸
隨著高速增長,系統很快跨越了十萬流量階段。主要需求是什麼?網站能夠正常訪問,當然速度更快點就好了。而此時系統面臨的問題有:在流量峰值期容易宕機,因為大量的請求會壓到數據庫上,所以數據庫成為新的瓶頸,從而,人越多訪問越慢。而在這個時候,機器數量也從一台變成了多台,所以很自然的行程了分佈式架構 首先,使用了一些非常常見的技術,一方面是動靜分離,動態的頁面通過Web-Servre訪問,靜態的像圖片等就單獨放到了一些服務器上。另外一點就是讀寫分離…