本質是因為:隨著互聯網的進一步發展與各行業信息化建設進程加快、參與者的增多,人們對軟件有了更多更新的要求,需要軟件不僅能實現功能,而且要求保證許多人可以共同參與使用,因而軟件所需承載的數據量和吞吐量必須達到相應的需求。而目前的關系型數據庫在某些方面有一些缺點,導致不能滿足需要。
屏南網站制作公司哪家好,找創新互聯!從網頁設計、網站建設、微信開發、APP開發、成都響應式網站建設等網站項目制作,到程序開發,運營維護。創新互聯自2013年創立以來到現在10年的時間,我們擁有了豐富的建站經驗和運維經驗,來保證我們的工作的順利進行。專注于網站建設就選創新互聯。
具體則需要對比關系型數據庫與Nosql之間的區別可以得出
關系型數據庫
關系型數據庫把所有的數據都通過行和列的二元表現形式表示出來。
關系型數據庫的優勢:
1.?保持數據的一致性(事務處理)
2.由于以標準化為前提,數據更新的開銷很小(相同的字段基本上都只有一處)
3.?可以進行Join等復雜查詢
其中能夠保持數據的一致性是關系型數據庫的最大優勢。
關系型數據庫的不足:
不擅長的處理
1.?大量數據的寫入處理(這點尤為重要)
2.?為有數據更新的表做索引或表結構(schema)變更
3.?字段不固定時應用
4.?對簡單查詢需要快速返回結果的處理
--大量數據的寫入處理
讀寫集中在一個數據庫上讓數據庫不堪重負,大部分網站已使用主從復制技術實現讀寫分離,以提高讀寫性能和讀庫的可擴展性。
所以在進行大量數據操作時,會使用數據庫主從模式。數據的寫入由主數據庫負責,數據的讀入由從數據庫負責,可以比較簡單地通過增加從數據庫來實現規模化,但是數據的寫入卻完全沒有簡單的方法來解決規模化問題。
第一,要想將數據的寫入規模化,可以考慮把主數據庫從一臺增加到兩臺,作為互相關聯復制的二元主數據庫使用,確實這樣可以把每臺主數據庫的負荷減少一半,但是更新處理會發生沖突,可能會造成數據的不一致,為了避免這樣的問題,需要把對每個表的請求分別分配給合適的主數據庫來處理。
第二,可以考慮把數據庫分割開來,分別放在不同的數據庫服務器上,比如將不同的表放在不同的數據庫服務器上,數據庫分割可以減少每臺數據庫服務器上的數據量,以便減少硬盤IO的輸入、輸出處理,實現內存上的高速處理。但是由于分別存儲字不同服務器上的表之間無法進行Join處理,數據庫分割的時候就需要預先考慮這些問題,數據庫分割之后,如果一定要進行Join處理,就必須要在程序中進行關聯,這是非常困難的。
--為有數據更新的表做索引或表結構變更
在使用關系型數據庫時,為了加快查詢速度需要創建索引,為了增加必要的字段就一定要改變表結構,為了進行這些處理,需要對表進行共享鎖定,這期間數據變更、更新、插入、刪除等都是無法進行的。如果需要進行一些耗時操作,例如為數據量比較大的表創建索引或是變更其表結構,就需要特別注意,長時間內數據可能無法進行更新。
--字段不固定時的應用
如果字段不固定,利用關系型數據庫也是比較困難的,有人會說,需要的時候加個字段就可以了,這樣的方法也不是不可以,但在實際運用中每次都進行反復的表結構變更是非常痛苦的。你也可以預先設定大量的預備字段,但這樣的話,時間一長很容易弄不清除字段和數據的對應狀態,即哪個字段保存有哪些數據。
--對簡單查詢需要快速返回結果的處理? (這里的“簡單”指的是沒有復雜的查詢條件)
這一點稱不上是缺點,但不管怎樣,關系型數據庫并不擅長對簡單的查詢快速返回結果,因為關系型數據庫是使用專門的sql語言進行數據讀取的,它需要對sql與越南進行解析,同時還有對表的鎖定和解鎖等這樣的額外開銷,這里并不是說關系型數據庫的速度太慢,而只是想告訴大家若希望對簡單查詢進行高速處理,則沒有必要非使用關系型數據庫不可。
NoSQL數據庫
關系型數據庫應用廣泛,能進行事務處理和表連接等復雜查詢。相對地,NoSQL數據庫只應用在特定領域,基本上不進行復雜的處理,但它恰恰彌補了之前所列舉的關系型數據庫的不足之處。
優點:
易于數據的分散
各個數據之間存在關聯是關系型數據庫得名的主要原因,為了進行join處理,關系型數據庫不得不把數據存儲在同一個服務器內,這不利于數據的分散,這也是關系型數據庫并不擅長大數據量的寫入處理的原因。相反NoSQL數據庫原本就不支持Join處理,各個數據都是獨立設計的,很容易把數據分散在多個服務器上,故減少了每個服務器上的數據量,即使要處理大量數據的寫入,也變得更加容易,數據的讀入操作當然也同樣容易。
典型的NoSQL數據庫
臨時性鍵值存儲(memcached、Redis)、永久性鍵值存儲(ROMA、Redis)、面向文檔的數據庫(MongoDB、CouchDB)、面向列的數據庫(Cassandra、HBase)
一、 鍵值存儲
它的數據是以鍵值的形式存儲的,雖然它的速度非常快,但基本上只能通過鍵的完全一致查詢獲取數據,根據數據的保存方式可以分為臨時性、永久性和兩者兼具 三種。
(1)臨時性
所謂臨時性就是數據有可能丟失,memcached把所有數據都保存在內存中,這樣保存和讀取的速度非常快,但是當memcached停止時,數據就不存在了。由于數據保存在內存中,所以無法操作超出內存容量的數據,舊數據會丟失。總結來說:
。在內存中保存數據
。可以進行非常快速的保存和讀取處理
。數據有可能丟失
(2)永久性
所謂永久性就是數據不會丟失,這里的鍵值存儲是把數據保存在硬盤上,與臨時性比起來,由于必然要發生對硬盤的IO操作,所以性能上還是有差距的,但數據不會丟失是它最大的優勢。總結來說:
。在硬盤上保存數據
。可以進行非常快速的保存和讀取處理(但無法與memcached相比)
。數據不會丟失
(3) 兩者兼備
Redis屬于這種類型。Redis有些特殊,臨時性和永久性兼具。Redis首先把數據保存在內存中,在滿足特定條件(默認是?15分鐘一次以上,5分鐘內10個以上,1分鐘內10000個以上的鍵發生變更)的時候將數據寫入到硬盤中,這樣既確保了內存中數據的處理速度,又可以通過寫入硬盤來保證數據的永久性,這種類型的數據庫特別適合處理數組類型的數據。總結來說:
。同時在內存和硬盤上保存數據
。可以進行非常快速的保存和讀取處理
。保存在硬盤上的數據不會消失(可以恢復)
。適合于處理數組類型的數據
二、面向文檔的數據庫
MongoDB、CouchDB屬于這種類型,它們屬于NoSQL數據庫,但與鍵值存儲相異。
(1)不定義表結構
即使不定義表結構,也可以像定義了表結構一樣使用,還省去了變更表結構的麻煩。
(2)可以使用復雜的查詢條件
跟鍵值存儲不同的是,面向文檔的數據庫可以通過復雜的查詢條件來獲取數據,雖然不具備事務處理和Join這些關系型數據庫所具有的處理能力,但初次以外的其他處理基本上都能實現。
三、?面向列的數據庫
Cassandra、HBae、HyperTable屬于這種類型,由于近年來數據量出現爆發性增長,這種類型的NoSQL數據庫尤其引入注目。
普通的關系型數據庫都是以行為單位來存儲數據的,擅長以行為單位的讀入處理,比如特定條件數據的獲取。因此,關系型數據庫也被成為面向行的數據庫。相反,面向列的數據庫是以列為單位來存儲數據的,擅長以列為單位讀入數據。
面向列的數據庫具有搞擴展性,即使數據增加也不會降低相應的處理速度(特別是寫入速度),所以它主要應用于需要處理大量數據的情況。另外,把它作為批處理程序的存儲器來對大量數據進行更新也是非常有用的。但由于面向列的數據庫跟現行數據庫存儲的思維方式有很大不同,故應用起來十分困難。
總結:關系型數據庫與NoSQL數據庫并非對立而是互補的關系,即通常情況下使用關系型數據庫,在適合使用NoSQL的時候使用NoSQL數據庫,讓NoSQL數據庫對關系型數據庫的不足進行彌補。
Hadoop
文件系統:文件系統是用來存儲和管理文件,并且提供文件的查詢、增加、刪除等操作。
直觀上的體驗:在shell窗口輸入 ls 命令,就可以看到當前目錄下的文件夾、文件。
文件存儲在哪里?硬盤
一臺只有250G硬盤的電腦,如果需要存儲500G的文件可以怎么辦?先將電腦硬盤擴容至少250G,再將文件分割成多塊,放到多塊硬盤上儲存。
通過 hdfs dfs -ls 命令可以查看分布式文件系統中的文件,就像本地的ls命令一樣。
HDFS在客戶端上提供了查詢、新增和刪除的指令,可以實現將分布在多臺機器上的文件系統進行統一的管理。
在分布式文件系統中,一個大文件會被切分成塊,分別存儲到幾臺機器上。結合上文中提到的那個存儲500G大文件的那個例子,這500G的文件會按照一定的大小被切分成若干塊,然后分別存儲在若干臺機器上,然后提供統一的操作接口。
看到這里,不少人可能會覺得,分布式文件系統不過如此,很簡單嘛。事實真的是這樣的么?
潛在問題
假如我有一個1000臺機器組成的分布式系統,一臺機器每天出現故障的概率是0.1%,那么整個系統每天出現故障的概率是多大呢?答案是(1-0.1%)^1000=63%,因此需要提供一個容錯機制來保證發生差錯時文件依然可以讀出,這里暫時先不展開介紹。
如果要存儲PB級或者EB級的數據,成千上萬臺機器組成的集群是很常見的,所以說分布式系統比單機系統要復雜得多呀。
這是一張HDFS的架構簡圖:
client通過nameNode了解數據在哪些DataNode上,從而發起查詢。此外,不僅是查詢文件,寫入文件的時候也是先去請教NameNode,看看應該往哪個DateNode中去寫。
為了某一份數據只寫入到一個Datanode中,而這個Datanode因為某些原因出錯無法讀取的問題,需要通過冗余備份的方式來進行容錯處理。因此,HDFS在寫入一個數據塊的時候,不會僅僅寫入一個DataNode,而是會寫入到多個DataNode中,這樣,如果其中一個DataNode壞了,還可以從其余的DataNode中拿到數據,保證了數據不丟失。
實際上,每個數據塊在HDFS上都會保存多份,保存在不同的DataNode上。這種是犧牲一定存儲空間換取可靠性的做法。
接下來我們來看一下完整的文件寫入的流程:
大文件要寫入HDFS,client端根據配置將大文件分成固定大小的塊,然后再上傳到HDFS。
讀取文件的流程:
1、client詢問NameNode,我要讀取某個路徑下的文件,麻煩告訴我這個文件都在哪些DataNode上?
2、NameNode回復client,這個路徑下的文件被切成了3塊,分別在DataNode1、DataNode3和DataNode4上
3、client去找DataNode1、DataNode3和DataNode4,拿到3個文件塊,通過stream讀取并且整合起來
文件寫入的流程:
1、client先將文件分塊,然后詢問NameNode,我要寫入一個文件到某個路徑下,文件有3塊,應該怎么寫?
2、NameNode回復client,可以分別寫到DataNode1、DataNode2、DataNode3、DataNode4上,記住,每個塊重復寫3份,總共是9份
3、client找到DataNode1、DataNode2、DataNode3、DataNode4,把數據寫到他們上面
出于容錯的考慮,每個數據塊有3個備份,但是3個備份快都直接由client端直接寫入勢必會帶來client端過重的寫入壓力,這個點是否有更好的解決方案呢?回憶一下mysql主備之間是通過binlog文件進行同步的,HDFS當然也可以借鑒這個思想,數據其實只需要寫入到一個datanode上,然后由datanode之間相互進行備份同步,減少了client端的寫入壓力,那么至于是一個datanode寫入成功即成功,還是需要所有的參與備份的datanode返回寫入成功才算成功,是可靠性配置的策略,當然這個設置會影響到數據寫入的吞吐率,我們可以看到可靠性和效率永遠是“魚和熊掌不可兼得”的。
潛在問題
NameNode確實會回放editlog,但是不是每次都從頭回放,它會先加載一個fsimage,這個文件是之前某一個時刻整個NameNode的文件元數據的內存快照,然后再在這個基礎上回放editlog,完成后,會清空editlog,再把當前文件元數據的內存狀態寫入fsimage,方便下一次加載。
這樣,全量回放就變成了增量回放,但是如果NameNode長時間未重啟過,editlog依然會比較大,恢復的時間依然比較長,這個問題怎么解呢?
SecondNameNode是一個NameNode內的定時任務線程,它會定期地將editlog寫入fsimage,然后情況原來的editlog,從而保證editlog的文件大小維持在一定大小。
NameNode掛了, SecondNameNode并不能替代NameNode,所以如果集群中只有一個NameNode,它掛了,整個系統就掛了。hadoop2.x之前,整個集群只能有一個NameNode,是有可能發生單點故障的,所以hadoop1.x有本身的不穩定性。但是hadoop2.x之后,我們可以在集群中配置多個NameNode,就不會有這個問題了,但是配置多個NameNode,需要注意的地方就更多了,系統就更加復雜了。
俗話說“一山不容二虎”,兩個NameNode只能有一個是活躍狀態active,另一個是備份狀態standby,我們看一下兩個NameNode的架構圖。
兩個NameNode通過JournalNode實現同步editlog,保持狀態一致可以相互替換。
因為active的NameNode掛了之后,standby的NameNode要馬上接替它,所以它們的數據要時刻保持一致,在寫入數據的時候,兩個NameNode內存中都要記錄數據的元信息,并保持一致。這個JournalNode就是用來在兩個NameNode中同步數據的,并且standby NameNode實現了SecondNameNode的功能。
進行數據同步操作的過程如下:
active NameNode有操作之后,它的editlog會被記錄到JournalNode中,standby NameNode會從JournalNode中讀取到變化并進行同步,同時standby NameNode會監聽記錄的變化。這樣做的話就是實時同步了,并且standby NameNode就實現了SecondNameNode的功能。
優點:
缺點:
這次的NoSQL專欄系列將先整體介紹NoSQL,然后介紹如何把NoSQL運用到自己的項目中合適的場景中,還會適當地分析一些成功案例,希望有成功使用NoSQL經驗的朋友給我提供一些線索和信息。
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在這個層面上來說就要性能高很多了。
靈活的數據模型
NoSQL無需事先為要存儲的數據建立字段,隨時可以存儲自定義的數據格式。而在關系數據庫里,增刪字段是一件非常麻煩的事情。如果是非常大數據量的表,增加字段簡直就是一個噩夢。這點在大數據量的web2.0時代尤其明顯。
高可用NoSQL在不太影響性能的情況,就可以方便的實現高可用的架構。比如Cassandra,HBase模型,通過復制模型也能實現高可用。
總結NoSQL數據庫的出現,彌補了關系數據(比如MySQL)在某些方面的不足,在某些方面能極大的節省開發成本和維護成本。
MySQL和NoSQL都有各自的特點和使用的應用場景,兩者的緊密結合將會給web2.0的數據庫發展帶來新的思路。
當為大家描述我們的整體服務架構時,最常見的兩個問題是:
為什么采用結構化方式將數據存儲在SQL數據庫中,而不使用NoSQL平臺?
為什么自己維護數據中心,而不將Evernote托管到云服務提供商?
這兩個問題都很有趣,我們先來探討第一個。
對特定的應用而言,相比一個單一的SQL實例,一個現代的鍵值存儲引擎具備顯著的性能優勢和可擴展性。
CREATE TABLE notebooks ( id int UNSIGNED NOT NULL PRIMARY KEY, guid binary(16) NOT NULL, user_id int UNSIGNED NOT NULL, name varchar(100) COLLATE utf8_bin NOT NULL, ... ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE notes ( id int UNSIGNED NOT NULL PRIMARY KEY, guid binary(16) NOT NULL, user_id int UNSIGNED NOT NULL, notebook_id int UNSIGNED NOT NULL, title varchar(255) NOT NULL, ... FOREIGN KEY (notebook_id) REFERENCES notebooks(id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
如果你在Windows客戶端上創建了一個名為“Cooking”的記事本,并立即在其中粘貼了一個名為“Quick Tomato Sauce”的食譜,客戶端會立刻進行如下同步:
調用NoteStore.createNotebook() 請求服務器創建記事本,并返回以創建記事本的GUID。
通過指定記事本的GUID,調用NoteStore.createNote()在記事本中創建筆記。
每次API調用都通過SQL事物予以實現,可以讓客戶端完全信任服務器的任何提示。ACID兼容的數據庫可以做到這些:
原子性(Atomicity):如果API調用成功,那么所有的改動都會保存;如果API調用失敗,所有的改動都不會提交。
一致性(Consistency): 在API調用完成后,所有的賬戶都可用,并能保證內部狀態的一致性。每篇筆記都與記事本相關聯,以避免出現孤立項。數據庫不允許刪除關聯有記事的記事本,這得感謝FOREIGN KEY約束。
持久性(Durability):當服務器發送記事本已創建完畢的回執后,客戶端會認為它的存在具有持久性,以便進行后續的操作。變更的持久性,可以讓客戶端知道在任何時刻對服務狀態的影響都能保持一致性。
對我們的同步協議而言,持久性最為重要。如果客戶端不能確定服務器端的變更具有持久性,那么協議將會變得復雜而低效。
“大數據”問題
得益于事務處理的數據庫的ACID屬性,同樣使得數據集非常難以擴展,以超出單臺服務器的范圍。數據庫集群和多主復制技術并不理想,鍵值存儲為實現可擴展性提供了一條捷徑。
所幸,Evernote暫時不需要考慮這個問題。即便是我們有近10億的筆記,和近20億的資源文件,這也并不能稱得上是一個大數據集。通過按用戶分區,它被劃分成了2千萬個獨立的數據集。
我們尚未遇到所謂“大數據”引發的問題,倒是遇到了許多“中數據”的存儲問題,這就是通過規整分區形成的分片存儲架構。
也許以后……
我們對新的存儲系統非常感興趣,非常樂意應用在哪些對ACID要求不強,但確實需要橫向擴展的新項目中。例如,我們的報告分析系統已經逐漸超出了MySQL平臺的承受力,需要被更快、更先進的系統所取代。
我們現在對以Evernote用戶元數據為基礎的MySQL分片存儲頗為滿意,盡管這不會引起那些IT弄潮兒的興趣。
通過學習《億級流量網站架構核心技術》及《linux就該這么學》學習筆記及自己的感悟:架構設計之高可用高并發系統設計原則,架構設計包括墨菲定律、康威定律和二八定律三大定律,而系統設計包括高并發原則、高可用和業務設計原則等。
架構設計三大定律
墨菲定律 – 任何事沒有表面看起來那么簡單 – 所有的事都會比預計的時間長 – 可能出錯的事情總會出錯 – 擔心某種事情發生,那么它就更有可能發生
康威定律 – 系統架構師公司組織架構的反映 – 按照業務閉環進行系統拆分/組織架構劃分,實現閉環、高內聚、低耦合,減少溝通成本 – 如果溝通出現問題,應該考慮進行系統和組織架構的調整 – 適合時機進行系統拆分,不要一開始就吧系統、服務拆分拆的非常細,雖然閉環,但是每個人維護的系統多,維護成本高 – 微服務架構的理論基礎 – 康威定律– 每個架構師都應該研究下康威定律
二八定律 – 80%的結果取決于20%的原因
系統設計遵循的原則
1.高并發原則
無狀態
無狀態應用,便于水平擴展
有狀態配置可通過配置中心實現無狀態
實踐: Disconf、Yaconf、Zookpeer、Consul、Confd、Diamond、Xdiamond等
拆分
系統維度:按照系統功能、業務拆分,如購物車,結算,訂單等
功能維度:對系統功能在做細粒度拆分
讀寫維度:根據讀寫比例特征拆分;讀多,可考慮多級緩存;寫多,可考慮分庫分表
AOP維度: 根據訪問特征,按照AOP進行拆分,比如商品詳情頁可分為CDN、頁面渲染系統,CDN就是一個AOP系統
模塊維度:對整體代碼結構劃分Web、Service、DAO
服務化
服務化演進: 進程內服務-單機遠程服務-集群手動注冊服務-自動注冊和發現服務-服務的分組、隔離、路由-服務治理
考慮服務分組、隔離、限流、黑白名單、超時、重試機制、路由、故障補償等
實踐:利用Nginx、HaProxy、LVS等實現負載均衡,ZooKeeper、Consul等實現自動注冊和發現服
消息隊列
目的: 服務解耦(一對多消費)、異步處理、流量削峰緩沖等
大流量緩沖: 犧牲強一致性,保證最終一致性(案例:庫存扣減,現在Redis中做扣減,記錄扣減日志,通過后臺進程將扣減日志應用到DB)
數據校對: 解決異步消息機制下消息丟失問題
數據異構
數據異構: 通過消息隊列機制接收數據變更,原子化存儲
數據閉環: 屏蔽多從數據來源,將數據異構存儲,形成閉環
緩存銀彈
用戶層:
DNS緩存
瀏覽器DNS緩存
操作系統DNS緩存
本地DNS服務商緩存
DNS服務器緩存
客戶端緩存
瀏覽器緩存(Expires、Cache-Control、Last-Modified、Etag)
App客戶緩存(js/css/image…)
代理層:
CDN緩存(一般基于ATS、Varnish、Nginx、Squid等構建,邊緣節點-二級節點-中心節點-源站)
接入層:
Opcache: 緩存PHP的Opcodes
Proxy_cache: 代理緩存,可以存儲到/dev/shm或者SSD
FastCGI Cache
Nginx+Lua+Redis: 業務數據緩存
Nginx為例:
PHP為例:
應用層:
頁面靜態化
業務數據緩存(Redis/Memcached/本地文件等)
消息隊列
數據層:
NoSQL: Redis、Memcache、SSDB等
MySQL: Innodb/MyISAM等Query Cache、Key Cache、Innodb Buffer Size等
系統層:
CPU : L1/L2/L3 Cache/NUMA
內存
磁盤:磁盤本身緩存、dirtyratio/dirtybackground_ratio、陣列卡本身緩存
并發化
2.高可用原則
降級
降級開關集中化管理:將開關配置信息推送到各個應用
可降級的多級讀服務:如服務調用降級為只讀本地緩存
開關前置化:如Nginx+lua(OpenResty)配置降級策略,引流流量;可基于此做灰度策略
業務降級:高并發下,保證核心功能,次要功能可由同步改為異步策略或屏蔽功能
限流
目的: 防止惡意請求攻擊或超出系統峰值
實踐:
惡意請求流量只訪問到Cache
穿透后端應用的流量使用Nginx的limit處理
惡意IP使用Nginx Deny策略或者iptables拒絕
切流量
目的:屏蔽故障機器
實踐:
DNS: 更改域名解析入口,如DNSPOD可以添加備用IP,正常IP故障時,會自主切換到備用地址;生效實踐較慢
HttpDNS: 為了繞過運營商LocalDNS實現的精準流量調度
LVS/HaProxy/Nginx: 摘除故障節點
可回滾
發布版本失敗時可隨時快速回退到上一個穩定版本
3.業務設計原則
防重設計
冪等設計
流程定義
狀態與狀態機
后臺系統操作可反饋
后臺系統審批化
文檔注釋
備份
4.總結
先行規劃和設計時有必要的,要對現有問題有方案,對未來有預案;欠下的技術債,遲早都是要還的。
本文作者為網易高級運維工程師
項目上需要找一個硬盤型的NoSQL,用于將 Redis 中的冷數據落入硬盤。初步選型了幾款 key-value 類型的NoSQL,分別有 levelDB、 rocksDB、 TiDB、 SSDB、swapDB、 Kvrocks、Tikv 。均為基于 levelDB 開發的幾款NoSQL。其中因為 levelDB、rocksDB 無網絡接口,不方便做分布式和高可用。, TiDB 過重,還有 swapDB 社區不夠活躍且相關client API不完備。暫時選型 SSDB 。
項目需要存儲的其實是一個略長的二進制字符串,初步認為,使用 對象存儲 方案其實也可以替代NoSQL,所以壓測對象添加當前非常火的云原生對象存儲 MinIO
硬件名|配置 系統| Ubuntu(基于win10 wsl版的docker啟動) 內存| 16GB(實際可用6.08G) CPU| Intel i5-8400
測試項目: 1. 寫50M數據100次 2. 隨機讀取任意key 100次(對LRU機制不友好)
寫
數據導入成功!
數據序列化成功!
a 數據大小:50.99295234680176 MB
第1次寫入總用時: 797 ms
第2次寫入總用時: 848 ms
第3次寫入總用時: 3621 ms
第4次寫入總用時: 813 ms
第5次寫入總用時: 1862 ms
第6次寫入總用時: 838 ms
第7次寫入總用時: 2235 ms
第8次寫入總用時: 836 ms
第9次寫入總用時: 900 ms
第10次寫入總用時: 1027 ms
第11次寫入總用時: 1101 ms
第12次寫入總用時: 880 ms
第13次寫入總用時: 1956 ms
第14次寫入總用時: 866 ms
第15次寫入總用時: 2422 ms
第16次寫入總用時: 852 ms
第17次寫入總用時: 4511 ms
第18次寫入總用時: 875 ms
第19次寫入總用時: 2736 ms
第20次寫入總用時: 814 ms
第21次寫入總用時: 7172 ms
第22次寫入總用時: 891 ms
第23次寫入總用時: 7820 ms
第24次寫入總用時: 836 ms
第25次寫入總用時: 22103 ms
第26次寫入總用時: 877 ms
第27次寫入總用時: 2712 ms
第28次寫入總用時: 841 ms
第29次寫入總用時: 1928 ms
第30次寫入總用時: 916 ms
第31次寫入總用時: 839 ms
第32次寫入總用時: 826 ms
第33次寫入總用時: 7759 ms
第34次寫入總用時: 843 ms
第35次寫入總用時: 10670 ms
第36次寫入總用時: 843 ms
第37次寫入總用時: 9361 ms
第38次寫入總用時: 821 ms
第39次寫入總用時: 810 ms
第40次寫入總用時: 794 ms
第41次寫入總用時: 13281 ms
第42次寫入總用時: 833 ms
第43次寫入總用時: 811 ms
第44次寫入總用時: 798 ms
第45次寫入總用時: 18843 ms
第46次寫入總用時: 911 ms
第47次寫入總用時: 9428 ms
第48次寫入總用時: 898 ms
第49次寫入總用時: 17582 ms
第50次寫入總用時: 903 ms
第51次寫入總用時: 831 ms
第52次寫入總用時: 800 ms
第53次寫入總用時: 14602 ms
第54次寫入總用時: 827 ms
第55次寫入總用時: 5898 ms
第56次寫入總用時: 856 ms
第57次寫入總用時: 5693 ms
第58次寫入總用時: 1050 ms
第59次寫入總用時: 882 ms
第60次寫入總用時: 1020 ms
第61次寫入總用時: 15060 ms
第62次寫入總用時: 902 ms
第63次寫入總用時: 1062 ms
第64次寫入總用時: 915 ms
第65次寫入總用時: 7572 ms
第66次寫入總用時: 823 ms
第67次寫入總用時: 9649 ms
第68次寫入總用時: 832 ms
第69次寫入總用時: 10403 ms
第70次寫入總用時: 907 ms
第71次寫入總用時: 978 ms
第72次寫入總用時: 789 ms
第73次寫入總用時: 2111 ms
第74次寫入總用時: 947 ms
第75次寫入總用時: 4675 ms
第76次寫入總用時: 944 ms
第77次寫入總用時: 8592 ms
第78次寫入總用時: 832 ms
第79次寫入總用時: 2940 ms
第80次寫入總用時: 842 ms
第81次寫入總用時: 19835 ms
第82次寫入總用時: 862 ms
第83次寫入總用時: 7646 ms
第84次寫入總用時: 873 ms
第85次寫入總用時: 1002 ms
第86次寫入總用時: 842 ms
第87次寫入總用時: 9057 ms
第88次寫入總用時: 801 ms
第89次寫入總用時: 5117 ms
第90次寫入總用時: 918 ms
第91次寫入總用時: 798 ms
第92次寫入總用時: 853 ms
第93次寫入總用時: 7728 ms
第94次寫入總用時: 810 ms
第95次寫入總用時: 3969 ms
第96次寫入總用時: 814 ms
第97次寫入總用時: 2050 ms
第98次寫入總用時: 819 ms
第99次寫入總用時: 9566 ms
第100次寫入總用時: 833 ms/pre
隨機讀
第1次讀取 15總用時: 2251 ms
第2次讀取 73總用時: 2045 ms
第3次讀取 98總用時: 1548 ms
第4次讀取 20總用時: 2683 ms
第5次讀取 46總用時: 1156 ms
第6次讀取 69總用時: 1160 ms
第7次讀取 46總用時: 1520 ms
第8次讀取 51總用時: 1381 ms
第9次讀取 48總用時: 1000 ms
第10次讀取 69總用時: 1400 ms
第11次讀取 82總用時: 1236 ms
第12次讀取 22總用時: 1140 ms
第13次讀取 36總用時: 864 ms
第14次讀取 66總用時: 843 ms
第15次讀取 47總用時: 922 ms
第16次讀取 17總用時: 885 ms
第17次讀取 14總用時: 864 ms
第18次讀取 64總用時: 888 ms
第19次讀取 74總用時: 815 ms
第20次讀取 33總用時: 866 ms
第21次讀取 36總用時: 822 ms
第22次讀取 78總用時: 975 ms
第23次讀取 40總用時: 1186 ms
第24次讀取 54總用時: 857 ms
第25次讀取 92總用時: 963 ms
第26次讀取 43總用時: 955 ms
第27次讀取 38總用時: 853 ms
第28次讀取 47總用時: 926 ms
第29次讀取 62總用時: 877 ms
第30次讀取 70總用時: 890 ms
第31次讀取 88總用時: 895 ms
第32次讀取 15總用時: 937 ms
第33次讀取 3總用時: 993 ms
第34次讀取 99總用時: 892 ms
第35次讀取 76總用時: 818 ms
第36次讀取 30總用時: 1020 ms
第37次讀取 89總用時: 863 ms
第38次讀取 99總用時: 819 ms
第39次讀取 62總用時: 818 ms
第40次讀取 1總用時: 871 ms
第41次讀取 66總用時: 809 ms
第42次讀取 68總用時: 847 ms
第43次讀取 72總用時: 910 ms
第44次讀取 50總用時: 1128 ms
第45次讀取 47總用時: 898 ms
第46次讀取 26總用時: 909 ms
第47次讀取 35總用時: 872 ms
第48次讀取 30總用時: 826 ms
第49次讀取 79總用時: 904 ms
第50次讀取 66總用時: 863 ms
第51次讀取 2總用時: 885 ms
第52次讀取 65總用時: 900 ms
第53次讀取 67總用時: 1023 ms
第54次讀取 16總用時: 934 ms
第55次讀取 63總用時: 892 ms
第56次讀取 9總用時: 894 ms
第57次讀取 71總用時: 896 ms
第58次讀取 20總用時: 947 ms
第59次讀取 89總用時: 865 ms
第60次讀取 57總用時: 872 ms
第61次讀取 62總用時: 856 ms
第62次讀取 14總用時: 881 ms
第63次讀取 19總用時: 950 ms
第64次讀取 14總用時: 876 ms
第65次讀取 86總用時: 968 ms
第66次讀取 12總用時: 911 ms
第67次讀取 93總用時: 877 ms
第68次讀取 59總用時: 886 ms
第69次讀取 79總用時: 878 ms
第70次讀取 49總用時: 869 ms
第71次讀取 91總用時: 964 ms
第72次讀取 38總用時: 838 ms
第73次讀取 73總用時: 915 ms
第74次讀取 8總用時: 875 ms
第75次讀取 96總用時: 827 ms
第76次讀取 98總用時: 826 ms
第77次讀取 95總用時: 892 ms
第78次讀取 36總用時: 843 ms
第79次讀取 44總用時: 872 ms
第80次讀取 89總用時: 863 ms
第81次讀取 24總用時: 883 ms
第82次讀取 89總用時: 804 ms
第83次讀取 49總用時: 876 ms
第84次讀取 81總用時: 873 ms
第85次讀取 72總用時: 914 ms
第86次讀取 68總用時: 861 ms
第87次讀取 73總用時: 893 ms
第88次讀取 4總用時: 880 ms
第89次讀取 3總用時: 987 ms
第90次讀取 76總用時: 896 ms
第91次讀取 16總用時: 1010 ms
第92次讀取 73總用時: 903 ms
第93次讀取 83總用時: 933 ms
第94次讀取 52總用時: 945 ms
第95次讀取 48總用時: 901 ms
第96次讀取 26總用時: 942 ms
第97次讀取 37總用時: 883 ms
第98次讀取 44總用時: 866 ms
第99次讀取 89總用時: 921 ms
第100次讀取 61總用時: 896 ms/pre
寫
數據導入成功!
第1次寫入總用時: 956 ms
第2次寫入總用時: 912 ms
第3次寫入總用時: 1241 ms
第4次寫入總用時: 1564 ms
第5次寫入總用時: 942 ms
第6次寫入總用時: 3666 ms
第7次寫入總用時: 1629 ms
第8次寫入總用時: 1712 ms
第9次寫入總用時: 977 ms
第10次寫入總用時: 1515 ms
第11次寫入總用時: 911 ms
第12次寫入總用時: 1009 ms
第13次寫入總用時: 1024 ms
第14次寫入總用時: 1206 ms
第15次寫入總用時: 984 ms
第16次寫入總用時: 943 ms
第17次寫入總用時: 954 ms
第18次寫入總用時: 1033 ms
第19次寫入總用時: 1008 ms
第20次寫入總用時: 1121 ms
第21次寫入總用時: 963 ms
第22次寫入總用時: 949 ms
第23次寫入總用時: 889 ms
第24次寫入總用時: 1066 ms
第25次寫入總用時: 1289 ms
第26次寫入總用時: 1125 ms
第27次寫入總用時: 1111 ms
第28次寫入總用時: 953 ms
第29次寫入總用時: 964 ms
第30次寫入總用時: 1125 ms
第31次寫入總用時: 998 ms
第32次寫入總用時: 1993 ms
第33次寫入總用時: 926 ms
第34次寫入總用時: 920 ms
第35次寫入總用時: 926 ms
第36次寫入總用時: 1169 ms
第37次寫入總用時: 1325 ms
第38次寫入總用時: 1170 ms
第39次寫入總用時: 1074 ms
第40次寫入總用時: 1011 ms
第41次寫入總用時: 931 ms
第42次寫入總用時: 984 ms
第43次寫入總用時: 1563 ms
第44次寫入總用時: 905 ms
第45次寫入總用時: 944 ms
第46次寫入總用時: 1147 ms
第47次寫入總用時: 1429 ms
第48次寫入總用時: 934 ms
第49次寫入總用時: 1133 ms
第50次寫入總用時: 912 ms
第51次寫入總用時: 953 ms
第52次寫入總用時: 1127 ms
第53次寫入總用時: 1065 ms
第54次寫入總用時: 1323 ms
第55次寫入總用時: 1003 ms
第56次寫入總用時: 1489 ms
第57次寫入總用時: 1377 ms
第58次寫入總用時: 940 ms
第59次寫入總用時: 1317 ms
第60次寫入總用時: 912 ms
第61次寫入總用時: 898 ms
第62次寫入總用時: 934 ms
第63次寫入總用時: 1005 ms
第64次寫入總用時: 1729 ms
第65次寫入總用時: 983 ms
第66次寫入總用時: 1684 ms
第67次寫入總用時: 908 ms
第68次寫入總用時: 895 ms
第69次寫入總用時: 1171 ms
第70次寫入總用時: 1372 ms
第71次寫入總用時: 1261 ms
第72次寫入總用時: 1024 ms
第73次寫入總用時: 1048 ms
第74次寫入總用時: 904 ms
第75次寫入總用時: 941 ms
第76次寫入總用時: 928 ms
第77次寫入總用時: 1806 ms
第78次寫入總用時: 1052 ms
第79次寫入總用時: 1030 ms
第80次寫入總用時: 1092 ms
第81次寫入總用時: 1117 ms
第82次寫入總用時: 950 ms
第83次寫入總用時: 933 ms
第84次寫入總用時: 928 ms
第85次寫入總用時: 935 ms
第86次寫入總用時: 1908 ms
第87次寫入總用時: 994 ms
第88次寫入總用時: 1097 ms
第89次寫入總用時: 930 ms
第90次寫入總用時: 1052 ms
第91次寫入總用時: 1119 ms
第92次寫入總用時: 958 ms
第93次寫入總用時: 987 ms
第94次寫入總用時: 973 ms
第95次寫入總用時: 2036 ms
第96次寫入總用時: 891 ms
第97次寫入總用時: 954 ms
第98次寫入總用時: 951 ms
第99次寫入總用時: 1044 ms
第100次寫入總用時: 1366 ms/pre
隨機讀
第1次讀取 46總用時: 40 ms
第2次讀取 8總用時: 36 ms
第3次讀取 28總用時: 26 ms
第4次讀取 80總用時: 10 ms
第5次讀取 77總用時: 13 ms
第6次讀取 27總用時: 49 ms
第7次讀取 86總用時: 20 ms
第8次讀取 0總用時: 45 ms
第9次讀取 54總用時: 34 ms
第10次讀取 24總用時: 153 ms
第11次讀取 78總用時: 29 ms
第12次讀取 0總用時: 17 ms
第13次讀取 91總用時: 56 ms
第14次讀取 5總用時: 99 ms
第15次讀取 23總用時: 138 ms
第16次讀取 37總用時: 120 ms
第17次讀取 40總用時: 156 ms
第18次讀取 88總用時: 41 ms
第19次讀取 76總用時: 32 ms
第20次讀取 49總用時: 102 ms
第21次讀取 20總用時: 179 ms
第22次讀取 40總用時: 68 ms
第23次讀取 6總用時: 215 ms
第24次讀取 36總用時: 197 ms
第25次讀取 37總用時: 30 ms
第26次讀取 68總用時: 154 ms
第27次讀取 14總用時: 314 ms
第28次讀取 27總用時: 91 ms
第29次讀取 51總用時: 255 ms
第30次讀取 66總用時: 166 ms
第31次讀取 86總用時: 140 ms
第32次讀取 29總用時: 374 ms
第33次讀取 96總用時: 235 ms
第34次讀取 68總用時: 72 ms
第35次讀取 74總用時: 264 ms
第36次讀取 11總用時: 334 ms
第37次讀取 55總用時: 316 ms
第38次讀取 31總用時: 287 ms
第39次讀取 93總用時: 233 ms
第40次讀取 44總用時: 499 ms
第41次讀取 26總用時: 312 ms
第42次讀取 76總用時: 33 ms
第43次讀取 11總用時: 31 ms
第44次讀取 86總用時: 191 ms
第45次讀取 96總用時: 217 ms
第46次讀取 20總用時: 145 ms
第47次讀取 1總用時: 772 ms
第48次讀取 69總用時: 477 ms
第49次讀取 9總用時: 320 ms
第50次讀取 46總用時: 42 ms
第51次讀取 34總用時: 823 ms
第52次讀取 76總用時: 115 ms
第53次讀取 62總用時: 635 ms
第54次讀取 99總用時: 596 ms
第55次讀取 64總用時: 657 ms
第56次讀取 66總用時: 97 ms
第57次讀取 18總用時: 461 ms
第58次讀取 91總用時: 247 ms
第59次讀取 46總用時: 147 ms
第60次讀取 12總用時: 702 ms
第61次讀取 79總用時: 545 ms
第62次讀取 47總用時: 956 ms
第63次讀取 17總用時: 853 ms
第64次讀取 97總用時: 771 ms
第65次讀取 74總用時: 368 ms
第66次讀取 84總用時: 790 ms
第67次讀取 72總用時: 866 ms
第68次讀取 82總用時: 742 ms
第69次讀取 93總用時: 313 ms
第70次讀取 57總用時: 917 ms
第71次讀取 61總用時: 1185 ms
第72次讀取 66總用時: 162 ms
第73次讀取 5總用時: 168 ms
第74次讀取 68總用時: 275 ms
第75次讀取 43總用時: 1108 ms
第76次讀取 74總用時: 281 ms
第77次讀取 65總用時: 955 ms
第78次讀取 22總用時: 1169 ms
第79次讀取 88總用時: 501 ms
第80次讀取 80總用時: 1685 ms
第81次讀取 92總用時: 1286 ms
第82次讀取 89總用時: 1680 ms
第83次讀取 30總用時: 1537 ms
第84次讀取 41總用時: 1576 ms
第85次讀取 2總用時: 2193 ms
第86次讀取 52總用時: 1817 ms
第87次讀取 8總用時: 323 ms
第88次讀取 81總用時: 1409 ms
第89次讀取 40總用時: 577 ms
第90次讀取 88總用時: 598 ms
第91次讀取 19總用時: 2324 ms
第92次讀取 75總用時: 2275 ms
第93次讀取 29總用時: 668 ms
第94次讀取 77總用時: 2773 ms
第95次讀取 62總用時: 484 ms
第96次讀取 84總用時: 883 ms
第97次讀取 32總用時: 2945 ms
第98次讀取 44總用時: 884 ms
第99次讀取 66總用時: 631 ms
第100次讀取 38總用時: 2739 ms/pre
非常奇怪的是 MinIO 整體性能略優于 SSDB 但是理論上不太應該, SSDB 怎么說也是半內存半硬盤的NoSQL不應該比純硬盤的 MinIO 性能要差,有可能是 SSDB 寫到一定數據量后把本機內存寫爆了,導致讀寫非常慢。但這變相驗證了 SSDB 在極端情況下的不穩定。
文章標題:nosqlssdb主備,mysql數據庫主備
瀏覽地址:http://www.hntjjpw.com/article34/hdhgse.html
成都網站建設公司_創新互聯,為您提供網站改版、軟件開發、動態網站、網站導航、網站設計公司、網站制作
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