本文牽扯的面積可能會比較泛,或者說比較大,在這個層面很多人也有自己的見解,所以我這也僅僅是拋磚引玉,結合前面講述的一些基礎技術,從思想中闡述更為深入的架構思想基礎,因為最好的架構思想是架構師結合實際情況思考出來最適合的架構,這裡僅僅說明下一些常用的原理和思想,主要包含的內容有(內容很泛,所以都是簡單闡述入門知識,具體後續深入探討):

1、app切分集羣組擴展

2、app集羣組負載均衡

3、Memcached原理

4、db cache應用

5、db存儲類型以及存儲cache說明

6、存儲條帶思想

7、資料庫集羣

8、資料庫分散式存儲

9、資料庫容災備份以及監控

10、nosql思想

11、無鎖分析

1、app切分集羣組擴展

應用系統架構隨著外部並發量的增加,必然導致的是app應用的壓力逐漸增加,並且絕大部分app對於線程的分配能力都是有限的,但是app應用在擴展上是非常容易的,最基礎的就是一種應用的垂直切割,其次是水平切割。

在瞭解app切割原理的基礎上先來瞭解一個其他的概念就是,就是Internate的路由器如何路由你請求的一個URL,你發送的URL並不知道路由器發送到哪裡去了,最終路由到遠端的伺服器(互聯網本身就是一個雲計算為基礎的平臺),到了遠程後,它如何找到自己的應用呢,以及應用下具體的服務內容呢?就是通過URL後面部分的標識符號。也就是在雲的最終技術也是各自管理各自的內容,而雲之所謂稱之為雲是因為你無須關心你發送的URL是如何路由到遠端的伺服器的,又是如何通過哪些路由器返回回來的。這裡不深入討論雲的概念,回到主題上是說遠端的伺服器每一個目標都有自己處理的對象,或者說不同的路徑下或者不同的埠下都會有自己的處理服務。所以app系統切割的基本思想就是路徑。

當一個系統業務十分複雜,應用並發量很大的情況下,必然導致的一個步驟就是業務分解,將一個大的系統拆分為多個小系統,不論是軟體本身設計的可擴展性還是軟體性能擴展性都會有很大的幫助,比如在各個子系統之間他們的業務的複雜性以及並發量都會有很大的區別,我們可以將這些小系統拆分到不同的集羣節點上去,這些集羣節點可以是由同一個主機發布出來的不同埠或者URL,或者是不同的主機發布出來的內容,並且三者可以根據實際情況調整使得成本、軟體擴展性、性能擴展性達到較好的程度,總之將一個大系統拆分為多個小系統是第一個需要做的,也就是app應用拆分,這種並不難,但是拆分的依據一定要把控好,而且還有一個總體架構,不然軟體最終會做的五花八門;在很多的應用下都會使用,只是在這種拆分,拆分後除上述的總體設計要做好外,還需要主意的一點就是系統通信問題,子系統拆分後應該是高內聚的,但是免不了需呀通信,否則就根本不算是一個系統的,而且即使不是同一個系統也有可能因為服務需求而需要去通信,所以在通信上需要多下功夫,在不同伺服器以及語言之間通信最麻煩的事情就是字符集,也是需要主意的,不過不是本文的重點。

在上面拆分完成後,當某一個子系統的並發量非常大的時候,我就需要單獨對某一個子系統進行拆分了,這種沒的選,一般不太可能通過URL來控制(除非申請不同的VIP或者在同一個主機上用不同的虛擬目錄來做,不過是不是有點挫),這種一般是通過在不同的服務埠(也稱為運行節點,在同一個主機上多個節點肯定是不同的埠的),或者發布到不同的主機上來完成;這部分拆分app應用不會受到太大的限制;這個地方需要主意的是,當你在app內部做靜態內存時,就無法做到當一個機器的內存修改後同時修改到其他內存中,除非你自己寫程序要麼定時刷新要麼相互之間傳送數據,但是這兩種都會付出巨大的成本,如何解決呢,我們後面會說到的Memcached就是解決的方法。

