RDBMS v.s. NoSQL
現在主流的資料庫像是 MySQL 之類的是關聯式資料庫 (RDBMS),不過隨著網路的發展,關聯式資料庫的特性在某些應用上其實沒有那麼適合。比方說,你對於資料間的關聯性沒那麼在意,你在意的是特定人、事或物的 "狀態" 變動,特別是這種狀態的變動非常大量且頻繁時,關聯式資料庫在處理這種需求就會變得力不從心,也因此後來有發展出了 NoSQL 這東西是專門針對這種應用設計的。而這次被主管要求要看的 MongoDB 正是一種 NoSQL DB。
RDBMS (Relational Database Management System)
關聯式資料庫在意的是資料之間的關聯性,也因此在設計關聯式資料庫時綱要 (Schema) 就顯得非常重要。因為這關係的是你要如何設計你的資料表 (像是要擁有那些欄位)、資料表之間的關聯性如何設計,接著就可以透過 SQL (structural language) 在不同資料表之間利用他們的關聯性組合 / 過濾出你要的資訊。
基於上述的特徵,RDBMS 有一件事情非常重要:正規化 (normalization)。藉由正規化避免不同資料表儲存了重複的資訊,如此一來在資料更新時可以 DB 中有重複的資料沒有同時被更新。不過也正因為這件事,綱要的設計就變得更重要,因為這時綱要的設計牽涉到的不只是正規化的問題,該怎麼更新、儲存資料到資料表就跟你的綱要有密切的關連性。
從上面的說明應該足以了解綱要的設計對於 RDBMS 的重要性,不過這同時也引出了一個問題:如果一開始的綱要設計不良,使用一段時間後才想要變更怎麼辦? 嗯,通常這就是一件大工程,因為第一件事情是要把所有的資料表變更成新的綱要架構,資料量大的時候這很費工;另一件事情就是所有用到這個 DB 的程式也都要更新修改,因此這也是一件大工程。
RDBMS 的另一個問題也是從綱要 & 正規化來的。想想看現今網路應用的資料量會有多龐大 (像是 FB 或 google 在處理的資料量),這些資料絕對不可能只讓一台主機去處理,一定會分散在許多主機。當 RDBMS 的資料表分散在不同主機時,想要取得某個查詢的結果或者是要更新資料時會變得相當麻煩:因為你可能會需要從主機 A 的資料表 X 去跟主機 B 的資料表 Y 先利用關鍵字找出你有興趣的資料區間,接著再這把這些資料統合成你要的結果。如果資料量又更多時,問題也不會因為僅僅多加幾台主機就能緩解,因為如何維護著這些資料表的關聯性也會是一大挑戰。所以就結論而言,在分散式系統的環境下 RDBMS 的優勢就難以發揮了。這些都是導致後來提出 NoSQL 的契機。
NoSQL (Not Only SQL)
相較於 RDBMS,NoSQL 其中一大特色就是設計 DB 時可以無綱要吧,他儲存資料的方法不像 RDBMS 有固定的欄位與綱要,他的概念偏向於
- 每一筆資料都當成一個文件 (而且每個文件可以長得不一樣)
- 每一個文件都給他一個唯一的編號
其實這樣的組合就有點像是一個 hash table 的概念。NoSQL 在意的是某個編號底下的文件有沒有需要更新、需不需要新增/刪除某份/些文件等等,因此相較於 RDBMS,文件之間是否有重複的資料以及是否有任何關連性比較不是 NoSQL 在意的重點,也因此早期 NoSQL 好像真的就是指不用 SQL,不過現在普遍認為 NoSQL 應該是 Not Only SQL,其中一個原因應該是來自於 NoSQL 其實也是可以支援部分 SQL 語法的。
要舉例的話,比較常看到的例子就是某個遊戲的玩家資料,又或者是社群網站上的個人資料 (像是 FB 就自己開發了一套 NoSQL 叫 Cassandra) 等等。
NoSQL 基於這樣的特性,要隨時增減伺服器的數量會變得比 RDBMS 容易許多,當然相對的也會有一些問題。舉例來說,RDBMS 通常都會提供 ACID (下面會介紹) 的保證,而 NoSQL因為儲存資料的方式本來就已經沒有固定的格式甚至可能有大量的重複資料 (想像一下:線上遊戲的廠商想要把某項武器修改調整他的屬性甚至是移除?) 這種狀況下還要 NoSQL 提供 ACID 的保證無疑會浪費掉 NoSQL 的優勢,也因此現在 NoSQL DB 提供的則是 CAP (也是下面會介紹)。
Scaling
Scaling 指的是 DB 如何提升他的處理能力,分成 vertical 跟 horizontal
- Vertical scaling
- 直接提升主機本身的處理能力 (EX: 加大硬碟或是 CPU 處理速度加快)
- 就像早期個人電腦變快的方法都是直接加速 CPU 的時脈,這種針對零件本身的效能提升
- Horizontal Scaling
- 一台主機不夠你有沒有用兩台?
- 增加主機的數量就是 horizontal scaling 的精神,就像現在 CPU 都是多核心那樣,藉由增加數量來增加可處理的餘裕
- 不過增加數量跟能提升效能不見得是正比,比方說 CPU 是八核心,結果每次都只讓其中 一個核心做事的話你的電腦跑起來還是會很慢
以 RDBMS 跟 NoSQL 來看,RDBMS 用 vertical scaling 比較容易看到效能的提升,而 NoSQL 的架構則是非常容易採用 horizontal scaling,也是現在 web-base 應用最需要的特色
ACID
- A = Atomicity
- Each transaction be "all or nothing"
- C = Consistency
- Any transaction will bring the database from one valid state to another
- I = Isolation
- Concurrent execution of transactions results in a system state that would be obtained if transactions were executed sequentially
- D = Durability
- Once a transaction has been committed, it will remain so, even in the event of power loss, crashes, or errors.
A: 一道指令下去要嘛成功不然就是完全沒影響 (all or nothing)。比方說轉帳這件事,你不會希望轉帳失敗後對方沒收到錢但你的帳戶還是被扣錢了
C: 資料庫的一致性。同樣是轉帳這件事當例子,A 轉了 10 元給 B,結果 B 只拿到 5 元就是不一致,這時候資料庫比須取消這項操作
I: 數道指令同時執行跟他們以某項順序依序執行,最後的結果必須完全一樣。還是拿轉帳當例子,A 轉給 B $10,B 也要轉給 C $10,A、B 同時轉帳跟 A 先轉再換 B 以及 B 先轉帳再換 A 最後的結果必須都要一樣。
D: 一道指令成功後就永遠都是有效的。你不會希望轉帳成功後因為突然停電結果發現剛剛轉帳的結果不見了。
NoSQL 因為其特性難以保證 ACID,特別是 consistency 這一項有時候只會提供 eventually consistent (也就是現在不一致沒關係,過了一段時間後會一致就好),所以 NoSQL 是有可能出現同一筆資料現在讀跟晚點再讀結果不一樣這種情形...而且由於 NoSQL 比較常被用在分散式的儲存環境,相較於 ACID,更加注重的是下面的 CAP。
CAP Theorem
- C = Consistency
- Every read receives the most recent write or an error
- A = Availability
- Every request receives a (non-error) response – without guarantee that it contains the most recent write
- P = Partition tolerance
- The system continues to operate despite an arbitrary number of messages being dropped (or delayed) by the network between nodes
Theorem
It is impossible for a distributed data store to provide more than two out of the above three guarantees.
CAP 特別針對的是分散式的儲存環境 (所以就是 NoSQL DB 最常被應用的環境)。而且根據這個理論會發現不可能同時提供三個保證,因此目前 NoSQL 通常是提供 2 個,至於是哪 2 個就要看設計者了。不過要說 MongoDB 提供了哪兩個...根據這一篇來看似乎可以根據你的設定有所改變。
這邊要特別注意的是提供 CAP 的保證根提供 ACID 的保證是兩回事,ACID 就算不會全部提供也不代表都不會有,像是 MongoDB 就有提供 Read Isolation 跟 Consistency 的保證,而且 MongoDB 也是會依據情況提供 Atomicity 的保證的。
沒有留言:
張貼留言