2014年5月4日 星期日

MongoDB 學習筆記之二 - MongoDB 簡介

一、什麼是 MongoDB?

MongoDB 是一套 open source 的 NoSQL DB。MongoDB 本身是用 C++ 開發的,它提供了高效能 (high performace)、高可用度 (high availability) 以及自動擴充 (automatic scaling) 等特色。

如下圖所示,在 MongoDB 中,一筆資料就是一個「document」(文件),所謂的 document 是由多個 field-value pairs 所組成的,其結構類似於 JSON 物件。一個 field (欄位) 裡的 value (值)可以是其他的文件、陣列或者由文件組成的陣列。


圖一、MongoDB 中每一筆紀錄都是 JSON 格式的 document

MongoDB 以 document 作為基本的資料儲存單位,有下列幾項好處
  1. JSON document 可對應於許多物件導向程式語言的原生資料類型 (如:物件),這也是近年來 JSONORM (Object-Relational Mapping) 日漸風行的原因 。
  2. RDBMS 的 JOIN 操作其實是成本高昂的,但如果採用 嵌入式文件 (embedded document) 或陣列的方式,可減少 JOIN 操作的使用。
  3. 動態的 schema 支援流暢的多型 (ploymorphism)。
本文寫作時的 MongoDB 社群正式版(production release)為 2.6.0 (2014/04/08 發行)。目前支援的 OS 如下表所示:

WindowsLinuxMac OS XSolaris
32-bit
64-bit

您可以在 MognoDB 官網的「Downloads」網頁下載。不過要注意的是,32 位元的版本有一個限制,即最多只能儲存 2 GB 的資料。所以,一般說來,你應該使用 64 位元版本。32 位元版本僅適用在 replica set 的「arbiter」(裁決者) 角色,或者用做 sharding 的 mongos (但請不要用於正式環境),相關資訊請參考這個網頁

MongoDB 的授權許可(license):
  • Database Server 和 Tools:AGPL
  • Drivers:Apache License
  • MongoDB Enterprise (企業版):MongoDB Inc. 提供商用的 licenses

MongoDB 的 key features(摘錄自官網):
  • High Performance
    • Support for embedded data models reduces I/O activity on database system.
    • Indexes support faster queries and can include keys from embedded documents and arrays.
  • High Availability (replica set)
    A replica set is a group of MongoDB servers that maintain the same data set, providing redundancy and increasing data availability.
    • automatic failover.
    • data redundancy.
  • Automatic Scaling (sharding)
    • Automatic sharding distributes data across a cluster of machines.
    • Replica sets can provide eventually-consistent reads for low-latency high throughput deployments.

二、關於 MongoDB Inc.

www.mongodb.org」是 MongoDB 社群版的官方網站,「www.mongodb.com」則是 MongoDB 企業版的官方網站,這兩個網站基本上都是由 Mongo Inc. 這家公司在維護。2013 年 8 月 27 日以前,MongoDB Inc. 其實叫做「10gen Inc.」的,為了避免造成大家的困惑,所以直接以產品名稱作為公司的名稱,詳情請參考 Tech Crunch 網站上這篇報導:《10gen Is Now MongoDB To Reflect Focus On NoSQL Database》。

2007 年,10gen Inc. 成立於紐約。由 Dwight Merriman (前 DoubleClick 創辦人兼 CTO )、Kevin P. Ryan (前 DoubleClick CEO、Gilt Groupe 創辦人)、 Eliot Horowitz (前 DoubleClck 工程師、 ShopWiki 創辦人兼 CTO ) 三人,接受了來自 Flybridge Capital Partners、In-Q-Tel、Intel、New Enterprise Associates (NEA)、Red Hat、紅杉資本 (Sequoia Capital) 以及 Union Square Ventures 共約 8,100 萬美金的投資。

10gen 最初的目標是希望能建立一個完全基於 open source 元件的 PaaS 架構,但因為該公司始終找不到一套既有的 DB 平台,可以符合他們建造此雲端架構的「原則」。因此,這家公司開始發展一套文件導向的資料庫系統 —— MongoDB