上述兩者完成後,新的問題出現了,就是子系統之間的通信,他們不再是單機對單機的通信,而是集羣組對集羣組的通信,所以子系統中間件必然有一些非一對一的通信機制就出現了,以及中途產生的同步通信和非同步通信等機制,如IBM MQ、EJB、Webservice、HttpClient、HttpInvokie、RPC、Socket甚至於藉助於資料庫或者文件作為中間層等等都是通信機制的基礎,應用非常特殊的公司會自己寫自己的通信機制。

有了上述的集羣,URL可以通過網路路由到具體的伺服器,但是伺服器下每一個集羣節點不可能都去申請一個URL吧,而且客戶也不會自己知道我第一次用URL1,下一次用URL2、再下一次用URL3來給你伺服器做負載均衡吧,客戶只知道用一個URL訪問你,而且那麼多的IP在互聯網上也會佔用非常大的資源,所以很多時候,一個大網站後臺可能數萬的主機,前端暴露的IP可能只有幾個,這個可以成為VIP,他們之間有一個綁定關係,由這個VIP來負責域名的幫頂,而VIP一般會綁定在一個負載均衡器上面,由負載均衡器根據實際請求內容負載到具體的主機上面去,下面第二章就是我們要寫的負載均衡基本原理。

2、app集羣組負載均衡

所謂負載均衡就是負載均衡了,呵呵,也就是不讓某太機器單獨忙,也不讓某臺機器太閑,將請求進行分發,這就是負載均衡器設計的初衷了。

隨著發展的變化,負載均衡器需要承擔更大的作用

第一個需要做的就是請求解析,也就是很多不同的應可能由一個負載均衡器來完成;

進一步,同一個應用發布的不同的節點或者不同的埠,負載均衡器可以識別出來並達到分發負載,將並發負載到很多不同的節點上去運行;

再進一步,某個客戶端請求第一次訪問了某個節點後,當session未失效時,應當做到繼續訪問同一臺主機,這樣保證客戶在多次交互中session內容是一致的,至少不會導致重新登陸等現象;

再進一步,在節點失敗是,負載均衡器應當識別出來,並可以將訪問切換到其他主機,在有必要的情況下需要做session複製。

負載均衡最基本的需要做到以上幾點內容纔算負載均衡。

負載均衡器一般需要的內容是全局的,但是它並不關注與細節,所以它主要做的事情是全局資源定位,監控,負載均衡,切換動作;一般會有一個單獨的管理節點和單獨的分發節點,但是每一門負載均衡的機制在設計層面都會有很大的區別,所以無需一概而論。

因為負載均衡器在所有應用的最前端,所以我們非常關注於它的性能,有很多基於高級語言編寫的負載均衡器,甚至於你可以直接通過你的JSP、ASP、PHP等等做一個簡單的控制跳轉上的負載均衡,但是他們的性能就很低了,擴展性受到明顯的限制,Linux內核纔是負載均衡器的王道,終極方案,要深入研究和負載均衡的方案,請大家多多參詳Linux內核。

目前市面上非常常用的負載均衡器是apache,它本身也可以作為WEB伺服器來應用(它的一些模塊就可以直接用於php),另外weblogic自帶的proxy+domain+managed模式也是一種負載均衡方法,不過我做過幾個版本效果不理想,主要原因還是主要是因為實現的基礎是高級語言吧;而apache雖然性能不錯,而且大家廣受喜愛的一種東西,不過隨著互聯網並發量的上升,apache在很多極為高並發的系統中仍然受到擴展性的限制,於是乎ngnix出現了,它是目前高並髮網站應用中最廣泛或者說在大網站中用得最多的負載均衡器,國內的大網站基本都有它的影子,它是俄羅斯一位工程師編寫,而且是免費的,性能極高,佔用資源極少,並且支持cache以及代理,很多客戶端訪問的機制都可以配置化,安裝和使用都非常簡單(要深入研究就沒那麼簡單),而且故障率非常低,為什麼那麼好,因為它的基礎就是unux內核,沒有別的,當然寫代碼一定要寫得很好纔行;當然國內並非沒有這樣的人才存在,而且要看公司是否給這類人才一個機會去完成這樣一個東西,因為自己寫的可能會更加適合於自己,其實國內也有很多對Unix內核研究很深入的頂尖高手。

