NoSQL概念
隨着web2.0的快速發展,非關系型、分布式數據存儲得到了快速的發展,它們不保證關系數據的ACID特性(原子性、一致性、隔離性、持久性,一個支持事務的數據庫,必需要具有這四種特性,否則在事務過程當中無法保證數據的正確性)。NoSQL概念在2009年被提了出來。NoSQL最常見的解釋是“non-relational”,“Not Only SQL”也被很多人接受(“NoSQL”一詞最早於1998年被用於一個輕量級的關系數據庫的名字)。
NoSQL被我們用得最多的當數key-value存儲,當然還有其他的文檔型的、列存儲、圖型數據庫、xml數據庫等。在NoSQL概念提出之前,這些數據庫就被用於各種系統當中,但是卻很少用於web互聯網應用。比如cdb、qdbm、bdb數據庫。
傳統關系數據庫的瓶頸
傳統的關系數據庫具有不錯的性能,高穩定型,久經歷史考驗,而且使用簡單,功能強大,同時也積累了大量的成功案例。在互聯網領域,MySQL成為了絕對靠前的王者,毫不誇張的說,MySQL為互聯網的發展做出了卓越的貢獻。
在90年代,一個網站的訪問量一般都不大,用單個數據庫完全可以輕松應付。在那個時候,更多的都是靜態網頁,動態交互類型的網站不多。
到了最近10年,網站開始快速發展。火爆的論壇、博客、sns、微博逐漸引領web領域的潮流。在初期,論壇的流量其實也不大,如果你接觸網絡比較早,你可能還記得那個時候還有文本型存儲的論壇程序,可以想象一般的論壇的流量有多大。
Memcached+MySQL
后來,隨着訪問量的上升,幾乎大部分使用MySQL架構的網站在數據庫上都開始出現了性能問題,web程序不再僅僅專注在功能上,同時也在追求性能。程序員們開始大量的使用緩存技術來緩解數據庫的壓力,優化數據庫的結構和索引。開始比較流行的是通過文件緩存來緩解數據庫壓力,但是當訪問量繼續增大的時候,多台web機器通過文件緩存不能共享,大量的小文件緩存也帶了了比較高的IO壓力。在這個時候,Memcached就自然的成為一個非常時尚的技術產品。
Memcached作為一個獨立的分布式的緩存服務器,為多個web服務器提供了一個共享的高性能緩存服務,在Memcached服務器上,又發展了根據hash算法來進行多台Memcached緩存服務的擴展,然后又出現了一致性hash來解決增加或減少緩存服務器導致重新hash帶來的大量緩存失效的弊端。當時,如果你去面試,你說你有Memcached經驗,肯定會加分的。
Mysql主從復制實現讀寫分離
由於數據庫的寫入壓力增加,Memcached只能緩解數據庫的讀取壓力。讀寫集中在一個數據庫上讓數據庫不堪重負,大部分網站開始使用主從復制技術來達到讀寫分離,以提高讀寫性能和讀庫的可擴展性。Mysql的master-slave模式成為這個時候的網站標配了。
分庫分表
隨着web2.0的繼續高速發展,在Memcached的高速緩存,MySQL的主從復制,讀寫分離的基礎之上,這時MySQL主庫的寫壓力開始出現瓶頸,而數據量的持續猛增,由於MyISAM使用表鎖,在高並發下會出現嚴重的鎖問題,大量的高並發MySQL應用開始使用InnoDB引擎代替MyISAM。同時,開始流行使用分表分庫來緩解寫壓力和數據增長的擴展問題。這個時候,分表分庫成了一個熱門技術,是面試的熱門問題也是業界討論的熱門技術問題。也就在這個時候,MySQL推出了還不太穩定的表分區,這也給技術實力一般的公司帶來了希望。雖然MySQL推出了MySQL Cluster集群,但是由於在互聯網行業內幾乎沒有成功案例,性能也不能滿足互聯網的要求,只是在高可靠性上提供了非常大的保證。
MySQL的擴展性瓶頸
在互聯網,大部分的MySQL都應該是IO密集型的,事實上,如果你的MySQL是個CPU密集型的話,那么很可能你的MySQL設計得有性能問題,需要優化了。大數據量高並發環境下的MySQL應用開發越來越復雜,也越來越具有技術挑戰性。分表分庫的規則把握都是需要經驗的。雖然有像淘寶這樣技術實力強大的公司開發了透明的中間件層來屏蔽開發者的復雜性,但是避免不了整個架構的復雜性。分庫分表的子庫到一定階段又面臨擴展問題。還有就是需求的變更,可能又需要一種新的分庫方式。
MySQL數據庫也經常存儲一些大文本字段,導致數據庫表非常的大,在做數據庫恢復的時候就導致非常的慢,不容易快速恢復數據庫。比如1000萬4KB大小的文本就接近40GB的大小,如果能把這些數據從MySQL省去,MySQL將變得非常的小。
關系數據庫很強大,但是它並不能很好的應付所有的應用場景。MySQL的擴展性差(需要復雜的技術來實現),大數據量場景下IO壓力大,表結構更改困難,正是當前使用MySQL的開發人員面臨的問題。
NoSQL的優勢
NoSQL數據庫種類繁多,但是一個共同的特點都是去掉關系數據庫的關系型特性。數據之間無關系,這樣就非常容易擴展。也無形之間,在架構的層面上帶來了可擴展的能力。
NoSQL數據庫都具有非常高的讀寫性能,尤其在大數據量下,同樣表現優秀。這得益於它的無關系性,數據庫的結構簡單。一般MySQL使用Query Cache,每次表出現更新后Cache就失效,這是一種大粒度的Cache,針對web2.0的交互頻繁的應用,Cache性能不高。而NoSQL的Cache是記錄級的,是一種細粒度的Cache,所以NoSQL在這個層面上來說就要性能高很多了。
不明白什么是Query Cache?
當mysql接收到一條select類型的query時,mysql會對這條query進行hash計算而得到一個hash值,然后通過該hash值到query cache中去匹配,如果沒有匹配中,則將這個hash值存放在一個hash鏈表中,同時將query的結果集存放進cache中,存放hash值的鏈表的每一個hash節點中存放了相應query結果集在cache中的地址,以及該query所涉及到的一些table的相關信息;如果通過hash值匹配到了一樣的query,則直接將cache中相應的query結果集返回給客戶端。如果mysql任何一張表中的任何一條數據發生了變化,便會通知query cache需要將與該table相關的query cache全部失效,並釋放占用的內存地址。
query cache的優點很明顯,對於一些頻繁執行select操作的表,mysql直接從cache中返回相應的結果集,而不用再從表table中取出,減少了IO開銷。即使query cache的收益很明顯,也不能忽略它所帶來的一些缺點:1、query語句的hash計算和hash查找帶來的資源消耗。mysql會對每條接收到的select類型的query進行hash計算然后查找該query的cache是否存在,雖然hash計算和查找的效率已經足夠高了,一條query所帶來的消耗可以忽略,但一旦涉及到高並發,有成千上萬條query時,hash計算和查找所帶來的開銷就的重視了;2、query cache的失效問題。如果表的變更比較頻繁,則會造成query cache的失效率非常高。表的變更不僅僅指表中的數據發生變化,還包括結構或者索引的任何變化;3、對於不同sql但同一結果集的query都會被緩存,這樣便會造成內存資源的過渡消耗。sql的字符大小寫、空格或者注釋的不同,緩存都是認為是不同的sql(因為他們的hash值會不同)。
NoSQL無需事先為要存儲的數據建立字段,隨時可以存儲自定義的數據格式。而在關系數據庫里,增刪字段是一件非常麻煩的事情。如果是數據量非常大的表,增加字段簡直就是一個噩夢。這一點在大數據量的web2.0時代尤其明顯。
NoSQL在不太影響性能的情況,就可以方便的實現高可用的架構。比如Cassandra,HBase模型,通過復制模型也能實現高可用。
總結
NoSQL數據庫的出現,彌補了關系數據(比如MySQL)在某些方面的不足,在某些方面能極大的節省開發成本和維護成本。MySQL和NoSQL都有各自的特點和使用的應用場景,兩者的緊密結合將會給web2.0的數據庫發展帶來新的思路。讓關系型數據庫關注在關系上,NoSQL關注在存儲上。
本文轉載自NoSQL開篇——為什么要使用NoSQL