My friends, my life, my style - James S.F. Hsieh

4/19/2015

BGP - Software design principles for Agile 敏捷 軟體設計原則 - part1

這是我製作的一堂關於 “軟體設計原則” 的課程, 主要的目的是讓更多人可以瞭解軟體設計原則的重要性與帶來的好處, 讓更多人成為 “偉大的軟體工程師”, 希望大家可以有所收穫, 也麻煩大家幫我推廣吧!!

3/03/2014

MongoDB 筆記

使用一個 database 總是會想知道它所提供的能力跟特性, 這是希望了解這個 database 適用於哪種些種類的應用, 畢竟, 沒有完美的 database 可以做到 availability / scalability / consistency / partition tolerance 四者兼備.

MongoDB 這個 NoSQL database 在 node.js 社群可以說是相當的活耀, 我認為可能主要是因為:

  • MongoDB data model 使用 Binary JSON
  • MongoDB 的 console 與 map-reduce function 都是使用 JavaScript V8
  • MongoDB deployment 的簡易性與 node.js 可以說是一拍即合
所以, 我就來淺嚐一下 Mongo 了 ...


ACID Transactions

MongoDB 對於單一 document 的 write 是 atomic operation. MongoDB 的 data models 有很高的彈性, 它允許 embedded data 這樣的概念來描述多筆 data instances 的關係, 而且這個從屬關係的更新是 atomic operation. 以往 SQL 的作法是存放 normalized data, 所以通常會把這多筆 data 放在不同的 table 上並使其有關聯性, query 則使用 join 來得到兩者. SQL 最大的限制在於 schema 是預先定義的, 所以當要有新的關聯就必須新增與修改 table 才能達成但 MongoDB 則是 schema-less. MongoDB 的方式很類似於 GAE datastore, GAE datastore 可以建立多個 table 並且 table 之間是有所謂的 parent/child 關係. 從整體看他是個 tree/directory, 而 transaction 的運作範圍就是這棵 tree. 基本上這個概念跟 MongoDB 是等價的. DynamoDB 在這方面的表現算是最弱的, 根本上它既沒有 embedded data 的概念也沒有 transaction, DynamoDB 只提供 conditional writes 跟 atomic counters. 不過基於這兩個基本功能還是能達到 transaction 的目的, 詳細可以參考 From CD to ACID: Adding Atomicity and Isolation to DynamoDB .

附帶一提, 目前 MongoDB 的 write lock 依然使用 global lock 而非 collection lock, 這樣會導致 write scalability 有非常嚴重的問題, 目前 MongoDB 正在改進這問題 (雖然已經花了兩年多) 詳細可以參考 "Is it true that MongoDB has one global read/write lock?".

Secondary index

Index 可以視為是 data 的 clone subset 並且經過 sorting 或是 hash 的處理, 通常更新 data 之後 index 必須相對調整維持同步, data 跟 index 的 consistency 問題油然而生. MongoDB 支援 single field, compound index, multikey index, geospatial index, text index, 與 hash index 等多種 secondary index. MongoDB 更新 index 是同步的, 在更新 data 的同時 index 也同步的被更新. 這有別於 GAE datastore, GAE datastore 的 index 只能保證 eventual consistency, 而 DynamoDB 更是沒有提供 secondary index. Sharding 跟 index 同時運作是比較複雜的狀況, 因為, 每個 Shard 只擁有整體 database 的 data subset, 而每個 Shard 只有 subset 的 index, 這意味著當我們要執行一個 query 它所參考到的 index 不是 shard key index, 執行這個 query 必須要 scatter/gather 並且 merge 最後的結果, 可想而知跨 shard 的 query 是非常慢, 所以這種 on-the-fly 的 sorting/merge 都應該盡量避免, 也因此 group operation 在 sharding 的環境下是不被支援的. 所以sharding key 的選用就變得非常重要, 目前 shard key 必須是 single field, compound index 或是 hash index. 

Replication

Replication 主要用來提升 availability 與 scalability, MongoDB 提供基本的 single master / multiple slaves 的方式來達成 replication, 當 master 故障 replication set 會從 slaves 票選出一個 instance 做為 master. 一般狀況 replication 是採用 async 的方式來進行, 並且可以設定 read operation 的 data 來源是來自 master 或是 slaves, 所以當讀取的 data 是來自 slaves 時,  MongoDB 能提供 eventual consistency. 甚至, 會發生 uncommitted read 的情況, 由於 async 的關係如果 master 還沒有來得及 replica 卻已經發出 write acknowledged 或是 journaled 就掛了, 這時候, 某個 slaves 必須成為 master, 而剛剛寫入的 data 就必須被 rollback. 不過 MongoDB 有提供 replica acknowledged 的寫入模式 (read one write all), 有別於使用 Paxos algorithm 的 database, MongoDB 在 replica acknowledged 寫入模式下使用的時間會比使用 Paxos algorithm 來的久 (Paxos replica 只要大於 N/2 而非 N, read quorum write quorum), 但換來的是讀取速度的增加.

Sharding

Sharding 是 horizontal scaling 的一種技巧, 目的是用來提升 scalability, 我們會關心的就是 database 如何 rebalancing. 一個 MongoDB 的 sharded cluster 可以存有很多個 chunks. 當一個 chunk 過大時, MongoDB 會自動的觸發 splitting, 觸發的時機為 data 被 insert/update. 所以 splitting 是個 incremental 的 operation. MongoDB 同時也提供 balancing 將 chunk 從 cluster A 移至 cluster B. 當 Shard key 使用 hash key 時, MongoDB "也許" 是使用 consistent hashing 的方式 sharding data, 這樣才能減少 sharding data 的移動.


下個來研究 Riak 跟 Cassandra 吧 :D


Reference 


8/22/2013

蝙蝠女

用 HTC ONE Max Scribble App 做的內容喔
https://googledrive.com/host/0B7uI6_CEmoHqZnRMVm0wOEo0SFk/index.htmll