3、Memcached原理

這一章本身就想在資料庫後面說明的,不過由於只是簡單介紹,而且後面應該幾乎都是技術,所以就這這裡說明瞭。

一般應用程序除了處理業務邏輯和一定的計算後,就是訪問資料庫,做資料庫的存、取、事務操作,在OLAP會有更多的是在資料庫端的計算,OLAP不是本文的重點,因為OLAP不會涉及並發量的問題,所以更多偏重於OLTP,而且是極高並發的系統。

當前端app並發達到一定程度,即將考慮的問題就是資料庫的壓力,資料庫面對的更多的數據,雖然它在各方面做了非常大的優化,不過它畢竟是存大量鎖機制和磁碟讀寫操作,來保證數據一致性和安全性,而這兩者往往是影響性能的關鍵指標,但是我們很多時候又不得不用資料庫,因為他可以提供給我們的東西實在是太多了。

在互聯網應用中有個幾乎所有網站都會擁有的一個共同特徵那就是讀取次數非常多,而寫的次數相對比例較少(並不代表沒有寫操作),此時人們在設計上第一個想法是讓資料庫來完成主備或者鏡像方式上的讀寫分離,不過始終會與資料庫交互,而且擴展上會受到非常大的限制,在極高並發下,人們又對應用做了對頁面輸出html的方式,但是最終發現在實施過程中會受到很多限制(尤其是ajax交互),雖然有很多軟體可以支持,此時很多人想到將數據載入到內存中,按照某種方式刷新內存即可,不過我們上面已經討論,在集羣下它很難做到每個被切割開的節點他們之間的靜態內存是一致的,所以Memcached出現了。

Memcached我看網上寫它是分散式的,這個大家最好不要亂理解,因為從基本的設計上講,它只是將app和靜態內存分開了,而並非真正意義上做到分散式(真正意義上的分散式應當自動將多個Memcached節點的訪問如同訪問一個節點一樣簡單),而一般Memcached的訪問方式還是通過程序去控制的,而多個不同節點劃分,也是通過人為的完成的,你可以認為你訪問的Memcached是資料庫一樣的東西,因為它的訪問方式類似於資料庫,但是它如果命中肯定比訪問資料庫要快很多,而且可以大量減少讀的壓力,因為一個大網站百分之八九十以上的壓力來源於讀;一個好的Memcached設計會使得讀命中率達到95%以上,而其成本只需要大內存,並具有極大的擴展性;根據實際系統的場景講Memcached劃分數據的方法指定,當命中是獲取,當修改時先修改資料庫,然後讓對應的cached失效即可;主意解決如果它掛掉會產生什麼問題,它的基礎原理是一種Key-Value方式,但是通用的東西往往不是性能最佳的東西,所以你在有必要的情況下可以適當做下修改,淘寶網的tair開源技術就是一套自己完成的分散式緩存技術,也是很不錯的選擇。

4、db cache應用

上述已經描述到資料庫訪問會有大量的磁碟操作,這裡我們說下oracle是如何緩解這些問題的,以至於它一直在資料庫領域處於行業界得老大哥形象出現。

它首先由一個SGA的全局區域,內部的其他區域已經在前面的文章中說明,中間對於數據層面,最重要的就是databuffer了,這個databuffer是採用基於LRU演算法為基礎的方式來完成的所以只要有足夠大的內存,在讀遠大於寫的情況下命中率也會非常高(其實oracle做寫操作也是寫內存的,即使你commit命令oracle也不會做磁碟寫,但是它會寫日誌,當達到一定並發量日誌寫也是不可估量的,而且臟塊列表也會非常頻繁的被刷新到磁碟上,也很容易出現瓶頸),data buffer這也是db cache最為核心的部分,當然還有些其他區域也有一定的cache思想。

