Consistency

08:33下午 七月 10, 2010 in category Java by ingramchen

前幾個月為了 scale 我們的資料庫,我們轉向 NoSQL 這個新領域求助,而最後,我選擇了 Apache Cassandra。現在它安穩地服務了兩個月有餘,暫時還沒遇到大問題。 資料庫 Scalability 這個題材我初次碰到,當初自然作了一些功課,尤其是對 Consistency 的意義重新了解。趁我還有一些記憶,用自己的話重新解釋一遍,強化記憶和概念。

Consistency (一致性) 這個字太泛稱了,可以用在不同的題材之下。這裡只討論資料庫,那就估且稱作 資料一致性 吧。資料一致性,是在一致什麼玩意呢?Relational Database Management System,RDBMS,通常滿足 ACID 的要求。ACID 的性質就包含了 Consistency 的定義:

  • Atomicity:一個 transaction 中,資料不是全部變更成功,就是全部失敗
  • Consistency:每一個 transaction 完成後,資料都必須永遠符合 schema 的規範,例如 schema 中所定義的資料格式 (type)、資料限制 (constraint)、資料間的 referential integrity... 等等
  • Isolation:同時進行的 transaction 間,互相不影響。
  • Durability:當 transaction 完成後,它所做的資料異動永遠存在,不論未來是否出現任何軟體或硬體方面的故障。

ACID 的各個性質句句不離 transaction 啊!不過,讓我們先拋開它,來看看 ACID 中的 C。老實說這裡 C 的定義挺陜隘的,它只要求資料要符合 schema, 然後就沒了。如果要選個更確切的字來描述這樣的性質,我寧可選 Valid,或是 Integrity 這樣的字眼,而不是 Consistency。當初為什麼選 Consistency ? 猜想是為了湊單字,湊個漂亮的 ACID (酸) 吧。有獨無偶,NoSQL 界也湊了個單字叫 BASE (鹼) - Basically Available Soft-state Eventually Consistency 這幾個字湊的太明顯了,逐字解釋它反而變得沒有意義,不過它還是帶出了 Eventually Consistency - 最終一致性。

Eventually Consistency,這字眼出現在各個討論 scalability 的部落格裡,這裡的 Consistency,又是指什麼? 這個問題的答案,要再往前追溯,追溯這些專家們,他們面臨了什麼問題。

他們面臨了 Scalability 的問題 (廢話...) ,再白話一點說,他們發現一台機器跑不動 (廢話的平方...)。 哈,很廢話沒錯,但它的背景和時代有關。RDBMS 擁有一段很長的歷史,它所著重的,都是讀取的效能和 transaction,因為過去只需要這兩種特性就可以滿足大部份的需求。 在這個前提下,要保有 ACID 性質還不算難。 但是,現在我們已經經歷過所謂的 web 2.0,進入了 Social Network (facebook) , 進入了 Cloud (google/amazon)。估且不論 web 2.0 和 cloud 的確切定義是什麼, 它們的共同特徵是用戶產生大量的資料,用戶不是單純的讀取資訊了,他們變成資訊貢獻者,他們產生了大量的 寫入。這時 RDBMS 垮了,一台撐不住這麼大量的寫入, 專家們只好死命的升級硬體, 但是量還是太大了,硬體趕不上了。這時馬上轉念:"那麼多裝個幾台試試吧"。然而,結果就像老闆一向以為加員工就可以加快專案進度一樣... 你知道的。

為了應付大量了寫入,工程師裝了兩台 database,這兩台的資料都一樣,所以可以分散資料的讀寫,降低系統負荷,也大大降低服務被中斷的機會。但事情從這時開始變複雜啦:

  • 用戶 A 寫入一筆,100 元到第一台,但用戶 A 後來卻向第二台讀同一筆,用戶 A 自然是氣的直跳腳,狂打客服!
  • 用戶 A 寫入一筆,100 元到第一台,用戶 B 同時也寫了入同一筆,200元到第二台。請問哪一台才是對的?
  • 用戶 A 寫入一筆,100 元到第一台,系統很聰明地在背後將這一筆同步到第二台,但不巧這時第二台剛好掛了。一小時後,第二台救回來了。但不見的變更怎麼補救呢?
  • ...etc

上述是一些可能遇到的問題,光是用想的就夠煩的了,資料要怎麼在多台間同步,並達到一致呢?ok, 我思考到這裡, 才發現原來專家們掛在嘴邊的 Consistency 是這個意思 -- 多台主機間,任何時間點,同一筆資料的一致性。跟 ACID 的 C 定義還差真遠, 先入為主的思考方式真是害死人啦。想通了這點,我才看懂 CAP 理論 是在講什麼。 CAP 理論中提到,下面的三點我們只能同時滿足兩點:

  • Consistency:多台主機間,任何時間點,同一筆資料的一致性
  • Availability:任何時間點資料都可以讀寫
  • Partition Tolerance:主機間出現斷層的容忍性,也就是主機間可不可以有一段時間不能相連。(例如網路斷線)

