網際網路架構三板斧之併發

技術瑣話發表於2019-03-01

由於營銷活動(創造營銷節點、擴大影響力的需要),總有很多產品策劃、運營樂此不疲的玩著一個game---在足夠集中的時間內比如秒級處理足夠多的使用者請求,讓世界為此狂歡,同時也是彰顯技術實力的一次大考。

小米賣著搶號的手機、天貓發明了雙11光棍節、微信和支付寶連續2年做著新春紅包。營銷活動的時候要使用前2板斧,保證可用性和簡單可擴充套件性,同時還要祭出第三板絕殺—攔河大壩、快取為王、去熱點資源的併發。

為啥要攔?很簡單,使用者很熱情(感性),但系統必須得理性!就3個蘋果手機,憑啥讓幾十萬人都湧入櫃檯!在大秒系統一文中許同學就娓娓道來(省得少畫個圖)……
網際網路架構三板斧之併發
對大流量系統的資料做分層校驗也是最重要的設計原則,所謂分層校驗就是對大量的請求做成“漏斗”式設計,如上圖所示:在不同層次儘可能把無效的請求過濾,“漏斗”的最末端才是有效的請求,要達到這個效果必須對資料做分層的校驗,下面是一些原則:
1  先做資料的動靜分離
2  將90%的資料快取在客戶端瀏覽器
將動態請求的讀資料Cache在Web端
4  對讀資料不做強一致性校驗
對寫資料進行基於時間的合理分片
對寫請求做限流保護
7  對寫資料進行強一致性校驗
將90%的資料快取在客戶端瀏覽器,將動態請求的讀資料cache在web端,還是不夠的。在大秒的過程中,存在極端情況,就是請求超過單key所在server的QPS能力。
資料訪問熱點,比如Detail中對某些熱點商品的訪問度非常高,即使是Tair快取這種Cache本身也有瓶頸問題,一旦請求量達到單機極限也會存在熱點保護問題。有時看起來好像很容易解決,比如說做好限流就行,但你想想一旦某個熱點觸發了一臺機器的限流閥值,那麼這臺機器Cache的資料都將無效,進而間接導致Cache被擊穿,請求落地應用層資料庫出現雪崩現象。這類問題需要與具體Cache產品結合才能有比較好的解決方案,這裡提供一個通用的解決思路,就是在Cache的client端做本地Localcache,當發現熱點資料時直接Cache在client裡,而不要請求到Cache的Server。
資料更新熱點,更新問題除了前面介紹的熱點隔離和排隊處理之外,還有些場景,如對商品的lastmodifytime欄位更新會非常頻繁,在某些場景下這些多條SQL是可以合併的,一定時間內只執行最後一條SQL就行了,可以減少對資料庫的update操作。另外熱點商品的自動遷移,理論上也可以在資料路由層來完成,利用前面介紹的熱點實時發現自動將熱點從普通庫裡遷移出來放到單獨的熱點庫中。
心得體會
請允許筆者總結一下高併發方案的解決之道。

使用快取,能越前端快取的放在前端,

這樣呼叫鏈路最短。

這裡的快取不僅僅是redis、或者memcached,而是local或者climatchent優先的思路,去除對併發資源的依賴。比如[揭祕微信搖一搖背後的技術細節]一文中提到:
按一般的系統實現,使用者看到的紅包在系統中是資料庫中的資料記錄,搶紅包就是找出可用的紅包記錄,將該記錄標識為match屬於某個使用者。在這種實現裡,資料庫是系統的瓶頸和主要成本開銷。我們在這一過程完全不使用資料庫,可以達到幾個數量級的效能提升,同時可靠性有了更好的保障。 
1   支付系統將所有需要下發的紅包生成紅包票據檔案;
2   將紅包票據檔案拆分後放到每一個接入服務例項中;
3   接收到客戶端發起搖一搖請求後,接入服務裡的搖一搖邏輯拿出一個紅包票據,在本地生成一個跟使用者繫結的加密票據,下發給客戶端;
4   客戶端拿加密票據到後臺拆紅包,match後臺的紅包簡化服務通過本地計算即可驗證紅包,完成搶紅包過程。

 分拆熱點