一般來說,對於極為高並發的系統,資料庫的cached逐漸受到限制,雖然oracle rac可以非常高效的擴展,但是其限制最多是64節點的整列結構,而且在這個過程中並非沒有鎖,尤其是在集羣下的全局鎖機制,這個開銷也是很大的,但是我們很多時候訪問很多數據並非需要鎖,也就是這些數據是在這段時間內我們確定不會被修改或者說根本不會被修改甚至於說修改了一個簡單臟數據的延遲讀也是無所謂的,這類數據我們沒有必要讓他來和其他需要做絕對一致性的事情套在一起,該做事務的被阻塞了,可以間接做事務的也被阻塞了,所以在更多的層面我們希望的是app端做好cache,纔是更好的方案,通常app的性能會佔用整個系統性能指標的50%以上,而有20%在於資料庫端,另外還有設計方案、存儲等等其他的,以及SQL了。

在app設計cached後,資料庫更多的是做修改,讀顯得更加少,所以在app設計cached後,資料庫端的內存可以保留,也可以節約一些出來也可以。

5、db存儲類型以及存儲cache說明

存儲就是指最終數據存放的位置,有些地方也叫做整列(因為很多時候它是多個磁碟通過RAID完成的),存儲一般會有低端存儲、中端存儲、高端存儲。

存儲設備中最挫的就是本地硬碟了,一般都可以不認為他是獨立的存儲設備;但是最終你會發現它在是最好的,呵呵,在分散式的架構上,我們更加願意選擇廉價的成本設備,並自己架構主機來完成使得性能達到更高的程度;比如在一種順序寫非常多、隨機讀非常多的場景下,我們就更加願意選擇SSD硬碟來做存儲,因為它的總體設計就非常適合這種情況。

低端存儲一般只有一個控制器,壞掉全部壞掉,沒有任何存儲cached,存磁碟操作。

中端存儲一般有2個控制器,可以做均衡負載,而且可以冗餘保護,壞掉一個性能會降低50%,並且有一定的cache設備,有些時候也會分讀cache和寫cache,IBM DS 8000屬於一種中端存儲,不過它自稱是高端存儲設備,外部一般說他是偽高端設備。

高端存儲,多個控制器相互冗餘,壞掉一兩個性能影響較小,具體影響要看存儲成本和具體需求;EMC高端存儲就是非常流行的選擇,DMX3中還有一種讀cache鏡像和寫cache鏡像,在某些應用下性能更加提升;不過高端存儲的成本極高,在必要的環境下才會使用,絕大部分企業會使用中端存儲設備。

存儲成本並非和性能或者說高可用性完全成正比,尤其是本身高可用性很好的情況下;所以在選擇存儲的時候再考慮當前應用下需要考慮的就是成本,主要是:數據存儲容量、電費、網路帶寬;以及一個存儲在多少年後報廢等一起計算。

存儲的基本考量標準也是系統性能重點指標:IOPS、QPS、TPS、帶寬容量、單個請求響應時間。

這些目前不做深入探討,以後我們再說(因為涉及內容非常多,而且和磁碟管理方式有關係,如下面的條帶就會對其影響),只做下簡單介紹:

IOPS:磁碟陣列上每秒相應IO次數,這個IO次數不分讀寫,但是一般是OLTP系統中的小IO,一般用2K、4K這種來做測試(所以主意你在設計OLTP系統的資料庫block時為什麼要小,因為提取一條數據並不想用多次IO,而oracle提取數據的單位是block,mysql和sqlserver是頁);一般單個硬碟的IOPS會根據設計有關係,一個15k rpm 的IOPS一般是150個,但是並非絕對,可能會管理方式以及每個IO的大小有關係。

QPS和TPS是對IOPS的一個分解,其實本身沒這個概念,不過可以做這個來看出一個系統的讀寫比例以及讓系統以後如何設計來更好的工作。這兩個分別代表的是每秒的查詢次數、事務次數;可以通過一些內部SQL抓取等方法來實現。

