從各個角度總結了電商平台中的架構實踐,由於時間倉促,定了個初稿,待補充完善,歡迎大家一起交流。
轉載請宣告出處:
作者:楊步濤
專注於分散式架構、大數據、搜尋、開源技術
QQ:306591368
技術Blog:
##
客戶端頁面快取(http header中包含Expires/Cache of Control,last modified(304,server不回傳body,客戶端可以繼續用cache,減少流量),ETag)
##反向代理程式快取應用程式端的快取
(memcache)
記憶體資料庫Buffer、
cache機制(資料庫,中間件等)
2)B樹、倒排、bitmap
哈希索引適合綜合數組的尋址和鍊錶的插入特性,可以實現資料的快速存取。B樹索引適合查詢為主導的場景,避免多次的
IO,提高查詢的效率。
倒排索引實現單字到文檔映射關係的最佳實作方式和最有效的索引結構,廣泛用在搜尋領域。Bitmap是一種非常簡潔快速的資料結構,他能同時讓儲存空間和速度最優化(而不必空間換時間),適合於大量資料的的運算場景。
2.
#1 )
MR模型是無共享的架構,資料集分佈至各個節點。處理時,每個節點就近讀取本地儲存的資料處理
(map),將處理後的資料合併(combine)、排序(shuffle and sort)後再分發 (至reduce節點),避免了大量資料的傳輸,提高了處理效率。
2)
Parallel Computing)是指同時使用多種運算資源解決運算問題的過程,是提高電腦系統計算速度和處理能力的一種有效手段。它的基本思想是用多個處理器/進程/線程來協同求解同一問題,即將被求解的問題分解成若干個部分,各部分均由一個獨立的處理機來並行計算。 # 和MR的區別在於,它是基於問題分解的,而不是基於資料分解。 隨著平台並發量的增大,需要擴容節點進行集群,利用負載平衡設備進行請求的分發;負載平衡設備通常在提供負載平衡的同時,也提供失效檢測功能;同時為了提高可用性,需要有容災備份,以防止節點宕機失效帶來的不可用問題;備份有在線的和離線備份,可以根據失效性要求的不同,進行選擇不同的備份策略。 讀寫分離是對資料庫來講的,隨著系統並發量的增大,提高資料存取可用性的一個重要手段就是寫資料和讀取資料進行分離;當然在讀寫分離的同時,需要關注資料的一致性問題;對於一致性的問題,在分散式的系統CAP定量中,更多的關注於可用性。 平台中各模組之間的關係盡量是低耦合的,可以透過相關的訊息元件進行交互,能異步則異步,分清楚資料流轉的主流程和副流程,主副是異步的,例如記錄日誌可以是異步操作的,增加整個系統的可用性。 當然在非同步處理中,為了確保資料被接收或處理,往往需要確認機制(confirm、ack)。 但是有些場景中,雖然請求已經處理,但是因其他原因(例如網路不穩定),確認訊息沒有回傳,那麼這種情況下需要進行請求的重發,對請求的處理設計因重發因素需要考慮冪等性。 監控也是改善整個平台可用性的重要手段,多平台進行多個維度的監控;模組在運行時候是透明的,以達到運行期白盒化。 #拆分包含對業務的拆分和對資料庫的拆分。 系統的資源總是有限的,一段比較長的業務執行如果是一竿子執行的方式,在大量並發的操作下,這種阻塞的方式,無法有效的及時釋放資源給其他行程執行,這樣系統的吞吐量不高。 需要把業務進行邏輯的分段,採用非同步非阻塞的方式,提高系統的吞吐量。 隨著資料量和同時量的增加,讀寫分離無法滿足系統並發效能的要求,需要對資料進行切分,包括對資料進行分庫和分錶。這種分庫分錶的方式,需要增加資料的路由邏輯支援。 對於系統的伸縮性而言,模組最好是無狀態的,透過增加節點就可以提高整個的吞吐量。
#系統的容量是有限的,承受的並發量也是有限的,在架構設計時,一定需要考慮流量的控制,防止因意外攻擊或瞬時並發量的衝擊導致系統崩潰。在設計時增加流控的措施,可考慮對請求進行排隊,超出預期的範圍,可以進行告警或丟棄。 2) 原子操作與並發控制#對於共享資源的訪問,為了防止衝突,需要進行並發的控制,同時有些交易需要有事務性來確保交易的一致性,所以在交易系統的設計時,需考慮原子操作和並發控制。 保證並發控制一些常用高效能手段有,樂觀鎖、Latch、mutex、寫時複製、 MVCC通常是保證一致性的重要手段,這個在資料庫的設計中常會用到。 #平台中業務邏輯存在不同的類型,有計算複雜型的,有消耗IO型的,同時就同一種類型而言,不同的業務邏輯消耗的資源數量也是不一樣的,這就需要針對不同的邏輯採取不同的策略。 針對
同一類型的呼叫方式,不同的業務進行適當的資源分配,設定不同的計算節點數量或線程數量,對業務進行分流,優先執行優先順序高的業務。 4) 容錯隔離 系統的某些業務模組在出現錯誤時,為了減少並發對正常請求的處理的影響,有時需要考慮對這些異常狀態的請求進行單獨管道的處理,甚至暫時自動禁止這些異常的業務模組。 有些請求的失敗可能是偶然的暫時的失敗 ),需要進行請求重試的考慮。 5) 資源釋放 系統的資源是有限的,使用資源時,一定要在最後釋放資源,無論是請求走的是正常路徑還是異常的路徑,以便於資源的及時回收,供其他請求使用。 CDN系統能夠即時地根據網路流量和各節點的連接、負載狀況以及到用戶的距離和回應時間等綜合資訊將使用者的請求重新導向離用戶最近的服務節點。其目的是使用戶可就近取得所需內容,解決 Internet網路擁擠的狀況,提升用戶造訪網站的回應速度。 對於大規模電子商務平台一般需要建CDN做網路加速,大型平台如淘寶、京東都採用自建CDN,中小型的企業可以採用第三方CDN廠商合作,如藍汛、網宿、快網等。 當然在選擇CDN廠商時,需要考慮營運時間長短,是否有可擴充的頻寬資源、靈活的流量和頻寬選擇、穩定的節點、性價比。 一個大型的平台包含很多個業務域,不同的業務域有不同的集群,可以用 DNS做網域名稱解析的分發或輪詢,DNS方式實作簡單,但因存在cache而缺乏彈性;一般基於商用的硬體F5、NetScaler或是開源的軟負載lvs在4層做分發,當然會採用做冗餘(例如lvs+keepalived)的考慮,採取主備方式。 4#」層分發到業務叢集後,會經過web伺服器如nginx或HAProxy在7層做負載平衡或反向代理分發到叢集中的應用節點。 #選擇哪一種負載,需要綜合考慮各種因素(是否滿足高並發高效能,Session保持如何解決,負載平衡的演算法如何,支援壓縮,快取的記憶體消耗);以下基於幾種常用的負載平衡軟體做個介紹。 LVS,工作在4層,Linux實現的高效能高並發、可擴展性、可靠的的負載平衡器,支援多種轉送方式(NAT、DR、IP Tunneling),其中DR模式支援透過廣域網路進行負載平衡。支援雙機熱備(Keepalived或Heartbeat)。對網路環境的依賴性比較高。 Nginx工作在7層,事件驅動的、非同步非阻塞的架構、支援多進程的高並發的負載平衡器/反向代理軟體。可以針對網域名稱、目錄結構、正規規則針對http做一些分流。透過連接埠偵測到伺服器內部的故障,例如根據伺服器處理網頁傳回的狀態碼、逾時等等,並且會把回傳錯誤的請求重新提交到另一個節點,不過其中缺點就是不支援url來檢測。對於session sticky,可以基於ip hash的演算法來實現,透過基於cookie的擴充nginx-sticky-module支援session sticky#。 HAProxy支援4層和7層做負載平衡,支援session的會話保持,cookie的引導;支持後端url方式的偵測;負載平衡的演算法比較豐富,有RR、權重等。
,可以圖片伺服器之上加varnish做圖片快取。 3. App #應用程式層運行在jboss或 tomcat容器中,代表獨立的系統,例如前端購物、用戶自主服務、後端系統等 協定接口,HTTP、JSON 可以採用servlet3.0,非同步化servlet,提高整個系統的吞吐量 http請求經過Nginx,透過負載平衡演算法分到App的某一節點,這一層擴容比較簡單。 除了利用cookie儲存少量使用者部分資訊外(cookie一般不能超過 4K的大小),對於App接入層,保存有用戶相關的session數據,但是有些反向代理或負載平衡不支援對session sticky支援不是很好或對存取的可用性要求比較高(app存取節點宕機,session隨之遺失) ,這就需要考慮session的集中式存儲,使得App接入層無狀態化,同時系統用戶變多的時候,就可以透過增加更多的應用節點來達到水平擴展的目的。 ########### #########################Session###的集中式存儲,需要滿足以下幾點要求:####### a、高效的通訊協定 b、session的分散式緩存,支援節點的伸縮,資料的冗餘備份以及資料的遷移 c、session過期的管理 代表某一領域的業務提供的服務,對於電商而言,領域有用戶、商品、訂單、紅包、支付業務等等,不同的領域提供不同的服務, 這些不同的領域構成一個個模組,良好的模組劃分和介面設計非常重要,一般是參考高內聚、介面收斂的原則, 這樣可以提高整個系統的可用性。當然可以根據應用程式規模的大小,模組可以部署在一起,對於大規模的應用,一般是獨立部署的。 高並發: 業務層對外協定以NIO的RPC方式暴露,可以採用較成熟的NIO通訊框架,如netty、mina 可用性: 為了提高模組服務的可用性,一個模組部署在多個節點做冗餘,並自動進行負載轉發和失效轉移; 最初可以利用VIP+heartbeat方式,目前系統有一個單獨的元件HA,利用zookeeper實作(比原方案的優點) #一致性、交易: 對於分散式系統的一致性,盡量滿足可用性,一致性可以透過校對來達到最終一致的狀態。 通訊元件用於業務系統內部服務之間的調用,在大並發的電商平台中,需要滿足高並發高吞吐量的要求。 整個通訊元件包含客戶端和服務端兩部分。 客戶端和伺服器端維護的是長連接,可以減少每次請求建立連接的開銷,在客戶端對於每個伺服器定義一個連接池,初始化連接後,可以並發連接服務端進行rpc操作,連線池中的長連線需要心跳維護,設定請求逾時時間。 對於長連線的維護過程可以分成兩個階段,一個是發送請求過程,另一個是接收回應過程。在發送請求過程中,若發生IOException,則把該連線標記失效。接收回應時,服務端傳回SocketTimeoutException,如果設定了逾時時間,那麼就直接回傳異常,清除目前連線中那些逾時的請求。否則繼續發送心跳包(因為可能是丟包,超過pingInterval間隔時間就發送ping操作),若 ping不通(發送IOException),則表示目前連線是有問題的,那麼就把目前連線標記成已經失效;若ping通,則說明目前連線是可靠的,繼續進行讀取操作。失效的連線會從連線池中清除掉。 每個連線對於接收回應來說都以單獨的執行緒運行,客戶端可以透過同步(wait,notify)方式或非同步進行rpc調用, 序列化採用更有效率的hession 服務端採用事件驅動的NIO的MINA框架,支撐高並發高吞吐量的請求。 在在大多數的資料庫切分解決方案中,為了提高資料庫的吞吐量,首先是對不同的表進行垂直切分到不同的資料庫中, 然後當資料庫中一個表超過一定大小時,需要對該表進行水平切分,這裡也是一樣,這裡以用戶表為例; 對於訪問資料庫客戶端來講,需要根據用戶的ID,定位到需要訪問的資料; 資料切分演算法, 根據使用者的ID做hash操作,一致性Hash,這種方式有失效資料的遷移問題,遷移時間內服務不可用 維護路由表,路由表中儲存使用者和sharding的對應關係,sharding分為leader和replica,分別負責寫和讀取 #這樣每個biz客戶端都需要保持所有###sharding的連接池,這樣有個缺點是會產生全連接的問題; sharding的切分提到業務服務層進行,每個業務節點只維護一個shard的連線即可。 router) MongoDB中維護使用者id和shard的關係,為了確保可用性,建立replicatset叢集。 的sharding和資料庫的sharding是一一對應的,只存取一個資料庫sharding. 是業務註冊節點到zookeeper上/bizs/shard/下。 監聽zookeeper上/bizs/下節點狀態,快取線上biz在router。 client請求router取得biz時,router首先從mongodb中取得使用者對應的shard ,router根據快取的內容透過RR演算法取得biz節點。 為了解決router的可用性和並發吞吐量問題,對router進行冗餘,同時client監聽zookeeper的 /routers節點並快取線上router節點清單。 3) HA傳統實作HA的做法一般是採用虛擬IP漂移,結合Heartbeat、keepalived等實作HA, Keepalived#使用vrrp方式進行封包的轉發,提供4層的負載平衡,透過偵測vrrp封包來切換,做冗餘熱備更適合與 LVS搭配。 linux Heartbeat是基於網路或主機的服務的高可用,HAProxy或Nginx可以基於7層進行封包的轉發,因此Heatbeat更適合做HAProxy、Nginx,包括業務的高可用。 在分散式的叢集中,可以用zookeeper做分散式的協調,實作叢集的清單維護與失效通知,客戶端可以選擇hash演算法或roudrobin實作負載平衡;對於master-master模式、master-slave模式,可以透過zookeeper分散式鎖定的機制來支援。 #4) 訊息Message 對於平台各個系統之間的非同步交互,是透過 元件進行的。 在設計訊息服務元件時,需要考慮訊息一致性、持久化、可用性、以及完善的監控系統。 業界開源的訊息中介軟體主要RabbitMQ、 RabbitMQ,遵循AMQP協議,由內在高並發的erlanng語言開發;kafka是Linkedin於2010 年12月份開源的訊息發布訂閱系統,它主要用於處理活躍的串流資料,大資料量的資料處理上。 對訊息一致性要求比較高的場合需要有應答確認機制,包括生產訊息和消費訊息的過程;不過因網路等原理導致的應答缺失,可能會導致訊息的重複,這個可以在業務層次根據冪等性進行判斷濾波;RabbitMQ所採用的就是這種方式。還有一種機制是消費端從broker拉取訊息時帶上LSN號,從broker中某個LSN點批量拉取訊息,這樣無須應答機制,kafka分散式訊息中間件就是這種方式。 #訊息的在broker 對於可用性和高吞吐量的要求,叢集和主備模式都可以在實際的場景應用的。 RabbitMQ解決方案中有普通的叢集和可用性更高的mirror queue方式。 kafka採用zookeeper對叢集中的broker、consumer管理,可以註冊topic到zookeeper上;透過zookeeper的協調機制,producer儲存對應topic的broker訊息,可以隨機或輪詢傳送到broker上;並且producer可以基於語意指定分片,訊息傳送到broker的某一分片上。 #整體來講,RabbitMQ用在即時的對可靠性要求比較高的消息傳遞上。 kafka主要用於處理活躍的串流資料 大資料量的資料處理上。 5) Cache&Buffer Cache系統#在一些高並發高效能的場景中,使用cache可以減少對後端系統的負載,承擔可大部分讀取的壓力,可以大大提高系統的吞吐量,例如通常在資料庫儲存之前增加 但是引入cache架構不可避免的帶來一些問題,cache命中率的問題, cache失效所造成的抖動,cache和儲存的一致性。 Cache中的資料相對於儲存來講,畢竟是有限的,比較理想的情況是儲存系統的熱點數據,這裡可以用一些常見的演算法LRU等等淘汰老的數據;隨著系統規模的增加,單一節點cache不能滿足要求,就需要搭建分散式Cache;為了解決單一節點失效所造成的抖動 ,分散式cache一般採用一致性hash的解決方案,大幅減少因單一節點失效所造成的抖動範圍;而對於可用性要求比較高的場景,每個節點都是需要有備份的。資料在cache和儲存上都存有同一份備份,必然有一致性的問題,一致性比較強的,在更新資料庫的同時,更新資料庫cache。對於一致性要求不高的,可以去設定快取失效時間的策略。 Memcached作為高速的分散式快取伺服器,協定比較簡單,基於libevent的事件處理機制。 Cache系統在平台中用在router系統的客戶端中,熱點的資料會快取在客戶端,當資料訪問失效時,才去存取router系統。 當然目前更多的利用記憶體型的資料庫做cache,像是Redis、mongodb;redis比memcache有豐富的資料操作的API;redis和mongodb都對資料進行了持久化,而memcache沒有這個功能,因此memcache更適合在關係型資料庫之上的資料的快取。 系統 用在高速的寫入操作的場景中,平台中有些資料需要寫入資料庫,且資料是分庫分錶的,但對資料的可靠性不是那麼高,為了減少對資料庫的寫入壓力,可以採取批次寫入操作的方式。 開闢一個記憶體區域,當資料到達區域的一定閥值時如80%時,在記憶體中做分庫梳理工作(記憶體速度還是比較快的),後分庫批量flush。 6) 搜尋 在電子商務平台中搜尋是一個非常的重要功能,主要有搜尋詞類目導航、自動提示和搜尋排序功能。 開源的企業級搜尋引擎主要有 Solr是基於lucene的高效能的全文搜尋伺服器,提供了比lucene更為豐富的查詢語言,可配置可擴展,對外提供基於http協定的XML/JSON格式的介面。 #從Solr4版本開始提供了SolrCloud方式來支援分散式的索引,自動進行sharding資料切分;透過每個sharding的master-slave(leader、replica )模式提高搜尋的效能;利用zookeeper對叢集進行管理,包括leader選舉等等,保障叢集的可用性。 Lucene索引的Reader是基於索引的snapshot的,所以必須在索引commit的後,重新開啟一個新的snapshot,才能搜尋到新加入的內容;而索引的commit是非常耗效能的,這樣達到即時索引搜尋效率就比較低。 #對於索引搜尋即時性,Solr4 Solr4提供了NRT softcommit的解決方案,softcommit無需進行提交索引操作,就可以搜素到最新對索引的變更,不過對索引的變更並沒有sync commit到硬碟儲存上,若發生意外導致程式非正常結束,未commit的資料會遺失,因此需要定時的進行commit操作。 #平台中對資料的索引和儲存操作是異步的,可以大幅提高可用性和吞吐量;只對某些屬性欄位做索引操作,儲存資料的標識key,減少索引的大小;資料是儲存在分散式儲存Hbase 中的,hbase對二級索引搜尋支援的不好,然而可以結合Solr搜尋功能進行多維度的檢索統計。 索引資料和HBase資料儲存的一致性,也就是如何保障HBase儲存的資料都被索引過,可以採用confirm確認機制,透過在索引前建立待索引資料佇列,在資料儲存並索引完成後,從待索引資料佇列中刪除資料。 日誌系統需具備三個基本元件,分別為agent(封裝資料來源,將資料來源中的資料傳送給collector),collector (接收多個agent的數據,並進行匯總後導入後端的store中),store(中央儲存系統,應該具有可擴展性和可靠性,應該支持當前非常流行的HDFS)。 的開源日誌收集系統業界所使用的比較多的是cloudera的Flume和facebook的Scribe#Flume目前的版本FlumeNG對Flume從架構上做了大幅的改變。 ##在設計或對日誌收集系統做技術選型時,通常需要具有以下特徵: a、 應用系統和分析系統之間的橋樑,將他們之間的關係解耦 #b 、 分散式可擴展,具有高的擴展性,當資料量增加時,可以透過增加節點水平擴展日誌收集系統是可以伸縮的,在系統的各個層次都可伸縮,對資料的處理不需要帶狀態,伸縮性方面也比較容易實現。 c、 近實時性在一些時效性要求比較高的場景中,需要可以及時的收集日誌,進行資料分析;一般的日誌檔案都會定時或定量的進行 ,所以即時偵測日誌檔案的生成,及時對日誌檔案進行類似的 操作,並支援批次傳送提高傳輸效率;批次傳送的時機需要滿足訊息數量和時間間隔的要求。 d、 容錯性Scribe在容錯的考量是,當後端的儲存系統crash時,scribe會將資料寫到本機磁碟上,當儲存系統復原正常後,scribe FlumeNG透過Sink Processor實現負載平衡和故障轉移。多個Sink可以構成一個Sink Group。一個Sink Processor負責從一個指定的Sink Group中啟動一個Sink。 Sink Processor可以透過群組中所有Sink實現負載平衡;也可以在一個Sink失敗時轉移到另一個。
e、 事務支援 Scribe Flume FlumeNG的channel根據可靠性的要求的不同,可以基於記憶體和檔案持久化機制,基於記憶體的資料傳輸的銷量比較高,但是在節點宕機後,數據遺失,不可恢復;而檔案持久化宕機是可以恢復的。 g、 資料的定時定量歸檔 資料經過日誌收集系統歸集後,一般儲存在分散式檔案系統如Hadoop,為了方便對資料進行後續的處理分析,需要定時(TimeTrigger)或定量(SizeTrigger的rolling分散式系統的檔案。 在交易系統中,通常需要進行異質資料來源的同步,通常有資料檔案到關係型資料庫,資料檔案到分散式資料庫,關係型資料庫到分散式資料庫等。資料在異質來源之間的同步一般是基於效能和業務的需求,資料儲存在本地文件中一般是基於效能的考慮,檔案是順序儲存的,效率還是比較高的;資料同步到關係型資料一般是基於查詢的需求;而分散式資料庫是儲存越來越多的大量資料的,而關係型資料庫無法滿足大資料量的儲存和查詢請求。 在資料同步的設計中需要綜合考慮吞吐量、容錯性、可靠性、一致性的問題 #同步有即時增量資料同步和離線全量資料區分,以下從這兩個維度來介紹一下, 即時增量一般是Tail檔案來即時追蹤檔案變化,批次或多執行緒往資料庫匯出,這種方式的架構類似日誌收集框架。這種方式需要有確認機制,包括兩個面向。 一個面向是Channel需要給agent確認已經批次收到資料記錄了,發送LSN號給agent,這樣在agent失效恢復時,可以從這個LSN點開始tail;當然對於允許少量的重複記錄的問題(發生在channel給agent確認的時,agent宕機並未受到確認訊息),需要在業務場景中判斷。 另一個面向是sync給channel確認已經批次完成寫入到資料庫的操作,這樣channel可以刪除這部分已經confirm的訊息。 基於信度的要求,channel 參考下圖 需要將來源資料例如MySQL切分,多執行緒並發讀源數據,多執行緒並發批次寫入分散式資料庫例如HBase,利用channel作為讀寫之間的緩衝,實現更好的解耦,channel可以基於檔案儲存或記憶體。請參閱下圖: 對於來源資料的切分,如果是檔案可以根據檔案名稱設定區塊大小來切分。 對於關聯式資料庫,由於一般的需求是只離線同步一段時間的資料(例如凌晨把當天的訂單資料同步到HBase),所以需要在資料切分時(依照行數切分),會多執行緒掃描整個表(及時建立索引,也要回表) ,對於表中包含大量的資料來講,IO很高,效率非常低;這裡解決的方法是對資料庫依照時間欄位(依照時間同步的)建立分割區,每次依照分割區進行匯出。 9) 資料分析從傳統的基於關係型資料庫並行處理叢集、用於記憶體計算近實時的,到目前的基於hadoop的大量資料的分析,資料的分析在大型電子商務網站中應用非常廣泛,包括流量統計、推薦引擎、趨勢分析、使用者行為分析、資料探勘分類器、分散式索引等等。 並行處理叢集有商業的EMC Greenplum,Greenplum的架構採用了MPP(大規模並行處理),基於postgresql的大數據量儲存的分散式資料庫。 #記憶體運算方面有SAP的HANA,開源的nosql記憶體型的資料庫mongodb也支援mapreduce進行資料的分析。 #海量資料的離線分析目前網路公司大量的使用 Hadoop,Hadoop在可擴展性、健全性、運算效能和成本上具有無可取代的優勢,事實上已成為當前網路企業主流的大數據分析平台 Hadoop透過MapReuce的分散式處理框架,用於處理大規模的數據,伸縮性也非常好;但是MapReduce最大的不足是不能滿足即時性的場景,主要用於離線的分析。 基於MapRduce模型程式設計做資料的分析,開發上效率不高,位於hadoop之上Hive的出現使得資料的分析可以類似寫sql的方式進行,sql經過語法分析、產生執行計劃後最終生成MapReduce任務進行執行,這大大提高了開發的效率,做到以ad-hoc(計算在query發生時)方式進行的分析。 基於MapReduce模型的分散式資料的分析都是離線的分析,執行上都是暴力掃描,無法利用類似索引的機制;開源的 Cloudera Impala是基於MPP的平行程式設計模型的,底層是Hadoop儲存的高效能的即時分析平台,可以大幅降低資料分析的延遲。 目前Hadoop使用的版本是Hadoop1.0,一方面原有的MapReduce框架存在JobTracker單點的問題,另一方面JobTracker在做資源管理的同時又做任務的調度工作,隨著資料量的增加和Job任務的增多,明顯存在可擴展性、記憶體消耗、執行緒模型、可靠性和效能上的缺陷瓶頸;Hadoop2.0 yarn##整個框架進行了重構,分離了資源管理和任務調度,從架構設計解決了這個問題。 參考Yarn 原始基於單節點的計算,隨著系統資訊量爆炸式產生以及計算的複雜度的增加,單一節點的計算已無法滿足即時計算的要求,需要進行多節點的分散式的計算,分散式即時計算平台就出現了。 這裡所說的即時運算,其實是串流運算,概念前身其實是CEP複雜事件處理,相關的開源產品如Esper,業界分散式的串流計算產品Yahoo S4,Twitter storm等,以storm開源產品使用最為廣泛。 Twitter的Storm在以上這幾個方面做的比較好,下面要介紹一下Storm的架構。 整個叢集的管理是透過zookeeper來進行的。 客戶端提交拓樸到nimbus。 Nimbus針對該拓撲建立本地的目錄根據topology的配置計算task,分配task,在zookeeper上建立assignments節點儲存task和supervisor機器節點中woker的對應關係。 在zookeeper上建立taskbeats節點來監控task的心跳;啟動 topology。 #Supervisor去zookeeper上取得分配的tasks,啟動多個woker進行,每個woker產生task,一個task一個線程;根據topology資訊初始化建立task之間的連接;Task和Task之間是透過zeroMQ管理的;之後整個拓樸運行起來。 #Tuple是流的基本處理單元,也就是一個訊息,Tuple在task中流轉,Tuple的發送和接收過程如下: 發送Tuple,Worker提供了一個transfer的功能,用於當前task把tuple發到其他的task。以目的taskid和tuple參數,序列化tuple資料並放到transfer queue。 在0.8版本之前,這個queue是LinkedBlockingQueue,0.8之後是DisruptorQueue 。 #在0.8版本之後,每一個woker綁定一個inbound transfer queue和outbond queue,inbound queue用於接收 ##,outbond queue用於傳送訊息。 發送訊息時,由單一執行緒從transferqueue中拉取數據,把這個tuple透過zeroMQ傳送到其他的woker中。 # 接收Tuple,每個woker都會監聽zeroMQ的tcp連接埠來接收訊息,訊息放到DisruptorQueue後,後從queue中取得message(taskid,tuple),根據目的taskid,tuple的值路由到task中執行。每個tuple可以emit到direct steam#中,也可以送到regular stream##Reglular方式下,由Stream Group(stream id-->component id -->outbond tasks)功能完成目前tuple將要傳送的 Tuple的目的地。 透過上述分析可以看到,Storm在伸縮性、容錯性、高效能方面的從架構設計的角度得以支撐;同時在可靠性方面,Storm的ack組件利用異或xor 11) 即時推送即時推送的應用場景非常多,例如係統的監控動態的即時曲線繪製,手機訊息的推送,web即時聊天等。 Comet基於伺服器長連線的「伺服器推」技術,包含兩種: Long Polling:伺服器端在接到請求後掛起,有更新時返回連接即斷掉,然後客戶端再發起新的連接 Stream方式: 每次服務端資料傳送不會關閉連接,連接只會在通信發生錯誤時,或是連接重建時關閉(有些防火牆常被設定為丟棄過長的連接, 伺服器端可以設定一個逾時時間, 逾時後通知客戶端重新建立連接,並關閉原來的連線)。 Websocket:長連接,全雙工通訊 是 HTML5 的一種新的協議。它實作了瀏覽器與伺服器的雙向通訊。在 webSocket API 中,瀏覽器和伺服器端只需要透過一個握手的動作,便能形成瀏覽器與客戶端之間的快速雙向通道,使得資料可以快速的雙向傳播。 Socket.io是一個NodeJS websocket庫,包括客戶端的js和服務端的nodejs,用於快速建立即時的web應用。 待補充 資料庫儲存大體分為以下幾類,有關聯式(交易型)的資料庫,以oracle、mysql為代表,有keyvalue資料庫,以redis和memcached db為代表,有文件型資料庫如mongodb,有列式分散式資料庫以HBase,cassandra,dynamo為代表,還有其他的圖形資料庫、物件資料 庫、xml資料庫等。每種類型的資料庫應用的業務領域是不一樣的,以下從內存型、關係型、分散式三個維度針對相關的產品做性能可用性等方面的考慮分析。 1) 記憶體型資料庫記憶體類型的資料庫,以高並發高效能為目標,在事務性方面沒那麼嚴格,以開源nosql資料庫mongodb、redis為例 Ø Mongodb #通訊方式多執行緒方式,主執行緒監聽新的連接,連接後,啟動新的執行緒做資料的操作(IO
資料結構 # -->collection-->recordMongoDB在資料儲存上以命名空間劃分,一個collection是一個命名空間,一個索引也是一個命名空間。 同一個命名空間的資料被分成很多個Extent,Extent之間使用雙向鍊錶連接。 在每一個Extent 每一行資料儲存空間不僅包含資料佔用空間,還可能包含一部分附加空間,這使得在資料update變大後可以不移動位置。 索引以BTree結構實作。 如果你開啟了jorunaling日誌,那麼還會有一些檔案儲存你所有的操作記錄。 使用持久化儲存 MMap方式將檔案位址對應到內存的位址空間,直接操作記憶體位址空間就可以操作文件,不用再呼叫write,read操作,效能比較高。 mongodb呼叫mmap把磁碟中的資料對應到記憶體中的,所以必須有一個機制時刻的刷資料到硬碟才能保證可靠性,多久刷一次是與syncdelay參數相關的。 journal(進行復原用)是Mongodb中的redo log#,而Oplog則是負責複製的binlog。如果打開journal,那麼即使斷電也只會丟失100ms的數據,這對大多數應用來說都可以容忍了。從1.9.2+,mongodb都會預設開啟journal功能,以確保資料安全。而且journal的刷新時間是可以改變的,2-300ms的範圍,使用 --journalCommitInterval 指令。 Oplog和資料刷新到磁碟的時間是60s,對於複製來說,不用等到oplog刷新磁碟,在記憶體中就可以直接複製到Sencondary節點。
#Mongodb只支援對單行記錄的原子運算 HA集群使用的比較多的是Replica Sets,採用選舉演算法,自動進行 選舉,在保證可用性的同時,可以做到強一致性要求。 當然對於大量的數據,mongodb也提供了數據的切分架構 。 Ø Redis 豐富的資料結構,高速的反應速度,記憶體操作 通訊方式 reactor模式,實作自己的多路復用NIO機制(epoll,select,kqueue等) # 單一執行緒處理多任務 資料結構 hash+bucket結構,當鍊錶的長度過長時,會採取遷移的措施(擴展原來兩倍的hash表,把資料遷移過去,expand+rehash) # 持久化儲存 a、全量持久化RDB(遍歷redisDB,讀取bucket中的key,value),save指令阻塞主線程,bgsave開啟子程序進行snapshot持久化操作,產生rdb檔。 在shutdown時,會呼叫save操作
# 資料發生變化,在多少秒內觸發一次bgsave#sync,master接受slave發出來的命令b、增量持久化(aof類似redolog) ,先寫到日誌buffer,再flush flush的策略可以設定的,而已單條,也可以批次),只有flush到文件上的,才真正回到客戶端。 #要定時對aof檔案和rdb檔案做合併操作(在快照過程中,變更的資料先寫到aof buf中等子進程完成快照 記憶體snapshot>後,再進行合併aofbuf變化的部分以及全鏡像資料)。 #在高並發存取模式下,RDB模式使服務的效能指標出現明顯的抖動, 通用的解決方案是主從備份切換,採用HA軟體,使得失效的主redis可以快速的切換到從redis上。主從資料的同步採用複製機制,該場景可以做讀寫分離。 目前在複製方面,存在的一個問題是在遇到網路不穩定的情況下,Slave和Master斷開(包括閃斷)會導致Master需要將記憶體中的資料全部重新產生rdb檔案(快照檔案),然後傳送給Slave。 Slave接收完Master傳遞過來的rdb檔案以後會將自身的記憶體清空,把rdb檔重新載入到記憶體中。這種方式效率比較低下,在後面的未來版本Redis2.8作者已經實現了部分複製的功能。 2) 關係型資料庫關係型資料庫在滿足並發效能的同時,也需要滿足事務性,以mysql Ø mysql的架構原理 在架構上,mysql分為server層和儲存引擎層。 Server層的架構對於不同的儲存引擎來講都是一樣的,包含連接/執行緒處理、查詢處理(parser、optimizer)以及其他系統任務。儲存引擎層有很多種,mysql提供了儲存引擎的外掛程式結構,支援多種儲存引擎,用的最廣泛的是innodb和myisamin ;inodb主要面向OLTP方面的應用,支援事務處理,myisam不支援事務,表鎖,對OLAP操作速度快。
以下主要針對 儲存引擎做相關介紹。 在執行緒處理方面,Mysql是多執行緒的架構,由一個master#線程,一個鎖定監控線程,一個錯誤監控線程,和多個IO線程組成。並且對一個連線會開啟一個執行緒進行服務。 io執行緒又分為節省隨機IO的insert buffer#,用於交易控制的類似oracle的redo log ,以及多個write,多個read的硬碟和記憶體交換的IO執行緒。 在記憶體分配方面,包含innodb buffer pool ,以及log buffer。其中innodb buffer pool包括insert buffer、datapage、index page、資料字典、自適應hash。 Log buffer用於快取交易日誌,提供效能。 在資料結構方面,innodb包含表格空間、區段、區、頁/區塊,行。索引結構是B+tree結構,包括二級索引和主鍵索引,二級索引的葉子節點是主鍵PK,根據主鍵索引的葉子節點指向儲存的資料塊。這個B+樹儲存結構可以更好的滿足隨機查詢操作IO要求,分為資料頁和二級索引頁,修改二級索引頁面涉及到隨機操作,為了提高寫入時的效能,採用insert buffer做順序的寫入,再由後台執行緒以一定頻率將多個插入合併到二級索引頁面。為了確保資料庫的一致性(記憶體和硬碟資料檔案),以及縮短實例復原的時間,關聯式資料庫還有一個checkpoint的功能,用於把記憶體buffer中之前的髒頁依照比例(舊的LSN)寫入磁碟,這樣redolog檔案的LSN先前的日誌就可以被覆寫了,進行循環使用;在失效復原時,只需要從日誌中LSN點進行復原即可。 在事務特性支援上,關係型資料庫需要滿足ACID四個特性,需要根據不同的事務並發和資料可見性要求,定義了不同的事務隔離級別,並且離不開對資源爭用的鎖機制,要避免產生死鎖,mysql在Server層和儲存引擎層做並發控制,主要體現在讀寫鎖,根據鎖粒度不同,有各個層級的鎖(表格鎖定、行鎖定、頁鎖定、MVCC);基於提高並發效能的考慮,使用多版本並發控制MVCC來支援交易的隔離,並基於undo來實現,在做交易回溯時,也會用到undo段。 mysql 用redolog來確保資料的寫入的效能和失效恢復,在修改資料時只需要修改內存,再把修改行為記錄到交易日誌中(順序IO),不用每次將資料修改本身持久化到硬碟(隨機IO),大幅提升效能。 #在可靠性方面,innodb儲存引擎提供了兩次寫入機制double writer用於防止在flush頁面到儲存上出現的錯誤,解決磁碟half-writern的問題。 Ø 對於高並發高效能的mysql
## #來講,可以在多個維度進行效能方面的調優。 ############a###、硬體級別,#########日誌和資料的存儲,需要分開,日誌是順序的寫,需要做###raid1+ 0###,並且用###buffer-IO###;資料是離散的讀寫,走###direct IO###即可,避免走檔案系統###cache###帶來的開銷。 ##############################。儲存能力,###SAS###磁碟###raid####作業( ###raid###卡片緩存,關閉讀取###cache###,關閉磁碟###cache###,關閉預讀,只用###writeback buffer###,但需要考慮充放電的問題),當然如果資料規模不大,資料的儲存可以用高速的設備,###Fusion IO###、###SSD###。 ########################################################### ####對於資料的寫入,控制髒頁刷新的頻率,對於資料的讀取,控制###cache hit###率;因此而估算系統需要的###IOPS###,評估需要的硬碟數###量(fusion io###上到###IOPS ###在10w###以上,普通的硬碟###150)###。 ##################################### Cpu方面,單一實例關閉NUMA,mysql對多核心的支援不是太好,可以對多實例進行CPU綁定。 b、作業系統級別, 核心以及socket#的最佳化,網路最佳化bond、檔案系統、IO調度 #innodb主要用在 OLTP類別應用,一般都是IO密集型的應用,在提升IO能力的基礎上,充分利用cache機制。需要考慮的內容有, #在保證系統可用記憶體的基礎上,盡可能的擴大innodb buffer pool,一般設定為實體記憶體的3/4 檔案系統的使用,只在記錄交易日誌的時候用檔案系統的cache;盡量避免mysql用到swap(可以將vm.swappiness=0,記憶體緊張時,釋放檔案系統cache) #IO調度最佳化,減少不必要的阻塞,降低隨機IO存取的延時(CFQ、Deadline、NOOP) server以及儲存引擎層級(連線管理、網路管理、table管理、日誌) cache/buffer、Connection、IO## d、應用層級(如索引的考慮, 的最佳化適當冗餘;最佳化sql#查詢導致的CPU問題和記憶體問題,減少鎖的範圍,減少回表掃描,覆蓋索引)#Ø 在高可用實踐方面, 、master-slave模式,master-master模式是一個作為主負責讀寫,另一個作為standby提供災備, maser-slave是一個作為主提供寫入操作,其他幾個節點作為讀取操作,支援讀寫分離。 #對於節點主備失效偵測與切換,可以採用 軟體,當然也可以從更細緻客製化的角度,採用zookeeper作為叢集的協調服務。 對於分散式的系統來講,資料庫主備切換的一致性總是一個問題,可以有以下幾種方式: #a oracle的rack,缺點是比較複雜## b、共享SAN儲存方式,相關的資料檔案和日誌檔案都放在共用儲存上,優點是主備切換時資料保持一致,不會遺失,但由於備機有一段時間的拉起,會有短暫的不可用狀態 c、主備進行資料同步的方式,常見的是日誌的同步,可以保障熱備,即時性好,但是切換時,可能有部分資料沒有同步過來,帶來了資料的一致性問題。可以在操作主資料庫的同時,記錄操作日誌,切換到備時,會和操作日誌做個check,補齊未同步過來的資料; d、還有一種做法是備庫切換到主庫的regolog的儲存上,保證資料不會遺失。 資料庫主從複製的效率在mysql上不是太高,主要原因是事務是嚴格保持順序的,索引mysql在複製方麵包括日誌IO和relog log兩個過程都是單執行緒的串列操作,在資料複製最佳化方面,盡量減少IO#的影響。不過到了Mysql5.6版本,可以支援在不同的函式庫上的平行複製。 #Ø 基於不同業務要求的存取方式 平台業務中,不同的業務有不同的訪問要求,例如典型的兩大業務用戶和訂單,用戶一般來講總量是可控的,而訂單是不斷地遞增的,對於用戶表首先採取分庫切分,每個sharding做一主多讀,同樣對於訂單因更多需求的是用戶查詢自己的訂單,也需要按照用戶進行切分訂單庫,並且支持一主多讀。 在硬體儲存方面,對於交易日誌因是順序寫,快閃記憶體的優勢比硬碟高不了多少,所以採取電池保護的寫入快取的raid卡儲存;對於資料文件,無論是對使用者或訂單都會存在大量的隨機讀寫操作,當然加大記憶體是一個方面,另外可以採用高速的IO設備閃存,例如PCIe卡片 fusion-io。使用快閃記憶體也適合在單一執行緒的負載中,例如主從複製,可以對從節點配置fusion-IO卡,降低複製的延遲。 #對於訂單業務來講,量是不斷遞增的,PCIe卡片儲存容量比較有限,而且訂單業務的熱數據只有最近一段時間的(例如近3個月的),對此這裡列兩種解決方案,一種是flashcache方式,採用基於快閃記憶體和硬碟儲存的開源混合儲存方式,在快閃記憶體中儲存熱點的資料。另外一種是可以定期把老的資料匯出到分散式資料庫HBase中,使用者在查詢訂單清單是近期的資料從mysql取得,老的資料可以從HBase中查詢,當然需要HBase良好的rowkey設計以適應查詢需求。 對於資料的高並發的訪問,傳統的關係型資料庫提供讀寫分離的方案,但是帶來的確實資料的一致性問題提供的資料切分的方案;對於越來越多的海量數據,傳統的資料庫採用的是分庫分錶,實現起來比較複雜,後期要不斷的進行遷移維護;對於高可用和伸縮方面,傳統數據採用的是主備、主從、多主的方案,但是本身擴展性比較差,增加節點和宕機需要進行資料的遷移。對於上述提出的這些問題,分散式資料庫HBase有一套完善的解決方案,適用於高並發大量資料存取的要求。 Ø HBase 基於列式的高效能儲存降低IO 高效能 LSM Tree 適合高速寫入的場景 強一致的資料存取 MVCC HBase的一致性資料存取是透過MVCC來實現的。 HBase在寫資料的過程中,需要經過好幾個階段,寫HLog,寫memstore,更新MVCC; #只有更新了MVCC,才算是真正memstore寫成功,其中事務的隔離需要有mvcc的來控制,例如讀取資料不可以取得別的執行緒還未提交的資料。 高可靠度 HBase的資料儲存是基於HDFS ,提供了冗餘機制。 Region節點的宕機,對於記憶體中的資料尚未flush到檔案中,提供了可靠的復原機制。 # 可伸縮,自動切分,遷移 透過Zookeeper定位目標Region Server,最後定位Region。 Region Server擴容,透過將自身發佈到Master,Master均勻分佈。 # 可用性 存在單點故障,Region Server 宕機後,短時間內該server維護的region無法訪問,等待failover生效。 透過Master維護各Region Server健康狀況和Region分佈。 多個Master,Master宕機有zookeeper的paxos投票機制選取下一任Master# 。 Master就算全宕機,也不影響Region讀寫。 Master僅扮演一個自動運維角色。 HDFS為分散式儲存引擎,一備三,高可靠,0資料遺失。 HDFS的namenode是一個SPOF。 為避免單一region存取過於頻繁,單機壓力過大,提供了split機制 HBase的寫入是LSM-TREE的架構方式,隨著資料的append,HFile越來越多,HBase提供了HFile檔案進行compact,對過期資料進行清除,提高查詢的效能。
#Schema free HBase沒有像關係型資料庫那樣的嚴格的schema,可以自由的增加和刪除schema中的欄位。 HBase分散式資料庫,對於二級索引支援的不太好,目前只支援在rowkey上的索引,所以rowkey的設計對於查詢的效能來講非常關鍵。 大型分散式系統涉及各種設備,例如網路交換機,一般PC 平台的資料分類應用業務等級:應用事件、業務日誌、稽核日誌、請求日誌、例外、請求業務metrics 系統層級:CPU、記憶體、網路、IO 時效性需求 # 架構節點中Agent代理可以接收日誌、應用的事件以及透過探針的方式採集數據,agent採集資料的一個原則是和業務應用的流程是異步隔離的,不影響交易流程。 資料統一透過collector集群進行收集,按照資料的不同類型分發到不同的計算集群進行處理;有些資料時效性不是那麼高,例如按小時進行統計,放入 hadoop集群;有些數據是請求流轉的追蹤數據,需要可以查詢的,那麼就可以放入solr集群進行索引;有些數據需要進行即時計算的進而告警的,需要放到storm叢集中進行處理。 資料經過計算叢集處理後,結果儲存到Mysql或HBase中。 監控的web應用程式可以把監控的即時結果推送到瀏覽器中,也可以提供API#供結果的展現與搜尋。 以上是建立高並發高可用的架構的詳細內容。更多資訊請關注PHP中文網其他相關文章!3. 多重維度的可用
1) # 負載平衡、災難、備份
2) 讀寫分離
3) 依賴關係
4) 監控
4. 伸縮
1) 分割
2) 無狀態
5. 最佳化資源使用量
1) 系統容量有限
3)
基於邏輯的不同,採取不同的策略spin的方式,減少對執行緒的切換(例如Oracle latch設計);對於運算型的,充分利用多執行緒進行操作。
三、 剖析架構
1. CDN
2. 負載平衡、反向代理
對於圖片,需要有單獨的域名,獨立或分散式的圖片伺服器或如
mogileFS 4. 業務服務
5. 基礎服務中間件
1) 通訊元件
#2) 路由Router
8) 資料同步
的架構
10) 即時計算在網路領域,即時運算被廣泛即時監控分析、串流、風險控制等領域。電商平台系統或應用對日常產生的大量日誌和異常訊息,需要經過即時過濾、分析,以判定是否需要預警;同時需要對系統做自我保護機制,例如對模組做流量的控制,以防止非預期的對系統壓力過大而引起的系統癱瘓,流量過大時,可以採取拒絕或者引流等機制;有些業務需要進行風險的控制,比如彩票中有些業務需要根據系統的實時銷售情況進行限號與放號。 #12) 建議引擎
6. 資料儲存
3) 分散式資料庫
通常的查詢不需要一行的全部字段,大多數只需要幾個字段
對與面向行的存儲系統,每次查詢都會全部資料取出,然後再從中選出需要的字段
面向列的存儲系統可以單獨查詢某一列,從而大大降低IO
提高壓縮效率
同列資料具有很高的相似性,會增加壓縮效率
Hbase的許多特性,都是由列儲存決定的