上文提到,在極端情況下大秒使用了二級快取,通過拆分key來達到避免超過cache server請求能力的問題。在facebook有一招,就是通過多個key_index(key:xxx#N) ,來獲取熱點key的資料,其實質也是把key分散。對於非高一致性要求的高併發讀還是蠻有效的。如圖
網際網路架構三板斧之併發
則解決之道是:
• Hot keys are published to all web-servers
• Each web-server picks an alias for gets
– get key:xxx => get key:xxx#N
• Each web-server deletes all aliases
微博團隊披露:服務端本地快取,使用nginx本身快取和伺服器的L0快取,來提升模組的響應速度,做到了90%以上核心介面的響應時間在50ms以內,減少了程式等待時間,提升了伺服器的處理速度。
解決併發有1種基本辦法: 分拆!而分拆有兩種拆法,
1  拆資源
一是把資源(resource)拆了,著名的比如ConcurrentHashMap,拆成了16個桶,併發能力大大提高。
2   拆基礎資料
在紅包應用中,如果還依賴一個共同的基礎資料,也可以把這個基礎資料拆成多個cell。
預處理
[互動1808億次,16倍的超越!談支付寶紅包的高併發挑戰]一文中如此說:
在這次春晚活動中,涉及到大量的資源,包括圖片、拜年視訊等。圖片和視訊都比較大,十幾b到幾百kb不等。當在高峰期時,如果瞬間有海量的請求到CDN上,這麼大的請求頻寬根本扛不住。我們當時預估了大約有幾T的頻寬需求。
為了能有效地扛住瞬間峰值對CDN的壓力,我們對資源進行了有效的管理和控制。首先在客戶端預埋了幾個預設資源,萬一真不行了,這幾個資源可以用。其次儘量提前開啟入口,當使用者瀏覽過後,就將資源下載到本地。再次瀏覽時不再需要遠端訪問CDN。最後,做了應急預案,高峰期一旦發現流量告警,緊急從視訊切換到圖片,降低頻寬壓力,確保不出現頻寬不夠而發生限流導致的黑屏等體驗不好的問題。
最後的結果可以用完美來形容,由於預熱充分,頻寬雖然很高,但沒達到我們的告警值,應急預案也沒有使用。

微信團隊也提到:

在除夕,使用者通過搖一搖參與活動,可以搖到紅包或其他活動頁,這些頁面需要用到很多圖片、視訊或 H5 頁面等資源。在活動期間,參與使用者多,對資源的請求量很大,如果都通過實時線上訪問,伺服器的網路頻寬會面臨巨大壓力,基本無法支撐;另外,資源的尺寸比較大,下載到手機需要較長時間,使用者體驗也會很差。因此,我們採用預先下載的方式,在活動開始前幾天把資源推送給客戶端,客戶端在需要使用時直接從本地載入。

非同步化
江湖傳說中有一句話,叫能非同步的儘量非同步。做活動的時候,資源多寶貴啊,對C端無感但可以容忍的,就讓它慢慢做,而此種一般放入到佇列當中。
 

杭州的蘑菇街七公又名小白,是一個熱情的朋友。他提及交易服務依賴過多的解決之道。服務依賴過多,會帶來管理複雜性增加和穩定性風險增大的問題。試想如果我們強依賴10個服務,9個都執行成功了,最後一個執行失敗了,那麼是不是前面9個都要回滾掉?這個成本還是非常高的。所以在拆分大的流程為多個小的本地事務的前提下,對於非實時、非強一致性的關聯業務寫入,在本地事務執行成功後,我們選擇發訊息通知、關聯事務非同步化執行的方案。(看看下圖,那些可以非同步化?)

網際網路架構三板斧之併發

使用佇列

攔、攔、攔;之後快取抗;快取扛不住的併發分拆;但是還有一個問題,就是極端熱點資源在db裡,如果併發高還是會出問題。大秒一文中有較好的處理方案,就是排隊。Web伺服器排隊,在db層還做了一個patch排隊,真心是業務是最好的老師,不得已何必祭大招!


 應用層做排隊。按照商品維度設定佇列順序執行,這樣能減少同一臺機器對資料庫同一行記錄操作的併發度,同時也能控制單個商品佔用資料庫連線的數量,防止熱點商品佔用太多資料庫連線。關於詳情,可以閱讀大秒一文。

引用
引用內容 from:
《互動1808億次,16倍的超越!談支付寶紅包的高併發挑戰》- QCon公眾號
《10億紅包從天而降,揭祕微信搖一搖背後的技術細節》 - InfoQ網站
《淘寶大秒系統設計詳解》- CSDN
《解密微博紅包:架構、防刷、監控和資源排程》 -  InfoQ網站

http://www.slideshare.net/jboner/scalability-availability-stability-patterns

LiveJournal's Backend - A history of scaling 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31562044/viewspace-2637306/,如需轉載,請註明出處,否則將追究法律責任。

相關文章