在發現這套系統的潛力之後,10gen 決定放棄原來的雲端平台計畫,全力投入 MongoDB 的開發與維護。2009 年,10gen 將 MongoDB 公開釋出為 open source 專案。2010 年 8 月,10gen 設立了位於美國西岸加州 Palo Alto 的辦公室。2011 年,陸續在維吉尼亞州的 Reston、英國倫敦、愛爾蘭都柏林、西班牙巴塞隆納、澳洲雪梨等地設立據點。

2012 年 9 月,在 華爾街日報 一篇《The Next Big Thing 2012》的報導裡,10gen 評為頂尖軟體公司排行榜的第 9 名

2013 年 4 月,10gen 搬進了舊紐約時報大樓。並於同年 8 月 27 日 10gen 宣佈將更名為 MongoDB Inc.,讓大家能由公司名稱直接就聯想到其代表性產品。

2013 年 10 月,MongoDB Inc. 在新一輪融資中獲得了1.5 億美元的風險創投資金,其估值達到 12 億美元,成為紐約估值最高的新創公司!(詳情請參考 Bloomberg 的這篇報導:《MongoDB Now King of NYC Startups With $1.2 Billion Valuation》和 TechOrange 的這篇報導:《NoSQL 資料庫的春天:MongoDB 獲得 1.5 億美元融資,它背後的故事是什麼?》)

三、MongoDB vs. RDBMS

以下這張 MongoDB 與 RDBMS 的對照表摘錄自官網的《SQL to MongoDB Mapping Chart》:

RDBMSMongoDB
databasedatabase
tablecollection
rowdocument or BSON document
columnfield
indexindex
table joinsembedded documents and linking
primary key
Specify any unique column or column combination as primary key.
primary key
In MongoDB, the primary key is automatically set to the _id field.
aggregation (e.g. group by)aggregation pipeline
See the SQL to Aggregation Mapping Chart.

下圖是在「users」這個 collection 裡新增一筆 document 的範例,也說明了 MongoDB 中的 Collection 與 Document 之間的關係:

圖二、Collection 與 Document 之間的關係

下表則是 MongoDB 與 RDBMS 在 DDL 與 DML 的比較表:

DML / DDLRDBMSMongoDB
DDLCREATE TABLEdb.collection.insert()
db.createCollection()
ALTER TABLEdb.collection.update()
DROP TABLEdb.collection.drop()
CREATE INDEXdb.collection.ensureIndex()
DROP INDEXdb.collection.dropIndex()
db.collection.dropIndexes()
DMLINSERTdb.collection.insert()
db.collection.save()
UPDATEdb.collection.update()
db.collection.save()
DELETEdb.collection.remove()
SELECTdb.collection.find()
db.collection.findOne()

※ 關於「db.collection.save()」,請參考官方文件
  •  如果未指定 _id,則等同執行「db.collection.insert()」。
  •  如果有指定 _id,則等同執行 upsert(即 db.collection.update({ _id: "XXXX"}, {document}, { upsert : true}))。若該 _id 已存在,則更新該筆 document;若該 _id 不存在,則新增一筆 document。

四、MongoDB 的安裝

MongoDB 的安裝非常簡單,官網已經提供了各種作業系統的安裝說明(如下),所以這裡就不再贅述囉。
五、結論

MongoDB 因為獲得相當龐大的資金挹注,所以銀彈充足,目前改版速度相當快。以最近兩次改版僅間隔三個月(2014/01/10 才出 2.4.9 版、2014/04/08 便跳到 2.6.0 版),以及 2.6.0 版的 release notes 所揭露的新功能與改版幅度來看,現在 MongoDB 應該處於急速成長的階段。

雖然如此,但我仍覺得 MongoDB 是相當值得一試的產品!

2014年5月2日 星期五

MongoDB 學習筆記之一 - 從 NoSQL 談起