ps. 上面三點是我自己的見解,真正的解釋請見上面提供的連結。

為什麼只能同時滿足兩點?而實際上,我們只有 CP 和 AP 兩種可以選擇,沒有系統可以滿足 CA。 先來解釋 CP 好了,第一點 Consistency:我希望所有主機的資料一致,不會有人讀到舊的資料。 那麼,我必須每次寫入時,所有相關的主機都要同步更新,一台都不能漏。接下來是滿足第三點 Partition: 我希望系統可以容忍主機間發生斷層。網路斷線或某台主機掛點是很常見的,可以容忍這類錯誤的系統才是務實的作法。 好了,又要保持資料能同步更新,又要允許主機間中斷,那只好一旦發生中斷時,就停止資料的更新,直到主機回復後,才允許服務繼續。 換句話說,用戶就看到錯誤啦,而且還要等上一段時間。因此第二點 Availability 就不能滿足了。

好,再來看看 AP,我希望系統可以容忍主機間斷層 (Partition),又要發生斷層時,還讓用戶繼續讀寫資料 (Availability)。那還能怎麼辦? 只能讓用戶讀到不一致的資料囉:用戶寫資料到第一台,但系統無法同步到那個掛點的第二台,為了不讓服務中斷,我們只能回應用戶服務已成功。 之後第二台救回來了,用戶跑去讀第二台,他就會看到過期的資料。所以 Consistency 就無法滿足了。

那 CA 呢?滿足 CA 的條件是矛盾的,如果系統不能容忍斷層 (放棄 P),那麼等於是宣告了只能有一台主機,只有一台主機是可以滿足 Consistency 的。 但 Availability 就不可能了,只有一台主機是不可能達到不間斷的服務。

剛才的 AP 系統,我們說用戶可能會讀到過期的資料,那麼,我們何不盡可能的修復第二台的資料,讓資料的不一致性減到最低呢?這樣的概念就是 Eventually Consistency -- 資料最終會達到一致。用戶是可能讀到錯的資料,但下次再讀,就是對的了。 不是所有日常生活中的電腦系統,都一定要絕對的一致性才能使用。舉兩個例子,例如我們設計了一個類似的 email 系統,像是一般常見的站內信。 A 寄信給 B,資料寫到時第一台成功了,但同步到第二台卻失敗了,B 這時跑去看他的 in-box ,第一次看沒有,因為他連到的是第二台,後來再 refresh 一次, 他就看到了,因為系統已修復了第二台的錯誤。refresh 後才看到新信不是天天都在經歷嗎?沒什麼問題啊!另外一個例子就比較常見了,就是 DNS 系統,DNS 更新時是漸漸擴散到所有的主機,最後才達到一致,二十年來都是這樣運作的,有時的確有些不便,但是整體來說非常的成功,是 internet 的基石之一。

CP 與 AP 雖然只能選擇一種,但不代表一套軟體只能支援一種,例如 Cassandra 可以支援 CP,也可以支援 AP,端看軟體設定而定 (另外一個 NoSQL: Riak 聽說也是如此), 另外,對於 Eventually Consistency 常見的誤解是:"感覺上隨時都有可能出現不一致的資料"。其實不然,當主機都是好好時,放在 Cassandra 這類資料庫的資料是保持一致的, 只有當異常發生時,這段時間受影響的資料才會退回 Eventually Consistency。主機間發生斷層是不可預期的,但不代表這會是常態,系統大部份的資料,在大部份的時間裡都是保持一致的。

迴響[2]

NoSQL to die

10:12上午 三月 28, 2010 in category Java by ingramchen

今早看了一篇文章:

I can't wait for NoSql to die

有感而發所以又來嘴炮一下:

NoSQL 大致分為兩個族系,其一是 document database, 其二是 key-value store。這兩個族系只是因為都不是 relational 所以一起被炒熱。兩者的背景和運用都不同,未來的命運也會不一樣,只差在死的方式而已。

document db 跟 RoR / Django 這一些社群走的比較近,所以命運會和 RoR 那些差不多 ==> 多半只是為了求新求 cool 而已,看了 document db 老半天,我覺得沒什麼迫切的理由要用。所以我猜之後會和 RoR 一樣被邊緣化,被一些更新更夯的東西取代吧。

object db 跟 document db 很像,不是嗎?前者也是有一陣大熱潮啊,但後來就消失了。Object 在 db 端消失了,但在語言端卻更為壯大,到後來甚至為了跟 relational 橋接,而有了 ORM 的全盛時期,Hibernate 是當時的領頭羊。如果 document db 消失了,而 web 服務還是很需要 document 的方式存取資料,也許之後會有 DRM (Document-Relational-Mapping) 的全盛時期。

