海量資料高併發的解決方案
高併發的解決方案
1.應用和靜態資源分離
剛開始的時候應用和靜態資源是儲存在一起的,當併發量達到一定程度的時候就需要將靜態資源儲存到專門的伺服器中,靜態資源主要包括圖片、視訊、js、css和一些資原始檔等,這些檔案因為沒有狀態所以分離比較簡單,直接存放到響應的伺服器就可以了,一般會使用專門的域名去訪問。 通過不同的域名可以讓瀏覽器直接訪問資源伺服器而不需要再訪問應用伺服器了。架構圖如下:
2.頁面快取
頁面快取是將應用生成的頁面快取起來,這樣就不需要每次都生成頁面了,從而可以節省大量的CPU資源,如果將快取的頁面放到記憶體中速度就更快了。如果使用Nginx伺服器就可以使用它自帶的快取功能,當然也可以使用專門的Squid 伺服器。頁面快取的預設失效機制一班都是按快取時間處理的,當然也可以在修改資料之後手動讓相應的快取失效。 頁面快取主要是使用在資料很少發生變化的頁面,但是很多頁面是大部分資料都很少發生變化,而其中很少一部分資料變化頻率卻非常高,比如說一個顯示文章的頁面,正常來說完全可以靜態化,但是如果文章後面有“頂”和“踩”的功能而且顯示的有響應的數量,這個資料的變化頻率就比較高了,這就會影響靜態化。這個問題可以用先生成靜態頁面然後使用Ajax來讀取並修改響應的資料,這樣就可以一舉兩得來,既可以使用頁面快取也可以實時顯示一些變化頻率高的資料來。
其實大家都知道,效率最高、消耗最小的就是純靜態化的html頁面,所以我們儘可能使我們的網站上的頁面採用靜態頁面來實現,這個最簡單的方法其實也是最有效的方法。但是對於大量內容並且頻繁更新的網站,我們無法全部手動去挨個實現,於是出現了我們常見的資訊釋出系統CMS,像我們常訪問的各個門戶站點的新聞頻道,甚至他們的其他頻道,都是通過資訊釋出系統來管理和實現的,資訊釋出系統可以實現最簡單的資訊錄入自動生成靜態頁面,還能具備頻道管理、許可權管理、自動抓取等功能,對於一個大型網站來說,擁有一套高效、可管理的CMS是必不可少的。
除了門戶和資訊釋出型別的網站,對於互動性要求很高的社群型別網站來說,儘可能的靜態化也是提高效能的必要手段,將社群內的帖子、文章進行實時的靜態化,有更新的時候再重新靜態化也是大量使用的策略,像Mop的大雜燴就是使用了這樣的策略,網易社群等也是如此。
同時,html靜態化也是某些快取策略使用的手段,對於系統中頻繁使用資料庫查詢但是內容更新很小的應用,可以考慮使用html靜態化來實現,比如論壇中論壇的公用設定資訊,這些資訊目前的主流論壇都可以進行後臺管理並且儲存再資料庫中,這些資訊其實大量被前臺程式呼叫,但是更新頻率很小,可以考慮將這部分內容進行後臺更新的時候進行靜態化,這樣避免了大量的資料庫訪問請求。
3.叢集與分散式
叢集是每臺伺服器都具有相同的功能,處理請求時呼叫那臺伺服器都可以,主要起分流作用。
分散式是將不同的業務放到不同的伺服器中,處理一個請求可能需要用到多臺伺服器,這樣就可以提高一個請求的處理速度,而且叢集和分散式也可以同時使用。
叢集有兩個方式:一種是在靜態資源叢集。另一種是應用程式叢集。靜態資源叢集比較簡單。應用程式叢集在處理過程中最核心的問題就是Session 同步問題。
Session 同步有兩種處理方式:一種是在Session 發生變化後自動同步到其他伺服器,另一種就是用個程式統一管理Session。所有叢集的伺服器都使用同一個Session,Tomcat 預設使用就是第一種方式,通過簡單的配置就可以實現,第二種方式可以使用專門的伺服器安裝Mencached等高效的快取程式統一來管理session,然後再應用程式中通過重寫Request並覆蓋getSession 方法來獲取制定伺服器中的Session。
對於叢集來說還有一個核心的問題就是負載均衡,也就是接收到一個請求後具體分配到那個伺服器去處理的問題,這個問題可以通過軟體處理也可以使用專門的硬體(如:F5)解決。
4. 反向代理
反向代理指的是客戶端直接訪問的伺服器並不真正提供服務,它從別的伺服器獲取資源然後將結果返回給使用者。
圖:
4.1 反向代理伺服器和代理伺服器的區別
代理伺服器的作用是代我門獲取想要的資源然後將結果返回給我們,所要獲取的資源是我門主動告訴代理伺服器的,比如,我門想訪問Facebook,但是直接訪問不了,這時就可以讓代理伺服器訪問,然後將結果返回給我們。
反向代理伺服器是我門正常訪問一臺伺服器的時候,伺服器自己去呼叫了別的伺服器資源並將結果返回給我們,我門自己並不知道。
代理伺服器是我們主動使用的,是為我們服務的,他不需要有自己的域名;反向代理伺服器是伺服器自己試用的,我門並不知道,它有自己的域名,我門訪問它和訪問正常的網址沒有任何區別。
反向代理伺服器主要有三個作用: 1. 可以作為前端伺服器跟實際處理請求的伺服器整合; 2. 可以做負載均衡 3. 轉發請求,比如說可以將不同型別的資源請求轉發到不同的伺服器去處理。
5. CDN
cdn其實是一種特殊的叢集頁面快取伺服器,他和普通叢集的多臺頁面快取伺服器相比,主要是它存放的位置和分配請求的方式有點特殊。CDN 伺服器是分佈在全國各地的,當接收到使用者請求後會將請求分配到最合適的CDN伺服器節點獲取資料。比如聯通的使用者分配到聯通的節點,上海的使用者分配到上海的節點。
CDN的每個節點其實就是一個頁面快取伺服器,如果沒有請求資源的快取就會從主伺服器獲取,否則直接返回快取的頁面。
CDN分配請求(負載均衡)的方式是用專門的CDN域名解析伺服器在解析域名的時候就分配好的。一般的做法是在ISP哪裡試用CNAME將域名解析到一個特定的域名,然後再將解析到的那個域名用專門的CDN伺服器解析道相應的CDN節點。如圖。
第二步訪問CDN的DNS伺服器是應為CNAME記錄的目標域名使用NS記錄指向了CDN的DNS伺服器。CDN的每個節點可能也是叢集了多臺伺服器。
6. 底層的優化
前面說的所有都是架構都是建立在最前面介紹的基礎結構之上的。很多地方都需要通過網路傳輸資料,如果可以加快網路傳輸的速度,那將會讓整個系統得到改善。
7.資料庫叢集和庫表雜湊
大型網站都有複雜的應用,這些應用必須使用資料庫,那麼在面對大量訪問的時候,資料庫的瓶頸很快就能顯現出來,這時一臺資料庫將很快無法滿足應用,於是我們需要使用資料庫叢集或者庫表雜湊。
在資料庫叢集方面,很多資料庫都有自己的解決方案,Oracle、Sybase等都有很好的方案,常用的MySQL提供的Master/Slave也是類似的方案,您使用了什麼樣的DB,就參考相應的解決方案來實施即可。
上面提到的資料庫叢集由於在架構、成本、擴張性方面都會受到所採用DB型別的限制,於是我們需要從應用程式的角度來考慮改善系統架構,庫表雜湊是常用並且最有效的解決方案。我們在應用程式中安裝業務和應用或者功能模組將資料庫進行分離,不同的模組對應不同的資料庫或者表,再按照一定的策略對某個頁面或者功能進行更小的資料庫雜湊,比如使用者表,按照使用者ID進行表雜湊,這樣就能夠低成本的提升系統的效能並且有很好的擴充套件性。sohu的論壇就是採用了這樣的架構,將論壇的使用者、設定、帖子等資訊進行資料庫分離,然後對帖子、使用者按照板塊和ID進行雜湊資料庫和表,最終可以在配置檔案中進行簡單的配置便能讓系統隨時增加一臺低成本的資料庫進來補充系統性能。
8. 小結
網站架構的整個演變過程主要是圍繞大資料和高併發這兩個問題展開的,解決方案主要分為使用快取和多資源兩種型別。多資源主要指多儲存(包括多記憶體)、多CPU和多網路,對於多資源來說又可以分為單個資源處理一個完整的請求和多個資源合作處理一個請求兩種型別,如多儲存和多CPU中的叢集和分散式,多網路中的CDN和靜態資源分離。理解了整個思路之後就抓住了架構演變的本質,而且自己可能還可以設計出更好的架構。
其它簡單總結:
首先,我認為解決問題之前首先要有清晰的思路,如果只是用來別人的解決方案那也只能是拿來主義,沒有真正理解,沒有做到舉一反三。
海量資料和高併發經常被連在一塊說事兒,雖然他們完全是兩回事兒。海量資料純指的是資料庫的海量資料,而併發指的卻包括資料庫和伺服器的高訪問量。
那麼問題來了,既然是資料庫的資料量大,那怎麼辦呢?要想解決問題,首先要知道問題是什麼!!!那麼海量資料會給我帶來什麼樣的問題呢?
海量資料帶來的問題無非就是增刪改查的問題,除了之外還能有啥問題呢?總不能是帶來安全問題吧(打臉一,還真有可能是安全問題)
1 資料庫訪問緩慢
2 插入更新緩慢,這個問題只能通過分庫分表解決
要解決資料庫訪問緩慢的問題還有幾種方法,既然訪問資料庫慢的話,在邏輯允許的情況下可以不訪問資料庫呢?
1 使用快取
2 使用頁面靜態化
既然不訪問資料庫逃不過去了,那我們就對資料庫進行優化
3 優化資料庫(包含的內容非常多,比如引數配置,索引優化,sql優化等等)
4 分離資料庫中活躍的資料
5 讀寫分離
6 批量讀取和延遲修改;
7 使用搜索引擎搜尋資料庫中的資料;
8 使用NoSQL和Hadoop等技術;
9 進行業務的拆分;
高併發的解決方案
其實這個問題必須結合上面的海量資料來討論,什麼情況下會出現高併發呢?一定是平時訪問量就比較大的情況,那麼平時訪問量比較大相應的資料儲存也就越來越多,這都是相輔相成的,當然也有個例,比如剛需,比如12306,這裡的高併發相比於它的資料來說已經不算海量了。那麼平時訪問量大如何解決呢?因為這裡牽扯到伺服器和資料庫的問題,所以要從這兩方面來進行優化
1 增加web伺服器數量,也就是做叢集,做負載均衡。既然一臺伺服器無法完成任務,那就多用幾臺,幾臺不夠用機房
在通向第二種解決方法之前,還有沒有除了資料庫伺服器之外能做的一些優化手段呢?當然有
1.1 頁面快取
1.2 cdn
1.3 反向代理
1.4 應用程式和靜態資源分離(比如專供下載的資源單獨放在一起,給這臺伺服器提供很高的頻寬資源)
2 增加資料庫伺服器數量,同樣做叢集,做負載均衡。
海量資料的解決方案
1 使用快取
好多事情都是相輔相成的,相比來說使用快取更多是用來解決高併發問題的,因為海量資料導致了訪問的緩慢,容易造成高併發問題的嚴重性,又因為資料庫一般是web訪問的瓶頸,所以我們在業務邏輯允許的情況下儘量先避免操作資料庫,於是,就有了快取。將必要的資料存放在記憶體中,而不必每次都去資料庫中讀取造成不必要的效能浪費和加快訪問速度---這就是快取帶來的好處。那使用快取以及選用管理快取軟體時應該注意些什麼東西呢?
2 頁面靜態化---不想解釋,還有什麼值得去解釋呢?
3 資料庫優化
3.1 資料庫表結構涉及
3.2 資料型別的選用
3.3 sql優化
3.4 索引優化
3.5 配置優化
需要注意的地方實在太多,應該作為單獨的一章拿出來講
4 分離資料庫中的活躍資料
為什麼要分離呢?說一個我實際環境中遇到的問題吧!有一個表只有10幾個欄位,表有130萬條資料,但大小已經到了5G的資料,這本身是不太合理的,這麼少的資料佔用了太多的資料,說明其中有些欄位儲存了大量的字串(比如說文章內容等),每次檢索這個表時大部分是用不到這些大欄位內容的,但卻需要耗時比較長,產生很多的慢日誌。這時我們可以考慮將表進行垂直切分,將活躍資料分離開來,這樣能大大加快訪問速度
5 讀寫分離