近年來,資訊業界最夯的話題莫過於 Cloud Computing 和 Big Data 了,而「NoSQL」便是伴隨著這兩個主題所產生的技術主題。

MongoDB 也算是一種 NoSQL DB,所以我們會先從 NoSQL 說起,以利讀者們對於 NoSQL DB 有個基本認識以後,之後才來介紹 MongoDB。

一、NoSQL 的定義

一般人第一次看到「NoSQL」,直覺地都會以為是「不使用 SQL」的意思,其實不然,所以目前業界比較傾向使用「Not Only SQL」來解釋 NoSQL 一詞,也就是說通常是透過類似 SQL 的 API 來存取這類 DB。

以下則是摘錄《nosql-database.org》網站對「NoSQL」的定義:

「Next Generation Databases mostly addressing some of the points: being non-relationaldistributedopen-source and horizontally scalable. 」

圖一、《nosql-database.org》網站上對「NoSQL」的定義與特徵說明
二、NoSQL DB 的特徵

以下特徵採用的是《Toad World》網站「Survey distributed databases」一文的說法。
  1. Schema-less
    有類似「Table」的資料結構,但不需預先定義 schema。每一筆記錄的欄位數量與結構也可以不一樣。紀錄的內容與限制條件主要由應用程式來控管。
  2. Shared nothing architecture
    通常採用本地儲存、而非共同儲存設備(如 SAN 或 NAS)。本地磁碟的存取速度較透過網路傳輸快,也能透過增加節點的方式來擴充容量。使用一般規格的硬體即可(commodity hardware),故成本也隨之下降。
  3. Elasticity
    只需增加更多主機,便能立即擴充儲存容量與負載能力,所以不需要有停機時間(downtime)。當新節點加入後,資料庫便會開始分配任務給它。
  4. Sharding
    不將儲存視為龐大的空間,取而代之的是以「分片」(shard)方式來分割資料集。分片可在主機間進行複製(replication),但一個分片至少會由一部主機來管理。分片過大時,可採用自動分割方式,或者以程式為每一筆記錄指派所屬的分片ID。
  5. Asynchronous replication
    相較於 RAID (mirroring / stripping)或同步複製機制,NoSQL DB採用的是非同步的複製。這種方式較不會受到額外網路流量影響,所以能使寫入動作更快完成。又因為資料不會立即複製,所以某些時候可能發生資料遺失的狀況。此外,也沒有 lock 機制以保護某些特定資料。
  6. BASE instead of ACID
    由於 NoSQL DB 強調的是效能與可用度,所以「CAP Theorem」會比 RDBMS 的「ACID」更為重要。

三、NoSQL DB 的類型

世界頂尖的大師級人物  Martin Fowler、堪稱為「架構師中的架構師」。他在 2013 年的「goto; Conference」有一場主題為「Introduction to NoSQL」的演講,其中便對 NoSQL DB 做了一個分類:DocumentBig TableGraph 以及 Key-Value

而下面這張圖就是我仿效該場演講其中一張投影片所重製的:

圖二、NoSQL DB 的四大類型
以下則是放在 Youtube 上面的錄影,請大家一睹大師風采。


四、Non-Relational vs. Relational

2012 年 TechCrunch 網站上有一篇介紹 Big Data 五大開放源碼技術趨勢的文章 —— 「Big Data Right Now: Five Trendy Open Source Technologies」。該文作者 Tim Gasper 是 InfoChimps 的產品總監,InfoChimps 則是一家專門提供 Big Data 服務、平台的公司。

下圖也是我重製文中的一張照片,原圖是一張不是很清晰的照片。

圖三、Non-Relational vs. Relational

由上圖,我們可以知道:MongoDB 應該是一種 Non-RelationalNoSQLDocument based 的 DB:
  1. Non-Relational:代表了「無法或不使用 JOIN」。
  2. NoSQL:代表了「不使用標準 SQL 語言」。
  3. Document based:代表了「每筆紀錄都是一個 document」(相對於 RDBMS 的 row 而言)。
五、NoSQL DB 的理論基礎 - CAP & BASE