IO帶寬:當上述內容完成後,就需要考慮帶寬了,當你的IOPS可以上去後,但是帶寬上不去就悲劇了,那剛才的15k rpm來說,一般帶寬是13M/s,這裡單位注意是位元組(B),這裡假設有120塊磁碟,那麼也就是1560M/s,此時就需要通信上做一些支持,也就是要支持1G多的流量,需要光纖帶寬8Gb(這裡是網路上的大小,也就是二進位大小),那麼最少使用4塊2Gb的光纖卡;這種考慮基本在OLAP中比較多,而在OLTP系統中IO都是小IO,帶寬按照小IO的大小乘以IOPS已經足夠。

響應速度:這個因素就多了,除了上述的IOPS以及吞吐量以外,還和存儲cache有關係,甚至於和鎖都有關係,總之響應速度算是一個最終結果,影響因數上面每一種都會有,具體需要根據實際系統來協調,一般來說一個IO如果存磁碟操作最少需要10ms甚至於更多,而如果在cache中命中可能2ms左右就響應了,也就是從單個IO來說,cache命中比正常磁碟操作要快5倍,而平均IO一般保持在10ms是比較良好的,很多時候非cache的情況下平均IO一般會達到20ms以上

6、存儲條帶思想

大家不要被這個辭彙所嚇到,它就是RAID0的另一種說法,其實RAID有很多種,從RAID0~RAID7每一種都有自己的特徵所在,而且還有組合的,企業常用的有:RAID 10、RAID5、RAID3這幾種,本文不對磁碟陣列做詳細闡述,而只是通過條帶給帶出來一些思想。

RAID0,也就是條帶,它的思想源於負載均衡,和散列存儲,最終在磁碟上的統一實現,並將其作為磁碟組為中心,給外部調用,而無需關心磁碟的內部細節。

它按照一定的數據順序,將數據分佈逐個分佈在多個磁碟上,所以看起來就像「條帶」一樣,同時不論在讀還是寫的過程中,它都將IO負載到了不同的磁碟上,使得IO的總體性能幾乎可以與磁碟數成正比,極大提高IO性能。

但是RAID0本身沒有保護,也就是當磁碟壞掉,數據就丟了,找不回來,所以後來出現各種各樣的RAID,根據不同的情況每一種RAID都會有自己的方式來處理,實現補充程度的冗餘,還是那句話,發展到一定的冗餘度將會導致成本直線上升,但是並不一定會帶來收益的直線上升;RAID10就是通過50%冗餘完成,也就是一對一冗餘完成,同一個整列下所有的數據壞掉也可以找回來,除非兩塊磁碟是相互冗餘的磁碟同時壞掉;而RAID5屬於從RAID3、RAID4做一些演算法改進和性能提升上來的,其原理都是奇、偶校驗碼原則,數據分散式按照條帶思想,冗餘N+1塊磁碟,數據隨機存放在N塊磁碟上,剩餘一塊做校驗位,相對減少磁頭同步粒度,其中任意一塊磁碟壞掉,均可恢復,但同一個RAID5陣列同時壞掉2塊不行。

順便提及下,ORACLE個只瘋狗什麼東西都想獨霸,他的ASM就是拿出來和RAID競爭的,它的管理可以基於裸機,更加優於基於操作系統層的調用,而在裸設備的管理上又會有很多新的講究。

7、資料庫集羣

資料庫集羣上,最初是通過一種操作系統機制HA完成,但是它在資料庫層面存在很多缺陷,相對管理資料庫來說還存在很多專業上的個性化,所以ORACLE在10g推出了ORACLE RAC(其實是9i,但是9i的集羣做得很爛,所以可以認為是10g纔有的);另外10g之前的集羣需要第三方的cluster軟體完成,10g後就有了oracle自己的CRS軟體,並且是免費的,可以到官方下載。

