引言mysql
高併發常常會發生在有大活躍用戶量,用戶高彙集的業務場景中,如:秒殺活動,定時領取紅包等。面試
爲了讓業務能夠流暢的運行而且給用戶一個好的交互體驗,咱們須要根據業務場景預估達到的併發量等因素,來設計適合本身業務場景的高併發處理方案。redis
在工做這些年裏,我有幸遇到了高併發各類坑,對如何設計高性能接口有一些經驗,其實無外乎知足如下幾個特色:算法
靈敏性 伸縮性 容錯性 事件驅動/消息驅動 高性能接口設計準則sql
在引言裏我也說了高性能設計的四個準則,如今具體對這四個準則作一些描述;數據庫
應用程序應該儘量快的對請求作出響應。編程
若是能夠在順序獲取數據和並行獲取數據之間進行選擇的話,爲了儘快向用戶返回響應,始終應該優先選擇並行獲取數據,能夠同時請求互相沒有關聯的數據。當咱們須要請求多個互相無關,沒有依賴的數據的時候,應該考慮是否可以同時請求這些數據。緩存
若是可能出現錯誤,應該當即返回,將問題通知用戶,不要讓用戶等待直到超時。服務器
1.1 如何設計靈敏性數據結構
緩存前置
對於一些改變不頻繁的數據,應該放在分佈式緩存中,例如redis,若是是一些元數據(例如,一些計數器的配置信息,變量的配置信息等)則應該啓用本地緩存,簡單流程以下:
如何設計高性能的接口 若是一些熱點數據不大的話,建議服務啓動的時候就應該提早加載到緩存中,這樣能夠提升服務的性能。
讀寫拆分部署
若是你的服務既涉及到讀操做,也涉及到寫操做, 應該將讀寫隔離部署,這樣讀服務的壓力不會影響到寫服務,寫服務的壓力不會影響到讀服務。流程以下:
如何設計高性能的接口 固然除了按照讀寫進行拆分部署外,還能夠按照業務進行隔離部署。
對等設計、無狀態
所謂無狀態是指應用服務器不保存業務的上下文信息,而僅根據每次請求提交的數據進行相應的業務邏輯處理,多個服務實例(服務器)之間徹底對等,請求提交到任意服務器,處理結果是徹底同樣的。
不保存狀態的應用給高可用的架構設計帶來了巨大便利,既然服務器不保存請求的狀態,那麼全部的服務器徹底對等,當任意一臺或多臺服務器宕機,請求提交給集羣中的其餘任意一臺可用機器處理,這樣對終端用戶而言,請求老是可以成功的,整個系統依然可用。對於應用服務器集羣,實現這種服務器可用狀態實時檢測、自動轉移失敗任務的機制就是負載均衡。
如何設計高性能的接口 DB分庫分表,讀寫分離
對於數據層來講,若是數據量不大,db能夠採用讀寫分離部署,對於讀多寫少的場景能夠解決一部分壓力,從而提升咱們接口的響應速度,若是寫的數據量和讀的數據量都很大,那麼就必需要對db進行分庫分表外加讀寫分離了。
如何設計高性能的接口 2. 伸縮性
應用程序應該可以根據不一樣的工做負載進行伸縮擴展(尤爲是經過增長計算資源來進行擴展)。爲了提供伸縮性,系統應該努力消除瓶頸。
若是在虛擬機上運行內存數據庫,那麼添加另外一個虛擬幾點就能夠將全部的查詢請求分佈到兩臺虛擬服務器上,將可能的吞吐量增長至原來的兩倍。添加額外的節點應該可以幾乎線性的提升系統的性能。
增長一個內存數據庫的節點後,還能夠將數據分爲兩半,並將其中的一半移至新的節點,這樣就可以將內存容量提升至原來的兩倍。添加節點應該可以幾乎線性的提升內存容量。
因此通常好的接口設計是能夠經過水平擴展機器來達到提高性能的,這就要求咱們設計接口的時候提現無狀態性。
應用程序應該考慮到錯誤發生的狀況,而且從容的對錯誤狀況作出響應。若是系統的某個組件發生錯誤,對與該組件無關的請求不該該產生任務影響。錯誤是難以免的,所以應該將錯誤形成的影響限制在發生錯誤的組件以內。若是可能的話,經過對重要組件及數據的備份和冗餘,這些組件發生錯誤時不該該對其外部行爲有任何影響。
穩定性
穩定性是第一前提,如系統崩潰恢復容災備份這些,主要是一些數據保護的機制,還有就是程序參數的校驗、異常的處理、事務的回滾、程序邊界的設計(合理的邊界劃分能夠避免服務的連鎖崩潰)、對帳機制等,這些都是平常生活中經常使用的一些手段在計算機領域的體現,更詳細的設計就不深刻的分析了。
高併發
經過多年來對操做系統的研究,以及結合多年來各類語言的編程經驗來講,高性能的程序的開發其實都是有規可循的。由於高性能的程序基本上都會面臨類似的問題:如何提升併發,如何下降時間複雜度(可是並非一味的下降,須要在空間複雜度之間作一個平衡)。
如何提升併發:在目前的大多數程序中或多或少的都會遇到併發的問題,如何設計高效的併發很是的重要,從我我的的經驗來講,當遇到一個會存在併發的業務場景,我會首先整理業務場景,並根據業務場景畫出簡單的數據流圖,根據數據流圖找出相應的會併發訪問修改的數據,縮小加鎖的粒度(只對須要併發訪問的數據進行加鎖),。
而後分析數據的性質是否能夠局部的併發,這種狀況下就可使用分段鎖(再次減少加鎖的粒度,一個比較出名的例子就是mysql的表鎖、行鎖機制)。
最後再分析數據的訪問性質,是讀多寫少(大部分都是這種狀況)、讀少寫多(日誌)、仍是讀寫頻率差很少,不一樣的業務狀況使用不一樣的鎖,好比針對讀多寫少的業務來講,爲了提升讀的併發性可使用讀寫鎖;針對併發粒度較小,且併發操做的耗時很短的狀況,操做系統又提出了CAS操做(樂觀鎖),這種操做避免了上鎖和釋放鎖耗時的過程,進一步提升了併發性,可是隻是針對特定的場景才能達到想要的性能。
當單臺併發達到上限以後,就是分佈式系統粉墨登場了,雖然分佈式系統數據一致性會有必定的耗時,可是分佈式系統的併發卻有了顯著的提升,一致性所帶來的耗時/併發數帶來的平均延遲並不大,因此能很好的知足系統的需求。
高性能
高性能的設計主要分爲兩個層面,一個層面是操做系統層面的,另一個層面是業務層。
操做系統層面:儘可能使用操做系統和處理器自身的高性能的指令或者是運算方式,最簡單的例子是位運算,針對一些特殊的算法若是能使用位運算實現,那麼儘可能使用位運算實現(這在不少算法面試題中都會考的,由於位運算在不少場景都有特別切合實際的使用),還有就是合理高效的使用操做系統自身的API,如DMA之類的機制,以及有效的利用緩存之類的機制。
業務層面來講:首先須要爲數據的存儲設計合適的數據結構,這個也須要在空間利用率和訪問複雜度之間作權衡;而後爲業務中須要計算的場景設計高效的算法,算法的抽象是一個比較難的事情,算法設計須要在時間複雜度和空間複雜度中作權衡,還有就是針對算法的特性進行優化,能夠參考算法設計,若是算法具備分治、動態規劃這些算法的特性,那麼此類算法能夠採用併發機制提升算法的性能(算法設計很複雜,算法自己涉及到的不少高等數學的知識,還有就是算法的實現是否更加符合計算機的運行機制,建議多看看ACM算法設計相關書籍)若是想學習Java工程化、高性能及分佈式、深刻淺出。性能調優、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級架構進階羣:180705916,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們