在 2000 年 的 PODC(Principles of Distributed Computing)會議上,柏克萊加州大學的 Eric Brewer 提出了著名的 「CAP Theorem」(CAP 定理)。2002 年,Seth Gilbert 和 Nancy Lynch 證明了這一理論:

  • Consistency(一致性)
    一致性是說資料的原子性,這種原子性在傳統 RDBMS 中是透過 Transaction 來保證的,當 Transaction 完成時,無論其是成功還是回滾,資料都會處於一致的狀態。在分散式環境中,一致性是說多個節點的資料是否一致。
  • Availability(可用性)
    可用性是說服務能一直保證是可用的狀態,當使用者發出一個請求,服務能在有限時間內返回結果。
  • Partition Tolerance(分區容錯性)
    Partition 是指網路的分區。可以這樣理解,一般來說,關鍵的資料和服務都會位於不同的 IDC 機房。
下圖擷取自 Eric Brewer 的「Towards Robust Distributed Systems」簡報:

圖四、CAP Theorem

CAP 定理告訴我們:「一個分散式系統不可能同時滿足上述這三個需求,三個要素中最多只能同時滿足兩點」。因此,架構設計師不要把精力浪費在設計如何能同時滿足三者的完美分散式系統上,而是應該進行權衡取捨。

但是對於分散式資料系統而言,「分區容錯性」(P) 是基本要求,否則就不能稱為「分散式系統」了。因此,一般我們所說的 NoSQL DB 都是在「一致性」(C) 和「可用性」(A) 之間尋求平衡(即上圖中以紅色虛線框所標示的交集處)。

BASE 是 Basically Available、Soft state、Eventually consistent 三個片語的簡寫,是對 CAP 中 CA 的延伸:
  • Basically Available:基本可用;
  • Soft-state:軟狀態/柔性交易,即狀態可以有一段時間的不同步;
  • Eventual consistency:最終一致性;
BASE 是基於 CAP 理論逐步演化而來,核心思想是:即便不能達到「強一致性」(Strong consistency),但可以根據應用特點採用適當的方式來達到「最終一致性」(Eventual consistency)的效果。

BASE 是反 ACID 的,它完全不同於 ACID 模型,犧牲強一致性,獲得基本可用性和柔性可靠性,並要求達到最終一致性。

CAP 和 BASE 理論是 NoSQL 的理論基礎。

六、NoSQL DB 的缺點

個人以為 NoSQL DB 有以下三個缺點:

  1. 不易轉換
    不像 RDBMS 有共通的標準語言 —— SQL,各種 NoSQL 都有自己的 API。所以一旦選定某種 NoSQL 產品,便不易再轉換至其他產品,比方說由 MongoDB 轉換為 Couchbase
  2. 不支援 ACID
    ACID 可說是「Transaction」的構成要件,也是所有 RDBMS 的主要特性。但大部分的 NoSQL DB 都不保證 ACID,必須使用一些變通技巧來實現(MongoDB 可使用 2 Phase Commits)。
  3. 不支援 JOIN
    因為 NoSQL DB 是 Non-relational 的,所以不支援 JOIN 操作。以 MongoDB 而言,除了一開始就要妥善規劃 Data Model 之外(如使用 embedded document 或 reference),也可搭配 Index 和  Aggregation(含 MapReduce)等技巧來提高查詢效能。

本文對於 NoSQL 就暫時介紹到這裡囉,下面「延伸閱讀」還有許多不錯的資訊,各位也可以參考一下喔!

※ 延伸閱讀:

  1. [酷壳] 分布式系统的事务处理:
    http://coolshell.cn/articles/10910.html
  2. [Toad World] Survey distributed databases
    http://www.toadworld.com/products/toad-for-cloud-databases/w/wiki/308.survey-distributed-databases.aspx
  3. [Martin Fowloer] NoSQL
    http://martinfowler.com/nosql.html
  4. [myNoSQL] NoSQL Databases and Polyglot Persistence: A Curated Guide
    http://nosql.mypopescu.com/