資料庫集羣除正常的app擁有的(load banlance)負載均衡、(failover)失敗切換,還有很多機制在內,包含主從關係、切換機制、以及分散式計算(網格計算(Grid)在ORACLE RAC中是一種最簡單的實現方法,真正的網格計算是指在實際的網格環境下去管理網格下多個應用的資料庫包括集羣,他們是同一的,甚至於你無須關心網格下集羣組之間的關係,就能非常清晰得去做操作了),這裡的網格計算是指在一些大的統計下,在配置資料庫參數時,將相應的INSTANCE參數設置為集羣分組,並開啟並行,在做一些大操作時就會實現多實例配合完成,也是通過心跳完成的。

資料庫集羣的負載均衡一般是通過app端完成,這部分可能是client端的TNS配置(此時前提是通過cluster完成使用同一個service_name對應多個SID),或者類似TNS配置在鏈接資料庫的URL中,它內部一個重要參數就是LOAD_BALANCE等等,它可以設置為:(yes、on、true是等價的,不區分大小寫,即開啟負載均衡),相反,設置為(no、off、false)則為取消負載均衡,此時按照配置的遠程主機IP或者域名的順序逐個訪問到一個可用的即可,此時一般會導致一臺機器忙一臺機器閑的情況,不過另一臺機器如果只是用來做備機器,當一臺掛掉後切換過去也是可以的,一般用RAC我們也會將該參數開啟。

failover就是將資料庫的SQL切換到另一個機器上,但是事務會被回滾,具體是否切換或者如何切換要看其它參數配置,首先FAILOVER參數和上面參數的參數值一樣都是那樣設置,當設置為開啟狀態就會進行失敗切換,否則這個連接池的請求就會失敗;而其它幾個參數一般是在開啟狀態下有默認值的,自己也可以設置的哦,在FAILOVER_MODE配置中很多:

首先是TYPE參數的配置中一般有:session(失敗時候,所有內容被中止,已經操作的事務被回滾,創建新的session到另一個可用實例上)、select(設置為該參數和上面差不多,不過切換時,開始被操作的事務雖然被回滾,但是如果是select語句不會被中斷,會繼續執行),none(不做任何操作,直接回滾,也不接管,用於測試,客戶端會直接報錯)

其次METHOD參數,這個參數一般是有:basic(在發生失敗時候再在另一個實例上創建session回話節點)、preconnect(預先設立回話節點,有一定開銷,但是切換速度很快速,在主從模式下推薦)而RETRIES分別代表重試次數(默認5)、DELAY代表每次重試時間片信息(默認1秒)、BACKUP(備份節點的網路服務名)

集羣RAC由於設計更加專業於資料庫應用,所以他比起HA更加適用於資料庫,也是眾多企業的選擇,它配合data guard(有些是extend rac是包含了這兩種功能)來完成備份,也有oracle的一直以來的終極備份方案rman來完成,不過前者更加偏重於容災,還有些關於複製以及遷移等功能不是本文重點,不便多提及。

ORACLE RAC和相關的東西都是燒錢的東西,價格不菲,對各項硬體要求非常高,所以注意成本預算,如高速網路以及各個INSTANCE連接共享存儲陣列的SAN交換機一般需要多個來冗餘,心跳的交換機也需要冗餘等等。

ORACLE RAC依賴於一個共享存儲,做相應INSTANCE和資料庫級別的管理,這也是資料庫和實例的區別了,那麼它的瓶頸就在後端了,所以後端很多時候會選擇高端存儲來完成;另外它還有很多全局資源管理使得它的很多發展在這些瓶頸上出現問題,如它的節點一般最多支持64節點,而隨著節點數量的增加,成本會直線上升,至於性能是否能直線上升呢,你應該可以考慮下當前的各種瓶頸在哪裡,也需要和實際情況結合纔好說。

8、資料庫容災備份以及監控