至於第二個族系 key-value clusters 則是另外一回事了,這些東西都是超大的站在用 (google, amazon, facebook, digg, twitter) 而且已經好幾年了。現在開發者會趁熱找機會摸一摸,不過大概都沒什麼機會發揮。因為大部份的服務 scale 都太小了。等到 NoSQL 熱潮過之後,就會只剩原來的那些大型服務繼續開發和使用,再也無人問津。(這裡的 "大型服務" 是指公司的 "某一服務" 需要 50 台以上的 server)

當然我個人不希望 key-value store 沒人炒就沒下聞了。之前在某篇文章看到:

...NoSQL is an attempt to solve 3 technical problems that every big company faces: Transparent automation of sharding, replication and failover...

我想他說的 NoSQL 是專指 key-value store 這個族系。我本身為一個 server-side-guy,"sharding,replication 和 failover" 這三件事一直不斷的遇到,而且真的很煩很頭痛,如果有什麼解決方法可以讓痛苦少一點,我是不管怎麼樣都要先跳下去試一下不可。Cassandra 是目前看到的一道曙光,希望它能讓痛苦少一點。

至於無痛 scale up 則是一種迷思,最具代表性的就是 vertical scale-up -- 有個傢伙說什麼買個 128GB ram + SSD raid,這樣就搞定 digg scale 的問題。但這能一直加上去嗎?終究只是暫時的止痛劑而已。

成長永遠都是伴隨著痛苦!

最後,對於非網路公司,尤其是那些金融的,他們還是會繼續花大錢買 RDBMS,買爆力的機器,金融業重視 consistency,重視 ACID 是沒錯的,大企業需要強大的RDBMS,oracle / ibm / ms 這些公司就會生給他們,但是,oracle 這些公司特別的將高硬體規格的 db licence 費用調好幾倍貴,反正客戶付得起嘛,不搶白不搶啊!

迴響[7]

Cassandra Rant

09:57上午 三月 15, 2010 in category Java by ingramchen

昨天看了一篇 Cassandra 的 modeling 範例

WTF is a SuperColumn? An Intro to the Cassandra Data Model

這一篇我看兩次了,現在終於看懂一半了... NoSQL 號稱 schema free ,可以自由設計,可是遠比 Relational 還難設計很多。設計 Cassandra 的 'schema' 時,我們必需先想好要怎麼 query (你的 use case) ,然後才能下手。然後幾乎是一個 query 就要生一個專用的 'table' 給他用。

用比較的方式來想:如果我們在 RDBMS 裡有一個 table ,然後對這個 table 有三種 use case,在 RDBMS 裡我們就寫三個 SQL,然後加加 index 改進效能。這樣的需求在 cassandra 就變成要生出三個 'table' 專門來應付這三個 use case,而且,想當然爾,這三個 table 的資料全部 denormalize。

Cassandra 這樣做與 relational 相比有什麼缺點呢?最直接的是:我們得事先知道這三個 use case,不然設計不出來。而軟體的專案特性是什麼?需求只會一直改!而且還會隨時間不斷冒出來!Relational 可以讓我們在 '事後' 需求出現後,寫個 SQL 補個 index 就搞定了。 Cassandra 可不行啊,我們得為那個 query, clone 一整份 table 的資料, 然後如果有其他地方 update 的話,也要通通一起改 (都 denormalized 了嘛....)

NoSQL 這樣的概念完全無法適應客製軟體的開發,尤其是在 enterprise 裡,那種瞬息萬變的各種專案大小需求,用這篇 blog 的範例舉例:例如本來的用戶需求是:"我要列出某個有 sports tag 的所有 blog 文",當時我們用 nosql 設計好了。然後之後 woods 事件爆發,他跑來說,我要改成 "列有 sports tag, 但是沒有 woods 的 blog 文"

哇咧!用 Cassendra 是要怎麼改?只能再做一個 sports minus woods 的 'table' ,然後 insert 到 sports 的程式通通再改寫一遍。暈倒,想到就沒力!

但是!如果 blog 系統是給一億人用,那又是另外一回事了,我想RDBMS根本跑不起來。Cassandra 再難用也得用了。也許適合用 NoSQL 的 project 都有類似的特質:

  • 用戶超多,使用時間也長

    因此用戶其實也很抗拒改變,想想 facebook 改版多少人在叫了

  • 改變的動機來自於平台商內部,而不是用戶

    一般軟體是 "付錢的" 用戶不斷提需求的,所以要不斷的改,但 facebook/twitter 感覺就是平台商施捨給用戶的,我 (平台) 給多少功能,你 (用戶) 就用多少功能,誰叫你沒付錢呢?需求改變的頻率變成由平台商主導,所以改變數也可以大大減少吧。

想到這裡,我就覺得 NoSQL 並不會改變 IT 界的日常生態,也完全無法取代 SQL。只有在 mega web apps 這個圈子的人才有機會碰到,也許未來這會變常態,也許不會。

迴響[0]