融云展位現(xiàn)場(chǎng)溝通
18日上午,融云首席架構(gòu)師李淼為大家分享了《超大規(guī)模即時(shí)通訊系統(tǒng)性能優(yōu)化探索及實(shí)踐》主題演講,就龐大復(fù)雜的系統(tǒng)性能問(wèn)題該如何定位、分析以及工具排查;高并發(fā)系統(tǒng)的技術(shù)要點(diǎn)、難點(diǎn)、重點(diǎn)把控及措施、技巧;特定場(chǎng)景下系統(tǒng)性能問(wèn)題優(yōu)化可行性解決方案等內(nèi)容進(jìn)入深度解析。雖然臨近午飯時(shí)間,但大量的技術(shù)干貨及精彩的案例分享,讓現(xiàn)場(chǎng)一度爆滿,很多嘉賓即使站著也一直堅(jiān)持聽(tīng)完整場(chǎng)演講;即便會(huì)議結(jié)束,還有很多人與李淼進(jìn)一步交流。
融云首席架構(gòu)師李淼演講
火爆的演講現(xiàn)場(chǎng)
會(huì)議結(jié)束后參會(huì)嘉賓與李淼繼續(xù)溝通
以下為演講實(shí)錄摘要,希望在適用場(chǎng)景下,對(duì)開(kāi)發(fā)者有所脾益。
各位好,臨近中午了,感謝還有這么多同學(xué)和我一起分享。今天的主題是超大規(guī)模即時(shí)通訊系統(tǒng)性能優(yōu)化探索及實(shí)踐,介紹即時(shí)通訊模式下性能優(yōu)化如何完成。通過(guò)今天介紹的模型,大家如果有所得的話可以在系統(tǒng)當(dāng)中做一些應(yīng)用實(shí)踐。
性能問(wèn)題定位及關(guān)注點(diǎn)
首先說(shuō)性能問(wèn)題的關(guān)注點(diǎn),對(duì)于程序首先最直觀的關(guān)注點(diǎn)就是程序的響應(yīng)時(shí)長(zhǎng)。前提是響應(yīng)包括你的應(yīng)答必須是正確的,如果說(shuō)性能優(yōu)化完成之后結(jié)果不正確,那可以說(shuō)整個(gè)優(yōu)化失敗。
除了程序響應(yīng)時(shí)長(zhǎng)以外我們還會(huì)關(guān)注系統(tǒng)、數(shù)據(jù)存儲(chǔ)以及數(shù)據(jù)通訊。系統(tǒng)有一些直觀指標(biāo)可以衡量系統(tǒng)的健康性和系統(tǒng)性能。先說(shuō)CPU,我們主要關(guān)注CPU的負(fù)載及使用率;接下來(lái)是內(nèi)存,內(nèi)存主要關(guān)注正常的內(nèi)存利用率,是否使用了虛擬內(nèi)存,以及內(nèi)存碎片問(wèn)題;I/O問(wèn)題則關(guān)注磁盤和網(wǎng)絡(luò)I/O問(wèn)題,I/O是整個(gè)系統(tǒng)優(yōu)化過(guò)程中特別需要關(guān)注的點(diǎn),I/O如果做的好,對(duì)于整個(gè)平臺(tái)的性能提升幫助是最大的,有可能會(huì)比前面的CPU和內(nèi)存還要大。
數(shù)據(jù)存儲(chǔ)方面,在即時(shí)通訊保證消息可靠性的情況下,優(yōu)先進(jìn)行消息存儲(chǔ),通過(guò)這種方式保證消息不丟失、不亂序、不重復(fù)。對(duì)于數(shù)據(jù)存儲(chǔ)而言,其實(shí)和I/O有點(diǎn)類似,對(duì)于一般的業(yè)務(wù)來(lái)講,如果數(shù)據(jù)存儲(chǔ)優(yōu)化的好,平臺(tái)優(yōu)化方面就完成了60%左右的工作。
一般做系統(tǒng)時(shí)都會(huì)遇到網(wǎng)絡(luò)相關(guān)問(wèn)題,這就會(huì)涉及到網(wǎng)絡(luò)通訊問(wèn)題,怎么想辦法降低你的數(shù)據(jù)傳輸量,或者說(shuō)降低你和網(wǎng)絡(luò)之間的交互次數(shù),也是數(shù)據(jù)通訊里面需要完成的一個(gè)優(yōu)化。
下面通過(guò)三個(gè)階段介紹一下融云關(guān)于性能問(wèn)題的定位。第一個(gè)階段融云剛剛成立,那個(gè)時(shí)候性能問(wèn)題的定位主要是通過(guò)系統(tǒng)監(jiān)控,配合著系統(tǒng)日志以及診斷工具,主要監(jiān)控服務(wù)器里面的CPU、內(nèi)存及I/O指標(biāo)。
對(duì)于監(jiān)控來(lái)講,我們有一個(gè)類似業(yè)務(wù)監(jiān)控系統(tǒng),定時(shí)對(duì)每個(gè)節(jié)點(diǎn)進(jìn)行相關(guān)性的單元測(cè)試,以此來(lái)衡量當(dāng)前服務(wù)的健康狀況,以及每個(gè)系統(tǒng)的響應(yīng)速度。當(dāng)線上出現(xiàn)了系統(tǒng)告警時(shí),配合日志來(lái)查看業(yè)務(wù)是否正常。
第二個(gè)階段,我們嘗試過(guò)用一些開(kāi)源的APM工具。在整個(gè)系統(tǒng)當(dāng)中通訊模型是基于Actor模型做的,所以沒(méi)辦法整個(gè)構(gòu)建服務(wù)監(jiān)控網(wǎng)絡(luò),只能看一些相關(guān)數(shù)據(jù)。但在座各位如果開(kāi)發(fā)系統(tǒng),用APM是一個(gè)非常好的工具,可以幫助你進(jìn)行服務(wù)治理,系統(tǒng)監(jiān)控相關(guān)的工作,同時(shí)APM也有很多商業(yè)解決方案。
第三個(gè)階段,我們?cè)趯?duì)APM調(diào)研以及試用出現(xiàn)問(wèn)題之后,只能想辦法自研Monitor監(jiān)控系統(tǒng),我們會(huì)記錄每個(gè)信令的調(diào)用時(shí)間和調(diào)用鏈路,后臺(tái)有一個(gè)數(shù)據(jù)分析平臺(tái),我們查看一些信令前一天和今天的比值,看是不是有幅度變化;同時(shí)我們也會(huì)配合業(yè)務(wù)數(shù)據(jù)量觀測(cè)數(shù)據(jù)。一旦某個(gè)信令出現(xiàn)異常,我們就會(huì)進(jìn)行線上的服務(wù)排查。
實(shí)際上對(duì)于性能問(wèn)題的定位來(lái)講,第一個(gè)階段是最有效的,后面的手段都是輔助研發(fā)人員對(duì)于線上問(wèn)題的定位,這些都是相輔相成的:你判斷問(wèn)題、定位問(wèn)題需要工具,工具也可以提高你判斷問(wèn)題、定位問(wèn)題的速度。
高并發(fā)系統(tǒng)技術(shù)要點(diǎn)
對(duì)于高并發(fā)系統(tǒng)來(lái)講,其實(shí)技術(shù)要點(diǎn)很多,我羅列了四條:異步通訊、緩存策略、數(shù)據(jù)結(jié)構(gòu)及算法、數(shù)據(jù)存儲(chǔ)。對(duì)于性能優(yōu)化來(lái)講,這四點(diǎn)僅僅是一部分,但如果把這四點(diǎn)做好,平臺(tái)就能得到一個(gè)很大的提升。
首先是異步通訊,對(duì)于現(xiàn)在的分布式系統(tǒng)來(lái)講,都需要對(duì)服務(wù)進(jìn)行拆分,服務(wù)拆分以后我們需要通過(guò)一種方式將服務(wù)串聯(lián)起來(lái),現(xiàn)在有很多開(kāi)源的解決方案或框架,但是對(duì)于RPC來(lái)講,一般都是同步調(diào)用,有點(diǎn)類似于訪問(wèn)數(shù)據(jù)庫(kù),當(dāng)前的工作線程需要等待調(diào)用端反饋結(jié)果。
如果說(shuō)某個(gè)服務(wù)的響應(yīng)時(shí)長(zhǎng)十毫秒,對(duì)于調(diào)用端來(lái)講就需要等待十毫秒,為了解決這個(gè)問(wèn)題,現(xiàn)在很多RPC都支持異步RPC的方式,通過(guò)回調(diào)的方式解決同步RPC工作線程占用以及等待的問(wèn)題。
最后一個(gè)是Actor模型,Actor模型實(shí)際上在整個(gè)軟件系統(tǒng)上是一個(gè)屬于多線程數(shù)據(jù)協(xié)調(diào)的模型。所有的請(qǐng)求以及返回結(jié)果會(huì)以消息的方式進(jìn)行傳遞,融云也是使用了Actor模式作為服務(wù)間調(diào)用。
第二個(gè)是緩存策略,我們對(duì)于數(shù)據(jù)分為四層:首先是原始數(shù)據(jù),這個(gè)數(shù)據(jù)是保存在數(shù)據(jù)庫(kù)里面的;第二個(gè)是分布式緩存,對(duì)于很多無(wú)狀態(tài)的服務(wù)而言,性能優(yōu)化大部分依賴于分布式緩存來(lái)完成;第三個(gè)為了對(duì)數(shù)據(jù)訪問(wèn)進(jìn)行加速,可能會(huì)使用一些本地進(jìn)程內(nèi)緩存,由于沒(méi)有網(wǎng)絡(luò)訪問(wèn),同時(shí)直接的內(nèi)存訪問(wèn)速度更快,所以本地緩存策略也會(huì)作為服務(wù)加速的方式;最后就是客戶端緩存了,現(xiàn)在無(wú)論是App開(kāi)發(fā),PC客戶開(kāi)發(fā)都可以使用用戶側(cè)的數(shù)據(jù)存儲(chǔ),Web上的H5也可以使用類似local storage解決方案,但是一旦使用了客戶端存儲(chǔ),我們就需要設(shè)計(jì)一個(gè)健壯的數(shù)據(jù)同步模型。刨除客戶端緩存的問(wèn)題,為了盡可能達(dá)到使熱數(shù)據(jù)離用戶近一些這個(gè)目的,我們就需要想盡一切辦法提高緩存的命中率。
第三個(gè)是數(shù)據(jù)結(jié)構(gòu)及算法,適合場(chǎng)景的高效數(shù)據(jù)結(jié)構(gòu),首先我們要明確一個(gè)事情,適合的場(chǎng)景一定要對(duì)整個(gè)系統(tǒng)以及業(yè)務(wù)有充分的了解,根據(jù)這個(gè)方式再選擇合適的數(shù)據(jù)結(jié)構(gòu)。有的時(shí)候我們需要在時(shí)間復(fù)雜度和空間復(fù)雜度之間做權(quán)衡,什么時(shí)候拿空間換時(shí)間,什么時(shí)候拿時(shí)間換空間。另外就是算法,在開(kāi)發(fā)過(guò)程當(dāng)中,一定要明確算法的時(shí)間復(fù)雜度。由于系統(tǒng)里的需求,你需要提高算法復(fù)雜度,這個(gè)時(shí)候開(kāi)發(fā)人員要和產(chǎn)品人員進(jìn)行協(xié)調(diào)溝通。算法復(fù)雜度太高時(shí),就要想辦法優(yōu)化業(yè)務(wù),甚至說(shuō)優(yōu)化場(chǎng)景。
第四數(shù)據(jù)存儲(chǔ),我們依然要提場(chǎng)景的問(wèn)題。對(duì)于一般系統(tǒng)開(kāi)發(fā)來(lái)講,一個(gè)關(guān)系型數(shù)據(jù)庫(kù)基本上就可以滿足業(yè)務(wù)需求開(kāi)發(fā)了,但實(shí)際上如果僅僅通過(guò)關(guān)系型數(shù)據(jù)庫(kù)來(lái)做的話,即使能滿足業(yè)務(wù)需求也不一定可以滿足性能需求。所以說(shuō)要熟知你的業(yè)務(wù)場(chǎng)景,根據(jù)業(yè)務(wù)場(chǎng)景選擇合適的數(shù)據(jù)存儲(chǔ)。除此之外,還需要了解這些存儲(chǔ)的原理。
性能優(yōu)化案例
下面分享一下融云做的優(yōu)化案例,融云系統(tǒng)上線過(guò)程當(dāng)中沒(méi)有出現(xiàn)太多的性能問(wèn)題,實(shí)際上我們更多處理的是線上的BUG,或者說(shuō)由于一些低級(jí)失誤產(chǎn)生的故障。
首先第一個(gè)案例,字典樹(shù)在我們優(yōu)化之后變成了雙數(shù)組字典樹(shù),場(chǎng)景主要應(yīng)用于敏感詞過(guò)濾。當(dāng)時(shí)我們字典樹(shù)的實(shí)現(xiàn)都是以哈希多叉樹(shù)來(lái)做的,有幾個(gè)考慮:第一,敏感詞添加過(guò)程當(dāng)中不需要字典樹(shù)重建,另外算法復(fù)雜度很低。有次通過(guò)監(jiān)控,我們發(fā)了線上用于審核的系統(tǒng)出現(xiàn)了一些性能問(wèn)題,排查后發(fā)現(xiàn)有大量用戶錄入了很多業(yè)務(wù)上的關(guān)鍵敏感詞,這時(shí)我們將哈希樹(shù)調(diào)整為了雙數(shù)組字典樹(shù),場(chǎng)景我們也做了一些優(yōu)化,敏感詞讓用戶進(jìn)行批量添加,防止每次都會(huì)重構(gòu)。另外就是延遲,我們降低了字典樹(shù)重構(gòu)的時(shí)間。最后,對(duì)于審核服務(wù)來(lái)講,優(yōu)化效果直接將CPU的使用率降低了30%。
另外一個(gè)就是跳表,轉(zhuǎn)換成環(huán)形隊(duì)列,場(chǎng)景是做一些消息存儲(chǔ)。消息有一個(gè)時(shí)間遞增的特性,每個(gè)消息都會(huì)有一個(gè)時(shí)間遞增的方式,用于跳表方式來(lái)講復(fù)雜度很低,同時(shí)可以進(jìn)行定向掃描,但是由于我們需要做內(nèi)存保護(hù),要對(duì)跳表進(jìn)行流量控制,插入的過(guò)程當(dāng)中需要對(duì)老數(shù)據(jù)進(jìn)行淘汰,這時(shí)就需要一個(gè)特別大的鎖把內(nèi)存鎖住,保證線程安全和防止內(nèi)存溢出。但由于業(yè)務(wù)量不斷增大,我們換了一個(gè)思路,使用環(huán)形隊(duì)列,主要底線實(shí)現(xiàn)都是以數(shù)組的方式組織,同時(shí)改變之前對(duì)于消息的定位模式。之前是通過(guò)一個(gè)用戶請(qǐng)求的時(shí)間點(diǎn)開(kāi)始往后獲取最新數(shù)據(jù),改變模式之后我們通過(guò)最新的數(shù)據(jù)往前進(jìn)行迭代,查到時(shí)間點(diǎn)為止,通過(guò)這樣的方式整個(gè)降低了占用時(shí)間,同時(shí)針對(duì)這塊業(yè)務(wù)吞吐量大概提高了百分之百。
性能優(yōu)化案例內(nèi)存優(yōu)化篇。這個(gè)場(chǎng)景對(duì)于key縮短問(wèn)題,對(duì)于系統(tǒng)當(dāng)中的用戶ID本身來(lái)講長(zhǎng)度不可控。我們通過(guò)一個(gè)哈希算法轉(zhuǎn)變進(jìn)制,變成64進(jìn)制,這樣對(duì)于超過(guò)22個(gè)字節(jié)的數(shù)據(jù)進(jìn)行壓縮,最終優(yōu)化效果把內(nèi)存的利用率降低了大概10%。
第二個(gè)內(nèi)存優(yōu)化主要是LRU緩存優(yōu)化,如果有大量冷數(shù)據(jù)訪問(wèn)到系統(tǒng)中之后,會(huì)把熱數(shù)據(jù)沖掉,這對(duì)于系統(tǒng)的吞吐量有很大影響。我們優(yōu)化的方式是做了一個(gè)二級(jí)LRU緩存,將冷熱數(shù)據(jù)按照配比進(jìn)行隔離,冷數(shù)據(jù)40%,熱數(shù)據(jù)60%,這樣系統(tǒng)里熱數(shù)據(jù)被淘汰的問(wèn)題便得以緩解了。
性能優(yōu)化案例。數(shù)據(jù)狀態(tài)的延遲寫(xiě)入,這個(gè)場(chǎng)景中消息里會(huì)記錄每個(gè)用戶的狀態(tài)。如果用戶收了一千條消息,數(shù)據(jù)就要被寫(xiě)入一千次,我們通過(guò)另外一種模式,消息狀態(tài)數(shù)據(jù)一直是在本地內(nèi)存當(dāng)中進(jìn)行寫(xiě)入,待多次寫(xiě)入直到數(shù)據(jù)不活躍后,我們才將數(shù)據(jù)寫(xiě)入真實(shí)的存儲(chǔ)里。通過(guò)這種優(yōu)化,將之前的多次數(shù)據(jù)寫(xiě)入變成了一次數(shù)據(jù)寫(xiě)入。
之前監(jiān)控?cái)?shù)據(jù)每天有幾千億次需要存儲(chǔ)和寫(xiě)入,通過(guò)添加緩存區(qū),讓將監(jiān)控?cái)?shù)據(jù)傳輸量降低了兩個(gè)數(shù)量級(jí)。
數(shù)據(jù)存儲(chǔ)。首先對(duì)于消息來(lái)講,他的寫(xiě)入和讀取場(chǎng)景是比較特殊,通過(guò)自研的存儲(chǔ)引擎,將存儲(chǔ)的設(shè)備降低了一半的數(shù)據(jù)量,同時(shí)保證了整個(gè)系統(tǒng)的響應(yīng)速度。另外,調(diào)整了數(shù)據(jù)庫(kù)的業(yè)務(wù)引擎,對(duì)于業(yè)務(wù)數(shù)據(jù)占用磁盤比較高的問(wèn)題,優(yōu)化之后的結(jié)果大概只有之前的30%左右,即存儲(chǔ)降低了70%。
系統(tǒng)設(shè)計(jì)把控
系統(tǒng)設(shè)計(jì)把控是一個(gè)總結(jié)性的內(nèi)容,對(duì)于性能優(yōu)化來(lái)講首先應(yīng)該關(guān)注的是系統(tǒng)設(shè)計(jì),需要充分理解你的需求以及業(yè)務(wù)場(chǎng)景,根據(jù)業(yè)務(wù)場(chǎng)景來(lái)設(shè)計(jì)你的整個(gè)系統(tǒng),系統(tǒng)設(shè)計(jì)完成之后,我們要開(kāi)始進(jìn)行架構(gòu)設(shè)計(jì),現(xiàn)在很多人做架構(gòu)分享,例如現(xiàn)在比較火的微服務(wù)。但是這些架構(gòu)設(shè)計(jì)大家不要拿過(guò)來(lái)直接引用,需要充分的消化,通過(guò)架構(gòu)設(shè)計(jì)帶入系統(tǒng)設(shè)計(jì),進(jìn)行整個(gè)架構(gòu)的演進(jìn)和迭代。
另外,技術(shù)選型需要充分考慮團(tuán)隊(duì)對(duì)技術(shù)的接受能力,同時(shí)一定要對(duì)每個(gè)你所選東西的原理有充分認(rèn)識(shí),這樣的話才能做出一個(gè)比較好的選擇。
最后是程序?qū)崿F(xiàn),是在開(kāi)發(fā)過(guò)程當(dāng)中要不停進(jìn)行迭代、改進(jìn)和分享。技術(shù)沒(méi)有好壞之分,只有適合你的場(chǎng)景才是最好的。謝謝大家!