接下來一個系統設計應該如何?需要做的就是容災以及監控運行狀況是否良好,對於app端一般不需要容災,只需要監控,而其一般是通過監控內存、CPU、磁碟使用量(主要是日誌和本地緩存文件);如果監控系統做得不好,那麼我想很多DBA晚上睡不著(至於夜間做生產變更這類可以通過其他的自動化程序完成),系統的發展也會受到限制,我們需要一個伸縮性很強的系統就必然會走這一步。

而資料庫容災現在又很多方案,上面已經說了,現在比較多的就是使用dataguard備份到一個或多個備份機器上,dataguard上有多種配置機制,來實現各種常用的要求,關於磁碟管理可以使用ASM來管理,資料庫也可以負責制過去,也可以非同步通過程序度過去,也可以通過觸發器+dblink過去等等都可以實現。關鍵看實際需求。

資料庫的監控,這個oracle也提供了系列的監控軟體(Statspace、AWR、logmgr等等系列),不過很多時候我們需要更加精確的參數需要自己去編碼,否則就還是需要自己去查詢很多自己做報表什麼的,而且很不直觀;長期需要監控的除了常用的IOPS、TPS、QPS以外,還需要關心很多如latch徵用、sql parser(硬解析和軟解析的各方面指標)、cache命中率、鎖等待、內存指標變化、CPU指標變化、索引、磁碟碎片等等都需要得到全方位的監控

資料庫的管理應當自動化,首先從監控下手,完全自動化管理和資源調配方面是一個理想,不過半自動化也是很容易的,就是在有問題或者在一定情況下有某種方式的通知,如簡訊息吧。這樣DBA就不用成天盯著監控或者後臺的某個字典表一直看了。

9、CDN思想基礎

後面幾個章節不是本文重點,簡單闡述下即可,在高可用性網站設計中,即使前端應用增加了Memcached這類東西,不過始終不能很好的效果,要達到極佳的效果,因為很多時候跨網段的開銷是非常大的,經過的路由器越多開銷越大;其次很多時候,不願意因為大文件輸出(如視頻下載)導致應用伺服器宕機的事情,這是沒有必要的,因為應用伺服器更多關心的應該是業務處理。

CDN的出現就是為瞭解決這個問題,也就是網站加速器,他需要運營商的配合(具體細節請自己查閱資料),在很多地方建立站點,它需要做的事情就是託管DNS,通常DNS是解析域名成IP並訪問對應IP內容,而CDN做了一層重寫,就是通過域名解析得到的是一個CNAME,它按照提供CNAME會按照最短路徑找到對應的CDN網點,接受數據,客戶端的數據接受更加快速,並且可以實現冗餘保護,另外它只是緩存在這裡,可以認為是本地的一個私服,也就是需要跨網段的流量都切換到本地了,這裡做一個極端的假設,就是跨網段的開銷是2,本網段拖數據是1,有100個請求時,跨網段需要200的開銷,而本地網段就只需要101個開銷。

大文件下載,是通過緩存到本地的私服上,如視頻下載就很多時候這段時間大家看的都是熱播電影,就可以通過CDN來進行網站加速。

10、nosql思想

根據上面的描述,我們很多時候就不想做到百分百的數據安全,或者一致性吧,比如做一個網站的留言板,數據有一點偏差也無所謂,而且資料庫的sql parser一般是很慢的,很容易達到極限,所以nosql的誕生就出現了,現在很多開源的nosql平臺,它也是現有雲存儲的基礎,apache的hadoop以及谷歌的mapreduce後來做了一個Percolator,還有redis、mongodb等等,其實所謂nosql基礎的原理就是沒有sql,就想剛才說的Memcache一樣,只是它有存儲以及根據設計不同,會有一些會存在一些鎖機制,並且只是面向對象;有基於行存儲的、有基於列存儲的他們是根據實際應用場景設計的一種類似於資料庫的東西,它具有極高的擴展性和伸縮性,因為控制完全在於你本身的架構和設計,也是我們一直所崇尚的:最好的東西肯定是最優秀的人根據實際的場景所架構出來的。

不論是哪一門,nosql它首先拋開的是sql parser的一種,但是它沒有了SQL的支持,在一些複雜操作上顯得比較困難(這些就要看具體場景和nosql的設計了);我們在結合上述幾種技術的基礎上如何不將Cached、nosql、RDBMS、app幾個結合起來,向後端移動,實現app調用完全無需關心很多調用的細節,那麼這就是真正的雲存儲了,因為是在分散式存儲基礎上以及cache管理的基礎上實現了對應用的透明調用。

如何設計待以後專門有文章來闡述,今天只是一個開頭而已。

11、無鎖分析

通過上面的文章內容,我們在很多時候很多不必要的信息沒有必要使用RDBMS一樣的鎖和同步等等動作,所以所謂真正意義上的無鎖或者幾乎無鎖,就是將很多內容抽象出來利用間接的方法來實現。

一般來說降低鎖的粒度有以下幾種方法:

a.使用hash、range、點陣圖對數據進行提前分佈,讓其分框,根據實際情況而定,如果一個框只有一個線程在處理那麼就幾乎可以算是無鎖了。

b.在一些特殊必要的應用中,使用特殊的方法來控制,變通的方法來控制,如隊列中的對頭和隊尾演算法,如果只有一個生產者和一個消費者可以讓他們在一個定長數組下跑圈圈即可,後者永遠追不上前者,而多生產者多消費者模式又該如何呢?比如多個線程做push操作,那麼你只需要在多個線程以當前隊頭下標開始位置分配到不同的下標,幾個線程就可以無鎖操作了,那麼如何分配到不同的下標呢?用java的volatile,你可以認為它是鎖的,不過它非常輕量級的鎖,只是在對使用volatile變數修改和讀取過程中強制從從新內存中獲取,而不是寄存器,所以在計數器使用中,多個線程去同時修改這個變數並獲取到的值都是不同的;pop也是如此,這些有一定的應用場景,棧也可以用變通的手段得到解決。

c.還有一些通過版本號碼、向量複製、臟塊列表等等思想來實現,都有一些應用場景和方法;以及java提供的樂觀鎖機制(適用於非常多線程調用同一段代碼,而不是循環非常多次去調用同一段代碼)。

還有很多其他的知識可以借鑒,曾經看到過非常複雜的圖形演算法,而且是多維度的,太複雜了,所以這裡就不說明瞭。

根據上述N多知識可以看出很多知識都是相通的,無非就是分解、根據實際情況命中與解鎖,讓更快的地方替換最慢的地方,讓複雜的管理變得更加簡單。

另一種無鎖是一種變通的手段,就是單線程寫操作了,也就是完全無鎖的一種機制,其實你會覺得它很慢,經過測試發現,如果你的操作全是或者基本是OLTP中的小IO單個線程的寫已經可以達到非常快速度,這種非常適合於寫不多,但讀非常多的系統,也就是讀寫分離,寫全部在內存中完成,但是需要寫日誌,讀是從多個散列主機上獲取,但是也會從這個內存中獲取相應數據,內存中為最新修改後得數據列,他們之間會在對應欄位上以內存為主進行返回,這個機器只要內存足夠大(現在稍微好點的PC SERVER幾十G的內存非常容易),就可以承受非常大的修改,這個數據只需要在業務量較小的時候合併到靜態數據中即可;那麼當業務進行擴大,單線程無法承受的時候應該如何呢?內存也寫不下了,那麼此時又需要對其進行切割分離了,在業務和邏輯表上做一定的標識符號,類似於上述說到的volatile一樣的東西,而寫操作也可以類似於讀操作一樣的分層,這就越來越像Memcache+app+RDBMS這種結構了,只是它在Memcached有日誌記錄和恢復,並對於應用來說透明化了這種分散式的調用,它將整個體系向後端移動和抽象出來使得app的編程更加簡單和方便,也就是app無需關心數據的具體位置在哪裡,以及寫到哪裡去了,緩存在哪裡,他們如何同步的,這就逐步可以認為是雲存儲和計算了,另外其精巧的設計不得不說是非常優秀的。


推薦閱讀:
查看原文 >>
相關文章