


版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、從設(shè)計(jì)方案到案例分析,詳解常見(jiàn)性能優(yōu)化策略作者:邵曉明編輯:小智“ 本文旨在形成可實(shí)踐、可借鑒、可參考的各種性能優(yōu)化的方案以及選型考慮點(diǎn),同時(shí)配合具體的真實(shí)案例,讓其他人遇到相似問(wèn)題時(shí),不用從零開(kāi)始。除性能優(yōu)化外,也提供通用的常見(jiàn)思路及方案選型的考慮點(diǎn),幫助培養(yǎng)在方案選型時(shí)的意識(shí)、思維以及做各種權(quán)衡的能力。本文轉(zhuǎn)載自美團(tuán)點(diǎn)評(píng)技術(shù)團(tuán)隊(duì)博客,已獲授權(quán)。常見(jiàn)性能優(yōu)化策略分類(lèi)代碼之所以把代碼放到第一位,是因?yàn)檫@一點(diǎn)最容易引起技術(shù)人員的忽視。很多技術(shù)人員拿到一個(gè)性能優(yōu)化的需求以后,言必稱(chēng)緩存、異步、JVM 等。實(shí)際上,第一步就應(yīng)該是分析相關(guān)的代碼,找出相應(yīng)的瓶頸,再來(lái)考慮具體的優(yōu)化策略。有一些性能問(wèn)題,
2、完全是由于代碼寫(xiě)的不合理,通過(guò)直接修改一下代碼就能解決問(wèn)題的,比如for 循環(huán)次數(shù)過(guò)多、作了很多無(wú)謂的條件判斷、相同邏輯重復(fù)多次等。數(shù)據(jù)庫(kù)數(shù)據(jù)庫(kù)的調(diào)優(yōu),總的來(lái)說(shuō)分為以下三部分: SQL 調(diào)優(yōu)這是最常用、每一個(gè)技術(shù)人員都應(yīng)該掌握基本的 SQL 調(diào)優(yōu)手段(包括方法、工具、輔助系統(tǒng)等) 。這里以 MySQL 為例,最常見(jiàn)的方式是,由自帶的慢查詢(xún)?nèi)罩净蛘唛_(kāi)源的慢查詢(xún)系統(tǒng)定位到具體的出問(wèn)題的 SQL ,然后使用 explain 、profile 等工具來(lái)逐步調(diào)優(yōu),最后經(jīng)過(guò)測(cè)試達(dá)到效果后上線。這方面的細(xì)節(jié),可以參考MySQL 索引原理及慢查詢(xún)優(yōu)化。架構(gòu)層面的調(diào)優(yōu)這一類(lèi)調(diào)優(yōu)包括讀寫(xiě)分離、多從庫(kù)負(fù)載均衡、水平
3、和垂直分庫(kù)分表等方面,一般需要的改動(dòng)較大, 但是頻率沒(méi)有 SQL 調(diào)優(yōu)高, 而且一般需要 DBA 來(lái)配合參與。那么什么時(shí)候需要做這些事情?我們可以通過(guò)內(nèi)部監(jiān)控報(bào)警系統(tǒng)(比如 Zabbix ),定期跟蹤一些指標(biāo)數(shù)據(jù)是否達(dá)到瓶頸,一旦達(dá)到瓶頸或者警戒值,就需要考慮這些事情。 通常, DBA 也會(huì)定期監(jiān)控這些指標(biāo)值。連接池調(diào)優(yōu)我們的應(yīng)用為了實(shí)現(xiàn)數(shù)據(jù)庫(kù)連接的高效獲取、對(duì)數(shù)據(jù)庫(kù)連接的限流等目的,通常會(huì)采用連接池類(lèi)的方案,即每一個(gè)應(yīng)用節(jié)點(diǎn)都管理了一個(gè)到各個(gè)數(shù)據(jù)庫(kù)的連接池。隨著業(yè)務(wù)訪問(wèn)量或者數(shù)據(jù)量的增長(zhǎng),原有的連接池參數(shù)可能不能很好地滿(mǎn)足需求,這個(gè)時(shí)候就需要結(jié)合當(dāng)前使用連接池的原理、具體的連接池監(jiān)控?cái)?shù)據(jù)和當(dāng)
4、前的業(yè)務(wù)量作一個(gè)綜合的判斷,通過(guò)反復(fù)的幾次調(diào)試得到最終的調(diào)優(yōu)參數(shù)。緩存分類(lèi)本地緩存( HashMap/ConcurrentHashMap 、 Ehcache、 Guava Cache 等),緩存服務(wù)( Redis/Tair/Memcache 等)。使用場(chǎng)景什么情況適合用緩存?考慮以下兩種場(chǎng)景:短時(shí)間內(nèi)相同數(shù)據(jù)重復(fù)查詢(xún)多次且數(shù)據(jù)更新不頻繁,這個(gè)時(shí)候可以選擇先從緩存查詢(xún),查詢(xún)不到再?gòu)臄?shù)據(jù)庫(kù)加載并回設(shè)到緩存的方式。此種場(chǎng)景較適合用單機(jī)緩存。高并發(fā)查詢(xún)熱點(diǎn)數(shù)據(jù),后端數(shù)據(jù)庫(kù)不堪重負(fù),可以用緩存來(lái)扛。選型考慮如果數(shù)據(jù)量小,并且不會(huì)頻繁地增長(zhǎng)又清空(這會(huì)導(dǎo)致頻繁地垃圾回收),那么可以選擇本地緩存。具體的話,
5、如果需要一些策略的支持(比如緩存滿(mǎn)的逐出策略),可以考慮Ehcache;如不需要,可以考慮 HashMap ;如需要考慮多線程并發(fā)的場(chǎng)景,可以考慮 ConcurentHashMap 。其他情況, 可以考慮緩存服務(wù)。目前從資源的投入度、可運(yùn)維性、是否能動(dòng)態(tài)擴(kuò)容以及配套設(shè)施來(lái)考慮,我們優(yōu)先考慮Tair。除非目前Tair 還不能支持的場(chǎng)合(比如分布式鎖、Hash 類(lèi)型的 value),我們考慮用Redis。設(shè)計(jì)關(guān)鍵點(diǎn)什么時(shí)候更新緩存?如何保障更新的可靠性和實(shí)時(shí)性?更新緩存的策略,需要具體問(wèn)題具體分析。這里以門(mén)店 POI 的緩存數(shù)據(jù)為例,來(lái)說(shuō)明一下緩存服務(wù)型的緩存更新策略是怎樣的?目前約10萬(wàn)個(gè) PO
6、I 數(shù)據(jù)采用了 Tair作為緩存服務(wù),具體更新的策略有兩個(gè):接收門(mén)店變更的消息,準(zhǔn)實(shí)時(shí)更新。給每一個(gè)POI 緩存數(shù)據(jù)設(shè)置 5 分鐘的過(guò)期時(shí)間,過(guò)期后從 DB 加載再回設(shè)到 DB 。這個(gè)策略是對(duì)第一個(gè)策略的有力補(bǔ)充,解決了手動(dòng)變更DB 不發(fā)消息、接消息更新程序臨時(shí)出錯(cuò)等問(wèn)題導(dǎo)致的第一個(gè)策略失效的問(wèn)題。通過(guò)這種雙保險(xiǎn)機(jī)制, 有效地保證了POI 緩存數(shù)據(jù)的可靠性和實(shí)時(shí)性。緩存是否會(huì)滿(mǎn),緩存滿(mǎn)了怎么辦?對(duì)于一個(gè)緩存服務(wù),理論上來(lái)說(shuō),隨著緩存數(shù)據(jù)的日益增多,在容量有限的情況下,緩存肯定有一天會(huì)滿(mǎn)的。如何應(yīng)對(duì)?給緩存服務(wù),選擇合適的緩存逐出算法,比如最常見(jiàn)的LRU 。針對(duì)當(dāng)前設(shè)置的容量,設(shè)置適當(dāng)?shù)木渲担?/p>
7、比如10G 的緩存,當(dāng)緩存數(shù)據(jù)達(dá)到 8G 的時(shí)候,就開(kāi)始發(fā)出報(bào)警,提前排查問(wèn)題或者擴(kuò)容。給一些沒(méi)有必要長(zhǎng)期保存的 key,盡量設(shè)置過(guò)期時(shí)間。緩存是否允許丟失?丟失了怎么辦?根據(jù)業(yè)務(wù)場(chǎng)景判斷,是否允許丟失。如果不允許,就需要帶持久化功能的緩存服務(wù)來(lái)支持,比如 Redis 或者 Tair。更細(xì)節(jié)的話,可以根據(jù)業(yè)務(wù)對(duì)丟失時(shí)間的容忍度,還可以選擇更具體的持久化策略,比如 Redis 的 RDB 或者 AOF 。緩存被“擊穿”問(wèn)題對(duì)于一些設(shè)置了過(guò)期時(shí)間的 key,如果這些 key 可能會(huì)在某些時(shí)間點(diǎn)被超高并發(fā)地訪問(wèn), 是一種非常 “熱點(diǎn)” 的數(shù)據(jù)。 這個(gè)時(shí)候,需要考慮另外一個(gè)問(wèn)題:緩存被“擊穿”的問(wèn)題。
8、概念:緩存在某個(gè)時(shí)間點(diǎn)過(guò)期的時(shí)候,恰好在這個(gè)時(shí)間點(diǎn)對(duì)這個(gè)Key有大量的并發(fā)請(qǐng)求過(guò)來(lái),這些請(qǐng)求發(fā)現(xiàn)緩存過(guò)期一般都會(huì)從后端 DB 加載數(shù)據(jù)并回設(shè)到緩存,這個(gè)時(shí)候大并發(fā)的請(qǐng)求可能會(huì)瞬間把后端 DB 壓垮。如何解決: 業(yè)界比較常用的做法,是使用 mutex。簡(jiǎn)單地來(lái)說(shuō),就是在緩存失效的時(shí)候(判斷拿出來(lái)的值為空) ,不是立即去 load db ,而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis 的 SETNX或者 Memcache 的 ADD )去 set 一個(gè) mutex key,當(dāng)操作返回成功時(shí),再進(jìn)行 load db 的操作并回設(shè)緩存;否則,就重試整個(gè) get 緩存的方法。類(lèi)似下面的
9、代碼:異步使用場(chǎng)景針對(duì)某些客戶(hù)端的請(qǐng)求,在服務(wù)端可能需要針對(duì)這些請(qǐng)求做一些附屬的事情,這些事情其實(shí)用戶(hù)并不關(guān)心或者用戶(hù)不需要立即拿到這些事情的處理結(jié)果,這種情況就比較適合用異步的方式處理這些事情。作用縮短接口響應(yīng)時(shí)間,使用戶(hù)的請(qǐng)求快速返回,用戶(hù)體驗(yàn)更好。避免線程長(zhǎng)時(shí)間處于運(yùn)行狀態(tài),這樣會(huì)引起服務(wù)線程池的可用線程長(zhǎng)時(shí)間不夠用,進(jìn)而引起線程池任務(wù)隊(duì)列長(zhǎng)度增大,從而阻塞更多請(qǐng)求任務(wù),使得更多請(qǐng)求得不到技術(shù)處理。線程長(zhǎng)時(shí)間處于運(yùn)行狀態(tài),可能還會(huì)引起系統(tǒng)Load 、 CPU 使用率、機(jī)器整體性能下降等一系列問(wèn)題,甚至引發(fā)雪崩。異步的思路可以在不增加機(jī)器數(shù)和CPU 數(shù)的情況下, 有效解決這個(gè)問(wèn)題。常見(jiàn)做法
10、一種做法,是額外開(kāi)辟線程,這里可以采用額外開(kāi)辟一個(gè)線程或者使用線程池的做法,在IO 線程(處理請(qǐng)求響應(yīng))之外的線程來(lái)處理相應(yīng)的任務(wù),在 IO 線程中讓 response先返回。如果異步線程處理的任務(wù)設(shè)計(jì)的數(shù)據(jù)量非常巨大,那么可以引入阻塞隊(duì)列 BlockingQueue 作進(jìn)一步的優(yōu)化。具體做法是讓一批異步線程不斷地往阻塞隊(duì)列里扔數(shù)據(jù),然后額外起一個(gè)處理線程,循環(huán)批量從隊(duì)列里拿預(yù)設(shè)大小的一批數(shù)據(jù),來(lái)進(jìn)行批處理(比如發(fā)一個(gè)批量的遠(yuǎn)程服務(wù)請(qǐng)求) ,這樣進(jìn)一步提高了性能。 另一種做法, 是使用消息隊(duì)列 ( MQ )中間件服務(wù), MQ 天生就是異步的。一些額外的任務(wù),可能不需要我這個(gè)系統(tǒng)來(lái)處理,但是需要
11、其他系統(tǒng)來(lái)處理。這個(gè)時(shí)候可以先把它封裝成一個(gè)消息,扔到消息隊(duì)列里面,通過(guò)消息中間件的可靠性保證把消息投遞到關(guān)心它的系統(tǒng),然后讓這個(gè)系統(tǒng)來(lái)做相應(yīng)的處理。比如 C 端在完成一個(gè)提單動(dòng)作以后,可能需要其它端做一系列的事情,但是這些事情的結(jié)果不會(huì)立刻對(duì)C 端用戶(hù)產(chǎn)生影響, 那么就可以先把C 端下單的請(qǐng)求響應(yīng)先返回給用戶(hù),返回之前往MQ 中發(fā)一個(gè)消息即可。而且這些事情理應(yīng)不是C 端的負(fù)責(zé)范圍,所以這個(gè)時(shí)候用 MQ 的方式,來(lái)解決這個(gè)問(wèn)題最合適。NoSQL 和緩存的區(qū)別先說(shuō)明一下,這里介紹的和緩存那一節(jié)不一樣,雖然可能會(huì)使用一樣的數(shù)據(jù)存儲(chǔ)方案(比如Redis 或者 Tair),但是使用的方式不一樣,這一節(jié)
12、介紹的是把它作為DB 來(lái)用。如果當(dāng)作 DB 來(lái)用,需要有效保證數(shù)據(jù)存儲(chǔ)方案的可用性、可靠性。使用場(chǎng)景需要結(jié)合具體的業(yè)務(wù)場(chǎng)景,看這塊業(yè)務(wù)涉及的數(shù)據(jù)是否適合用 NoSQL 來(lái)存儲(chǔ),對(duì)數(shù)據(jù)的操作方式是否適合用 NoSQL 的方式來(lái)操作, 或者是否需要用到 NoSQL 的一些額外特性(比如原子加減等) 。如果業(yè)務(wù)數(shù)據(jù)不需要和其他數(shù)據(jù)作關(guān)聯(lián),不需要事務(wù)或者外鍵之類(lèi)的支持,而且有可能寫(xiě)入會(huì)異常頻繁, 這個(gè)時(shí)候就比較適合用 NoSQL(比如HBase)。比如,美團(tuán)點(diǎn)評(píng)內(nèi)部有一個(gè)對(duì) exception 做的監(jiān)控系統(tǒng),如果在應(yīng)用系統(tǒng)發(fā)生嚴(yán)重故障的時(shí)候,可能會(huì)短時(shí)間產(chǎn)生大量 exception 數(shù)據(jù),這個(gè)時(shí)候如果
13、選用MySQL ,會(huì)造成 MySQL 的瞬間寫(xiě)壓力飆升,容易導(dǎo)致 MySQL 服務(wù)器的性能急劇惡化以及主從同步延遲之類(lèi)的問(wèn)題,這種場(chǎng)景就比較適合用 Hbase 類(lèi)似的 NoSQL 來(lái)存儲(chǔ)。 JVM 調(diào)優(yōu)什么時(shí)候調(diào)?通過(guò)監(jiān)控系統(tǒng)(如沒(méi)有現(xiàn)成的系統(tǒng),自己做一個(gè)簡(jiǎn)單的上報(bào)監(jiān)控的系統(tǒng)也很容易)上對(duì)一些機(jī)器關(guān)鍵指標(biāo)( gc time、gc count、各個(gè)分代的內(nèi)存大小變化、機(jī)器的Load值與CPU使用率、JVM的線程數(shù)等)的監(jiān)控報(bào)警,也可以看gc log和jstat 等命令的輸出, 再結(jié)合線上JVM 進(jìn)程服務(wù)的一些關(guān)鍵接口的性能數(shù)據(jù)和請(qǐng)求體驗(yàn),基本上就能定位出當(dāng)前的JVM 是否有問(wèn)題,以及是否需要調(diào)優(yōu)
14、。怎么調(diào)?如果發(fā)現(xiàn)高峰期CPU 使用率與 Load 值偏大,這個(gè)時(shí)候可以觀察一些 JVM 的 thread count 以及 gc count(可能主要是 young gc count ),如果這兩個(gè)值都比以往偏大(也可以和一個(gè)歷史經(jīng)驗(yàn)值作對(duì)比),基本上可以定位是young gc 頻率過(guò)高導(dǎo)致,這個(gè)時(shí)候可以通過(guò)適當(dāng)增大young 區(qū)大小或者占比的方式來(lái)解決。如果發(fā)現(xiàn)關(guān)鍵接口響應(yīng)時(shí)間很慢,可以結(jié)合gc time 以及 gc log中的 stop the world 的時(shí)間,看一下整個(gè)應(yīng)用的 stop the world 的時(shí)間是不是比較多。如果是,可能需要減少總的 gc time ,具體可以從減
15、小 gc 的次數(shù)和減小單次 gc 的時(shí)間這兩個(gè)維度來(lái)考慮,一般來(lái)說(shuō),這兩個(gè)因素是一對(duì)互斥因素,我們需要根據(jù)實(shí)際的監(jiān)控?cái)?shù)據(jù)來(lái)調(diào)整相應(yīng)的參數(shù)(比如新生代與老生代比值、 eden 與 survivor 比值、 MTT 值、觸發(fā) cms 回收的old 區(qū)比率閾值等)來(lái)達(dá)到一個(gè)最優(yōu)值。如果發(fā)生full gc 或者 old cms gc 非常頻繁,通常這種情況會(huì)誘發(fā)STW 的時(shí)間相應(yīng)加長(zhǎng),從而也會(huì)導(dǎo)致接口響應(yīng)時(shí)間變慢。這種情況,大概率是出現(xiàn)了“內(nèi)存泄露” ,Java 里的內(nèi)存泄露指的是一些應(yīng)該釋放的對(duì)象沒(méi)有被釋放掉(還有引用拉著它) 。那么這些對(duì)象是如何產(chǎn)生的呢?為啥不會(huì)釋放呢?對(duì)應(yīng)的代碼是不是出問(wèn)題了?
16、問(wèn)題的關(guān)鍵是搞明白這個(gè),找到相應(yīng)的代碼,然后對(duì)癥下藥。所以問(wèn)題的關(guān)鍵是轉(zhuǎn)化成尋找這些對(duì)象。怎么找?綜合使用jmap 和 MAT ,基本就能定位到具體的代碼。多線程與分布式使用場(chǎng)景離線任務(wù)、異步任務(wù)、 大數(shù)據(jù)任務(wù)、耗時(shí)較長(zhǎng)任務(wù)的運(yùn)行* ,適當(dāng)?shù)乩?,可達(dá)到加速的效果。注意:線上對(duì)響應(yīng)時(shí)間要求較高的場(chǎng)合,盡量少用多線程,尤其是服務(wù)線程需要等待任務(wù)線程的場(chǎng)合(很多重大事故就是和這個(gè)息息相關(guān)) ,如果一定要用,可以對(duì)服務(wù)線程設(shè)置一個(gè)最大等待時(shí)間。常見(jiàn)做法如果單機(jī)的處理能力可以滿(mǎn)足實(shí)際業(yè)務(wù)的需求,那么盡可能地使用單機(jī)多線程的處理方式,減少?gòu)?fù)雜性;反之,則需要使用多機(jī)多線程的方式。對(duì)于單機(jī)多線程,可以引入
17、線程池的機(jī)制,作用有二:提高性能,節(jié)省線程創(chuàng)建和銷(xiāo)毀的開(kāi)銷(xiāo)限流,給線程池一個(gè)固定的容量,達(dá)到這個(gè)容量值后再有任務(wù)進(jìn)來(lái),就進(jìn)入隊(duì)列進(jìn)行排隊(duì),保障機(jī)器極限壓力下的穩(wěn)定處理能力在使用 JDK 自帶的線程池時(shí),一定要仔細(xì)理解構(gòu)造方法的各個(gè)參數(shù)的含義,如core pool size、 max pool size、 keepAliveTime 、 worker queue等,在理解的基礎(chǔ)上通過(guò)不斷地測(cè)試調(diào)整這些參數(shù)值達(dá)到最優(yōu)效果。如果單機(jī)的處理能力不能滿(mǎn)足需求,這個(gè)時(shí)候需要使用多機(jī)多線程的方式。這個(gè)時(shí)候就需要一些分布式系統(tǒng)的知識(shí)了。首先就必須引入一個(gè)單獨(dú)的節(jié)點(diǎn),作為調(diào)度器,其他的機(jī)器節(jié)點(diǎn)都作為執(zhí)行器節(jié)點(diǎn)。
18、調(diào)度器來(lái)負(fù)責(zé)拆分任務(wù),和分發(fā)任務(wù)到合適的執(zhí)行器節(jié)點(diǎn);執(zhí)行器節(jié)點(diǎn)按照多線程的方式(也可能是單線程)來(lái)執(zhí)行任務(wù)。這個(gè)時(shí)候,我們整個(gè)任務(wù)系統(tǒng)就由單擊演變成一個(gè)集群的系統(tǒng),而且不同的機(jī)器節(jié)點(diǎn)有不同的角色,各司其職,各個(gè)節(jié)點(diǎn)之間還有交互。這個(gè)時(shí)候除了有多線程、線程池等機(jī)制,像 RPC、心跳等網(wǎng)絡(luò)通信調(diào)用的機(jī)制也不可少。后續(xù)我會(huì)出一個(gè)簡(jiǎn)單的分布式調(diào)度運(yùn)行的框架。度量系統(tǒng)(監(jiān)控、報(bào)警、服務(wù)依賴(lài)管理)嚴(yán)格來(lái)說(shuō),度量系統(tǒng)不屬于性能優(yōu)化的范疇,但是這方面和性能優(yōu)化息息相關(guān),可以說(shuō)為性能優(yōu)化提供一個(gè)強(qiáng)有力的數(shù)據(jù)參考和支撐。沒(méi)有度量系統(tǒng),基本上就沒(méi)有辦法定位到系統(tǒng)的問(wèn)題,也沒(méi)有辦法有效衡量?jī)?yōu)化后的效果。很多人不重視這
19、方面,但我認(rèn)為它是系統(tǒng)穩(wěn)定性和性能保障的基石。關(guān)鍵流程如果要設(shè)計(jì)這套系統(tǒng),總體來(lái)說(shuō)有哪些關(guān)鍵流程需要設(shè)計(jì)呢?確定指標(biāo)采集數(shù)據(jù)計(jì)算數(shù)據(jù),存儲(chǔ)結(jié)果展現(xiàn)和分析需要監(jiān)控和報(bào)警哪些指標(biāo)數(shù)據(jù)?需要關(guān)注哪些?按照需求出發(fā),主要需要二方面的指標(biāo):接口性能相關(guān),包括單個(gè)接口和全部的 QPS、響應(yīng)時(shí)間、 調(diào)用量(統(tǒng)計(jì)時(shí)間維度越細(xì)越好;最好是,既能以節(jié)點(diǎn)為維度,也可以以服務(wù)集群為維度,來(lái)查看相關(guān)數(shù)據(jù)) 。其中還涉及到服務(wù)依賴(lài)關(guān)系的管理,這個(gè)時(shí)候需要用到服務(wù)依賴(lài)管理系統(tǒng)單個(gè)機(jī)器節(jié)點(diǎn)相關(guān),包括CPU 使用率、 Load 值、內(nèi)存占用率、網(wǎng)卡流量等。如果節(jié)點(diǎn)是一些特殊類(lèi)型的服務(wù)(比如MySQL 、 Redis、Tair)
20、,還可以監(jiān)控這些服務(wù)特有的一些關(guān)鍵指標(biāo)。數(shù)據(jù)采集方式通常采用異步上報(bào)的方式,具體做法有兩種:第一種,發(fā)到本地的 Flume 端口,由Flume 進(jìn)程收集到遠(yuǎn)程的Hadoop 集群或者 Storm 集群來(lái)進(jìn)行運(yùn)算; 第二種,直接在本地運(yùn)算好以后,使用異步和本地隊(duì)列的方式,發(fā)送到監(jiān)控服務(wù)器。數(shù)據(jù)計(jì)算可以采用離線運(yùn)算 ( MapReduce/Hive )或者實(shí)時(shí) /準(zhǔn)實(shí)時(shí)運(yùn)算(Storm/Spark)的方式,運(yùn)算后的結(jié)果存入 MySQL 或者HBase;某些情況,也可以不計(jì)算,直接采集發(fā)往監(jiān)控服務(wù)器。展現(xiàn)和分析提供統(tǒng)一的展現(xiàn)分析平臺(tái),需要帶報(bào)表(列表/圖表)監(jiān)控和報(bào)警的功能。真實(shí)案例分析案例一:商家
21、與控制區(qū)關(guān)系的刷新 job 背景這是一個(gè)每小時(shí)定期運(yùn)行一次的job,作用是用來(lái)刷新商家與控制區(qū)的關(guān)系。具體規(guī)則就是根據(jù)商家的配送范圍(多個(gè))與控制區(qū)是否有交集,如果有交集,就把這個(gè)商家劃到這個(gè)控制區(qū)的范圍內(nèi)。業(yè)務(wù)需求需要這個(gè)過(guò)程越短越好,最好保持在20 分鐘內(nèi)。優(yōu)化過(guò)程原有代碼的主要處理流程是:拿到所有門(mén)店的配送范圍列表和控制區(qū)列表。遍歷控制區(qū)列表,針對(duì)每一個(gè)控制區(qū):遍歷商家的配送范圍列表,找到和這個(gè)控制區(qū)相交的配送范圍列表。遍歷上述商家配送范圍列表,對(duì)里面的商家ID 去重,保存到一個(gè)集合里。批量根據(jù)上述商家ID 集合,取到對(duì)應(yīng)的商家集合。遍歷上述商家集合,從中拿到每一個(gè)商家對(duì)象,進(jìn)行相應(yīng)的處
22、理(根據(jù)是否已是熱門(mén)商家、自營(yíng)、在線支付等條件來(lái)判斷是否需要插入或者更新之前的商家和控制區(qū)的關(guān)系)。刪除這個(gè)控制區(qū)當(dāng)前已有的,但是不應(yīng)該存在的商家關(guān)系列表。分析代碼,發(fā)現(xiàn)第2 步的 a 步驟和 b 步驟,找出和某控制區(qū)相交的配送范圍集合并對(duì)商家ID 去重,可以采用 R 樹(shù)空間索引的方式來(lái)優(yōu)化。具體做法是:任務(wù)開(kāi)始先更新 R 樹(shù),然后利用 R 樹(shù)的結(jié)構(gòu)和匹配算法來(lái)拿到和控制區(qū)相交的配送范圍ID 列表。再批量根據(jù)配送范圍ID 列表,拿到配送范圍列表。然后針對(duì)這一批配送范圍列表(數(shù)量很?。?,用原始多邊形相交匹配的方法做進(jìn)一步過(guò)濾,并且對(duì)過(guò)濾后的商家ID 去重。這個(gè)優(yōu)化已經(jīng)在第一期優(yōu)化中上線,整個(gè)過(guò)程
23、耗時(shí)由40 多分鐘縮短到20 分鐘以?xún)?nèi)。第一期優(yōu)化改為 R 樹(shù)以后,運(yùn)行了一段時(shí)間,隨著數(shù)據(jù)量增大,性能又開(kāi)始逐漸惡化,一個(gè)月后已經(jīng)惡化到50 多分鐘。于是繼續(xù)深入代碼分析, 尋找了兩個(gè)優(yōu)化點(diǎn), 安排第二期優(yōu)化并上線。這兩個(gè)優(yōu)化點(diǎn)是:第 2 步的 c 步驟,原來(lái)是根據(jù)門(mén)店 ID 列表從 DB 批量獲取門(mén)店, 現(xiàn)在可以改成 mget 的方式從緩存批量獲取(此時(shí)商家數(shù)據(jù)已被緩存) ;第 2 步的 d 步驟,根據(jù)是否已是熱門(mén)商家、自營(yíng)、在線支付等條件來(lái)判斷是否需要插入或者更新之前的商家和控制區(qū)的關(guān)系。上線后效果通過(guò)日志觀察,執(zhí)行時(shí)間由 50 多分鐘縮短到 15 分鐘以?xún)?nèi),下圖是截取了一天的 4 臺(tái)機(jī)
24、器的日志時(shí)間(單位:毫秒) :可以看到,效果還是非常明顯的。案例二: POI 緩存設(shè)計(jì)與實(shí)現(xiàn)背景2014 年 Q4,數(shù)據(jù)庫(kù)中關(guān)于 POI (這里可以簡(jiǎn)單理解為外賣(mài)的門(mén)店)相關(guān)的數(shù)據(jù)的讀流量急劇上升,雖然說(shuō)加入從庫(kù)節(jié)點(diǎn)可以解決一部分問(wèn)題,但是畢竟節(jié)點(diǎn)的增加是會(huì)達(dá)到極限的,達(dá)到極限后主從復(fù)制會(huì)達(dá)到瓶頸,可能會(huì)造成數(shù)據(jù)不一致。所以此時(shí),急需引入一種新的技術(shù)方案來(lái)分擔(dān)數(shù)據(jù)庫(kù)的壓力,降低數(shù)據(jù)庫(kù)POI 相關(guān)數(shù)據(jù)的讀流量。 另外,任何場(chǎng)景都考慮加DB 從庫(kù)的做法,會(huì)對(duì)資源造成一定的浪費(fèi)。實(shí)現(xiàn)方案基于已有的經(jīng)過(guò)考驗(yàn)的技術(shù)方案,我選擇Tair 來(lái)作為緩存的存儲(chǔ)方案,來(lái)幫DB 分擔(dān)來(lái)自于各應(yīng)用端的POI 數(shù)據(jù)的讀
25、流量的壓力。理由主要是從可用性、高性能、可擴(kuò)展性、是否經(jīng)過(guò)線上大規(guī)模數(shù)據(jù)和高并發(fā)流量的考驗(yàn)、是否有專(zhuān)業(yè)運(yùn)維團(tuán)隊(duì)、是否有成熟工具等幾個(gè)方面綜合考量決定。詳細(xì)設(shè)計(jì)第一版設(shè)計(jì)緩存的更新策略,根據(jù)業(yè)務(wù)的特點(diǎn)、已有的技術(shù)方案和實(shí)現(xiàn)成本,選擇了用 MQ 來(lái)接收 POI 改變的消息來(lái)觸發(fā)緩存的更新,但是這個(gè)過(guò)程有可能失?。煌瑫r(shí)啟用了 key 的過(guò)期策略,并且調(diào)用端會(huì)先判斷是否過(guò)期,如過(guò)期,會(huì)從后端 DB 加載數(shù)據(jù)并回設(shè)到緩存,再返回。通過(guò)兩個(gè)方面雙保險(xiǎn)確保了緩存數(shù)據(jù)的可用。第二版設(shè)計(jì)第一版設(shè)計(jì)運(yùn)行到一段時(shí)間以后,我們發(fā)現(xiàn)了兩個(gè)問(wèn)題:某些情況下不能保證數(shù)據(jù)的實(shí)時(shí)一致(比如技術(shù)人員手動(dòng)改動(dòng) DB 數(shù)據(jù)、利用 M
26、Q 更新緩存失?。?,這個(gè)時(shí)候只能等待 5 分鐘的過(guò)期時(shí)間,有的業(yè)務(wù)是不允許的。加入了過(guò)期時(shí)間導(dǎo)致另外一個(gè)問(wèn)題: Tair 在緩存不命中的那一刻,會(huì)嘗試從硬盤(pán)中 Load 數(shù)據(jù),如果硬盤(pán)沒(méi)有再去 DB中 Load 數(shù)據(jù)。這無(wú)疑會(huì)進(jìn)一步延長(zhǎng)Tair 的響應(yīng)時(shí)間,這樣不僅使得業(yè)務(wù)的超時(shí)比率加大, 而且會(huì)導(dǎo)致 Tair 的性能進(jìn)一步變差。為了解決上述問(wèn)題,我們從美團(tuán)點(diǎn)評(píng)負(fù)責(zé)基礎(chǔ)架構(gòu)的同事那里了解到 Databus 可以解決緩存數(shù)據(jù)在某些情況下不一致的問(wèn)題,并且可以去掉過(guò)期時(shí)間機(jī)制,從而提高查詢(xún)效率,避免 tair 在內(nèi)存不命中時(shí)查詢(xún)硬盤(pán)。而且為了防止 DataBus 單點(diǎn)出現(xiàn)故障影響我們的業(yè)務(wù),我們
27、保留了之前接MQ 消息更新緩存的方案,作了切換開(kāi)關(guān),利用這個(gè)方案作容錯(cuò),整體架構(gòu)如下:上線后效果上線后,通過(guò)持續(xù)地監(jiān)控?cái)?shù)據(jù)發(fā)現(xiàn),隨著調(diào)用量的上升,到DB 的流量有了明顯地減少,極大地減輕了DB 的壓力。同時(shí)這些數(shù)據(jù)接口的響應(yīng)時(shí)間也有了明顯地減少。緩存更新的雙重保障機(jī)制,也基本保證了緩存數(shù)據(jù)的可用。見(jiàn)下圖:案例三:業(yè)務(wù)運(yùn)營(yíng)后臺(tái)相關(guān)頁(yè)面的性能優(yōu)化背景隨著業(yè)務(wù)的快速發(fā)展,帶來(lái)的訪問(wèn)量和數(shù)據(jù)量的急劇上升,通過(guò)我們相應(yīng)的監(jiān)控系統(tǒng)可以發(fā)現(xiàn),系統(tǒng)的某些頁(yè)面的性能開(kāi)始出現(xiàn)惡化。從用戶(hù)方的反饋,也證明了這點(diǎn)。此時(shí)此刻,有必要迅速排期,敏捷開(kāi)發(fā),對(duì)這些頁(yè)面進(jìn)行調(diào)優(yōu)。歡迎頁(yè)需求背景:歡迎頁(yè)是地推人員乃至總部各種角色人員進(jìn)入外賣(mài)運(yùn)營(yíng)后臺(tái)的首頁(yè),會(huì)顯示地推人員最想看到最關(guān)心的一些核心數(shù)據(jù),其重要性不言而喻,所以該頁(yè)面的性能惡化會(huì)嚴(yán)重影響到用戶(hù)體驗(yàn)。因此,首先需要優(yōu)化的就是歡迎頁(yè)。通過(guò)相應(yīng)定位和分析,發(fā)現(xiàn)導(dǎo)致性能惡化的主要原因有兩個(gè):數(shù)據(jù)接口層和計(jì)算展現(xiàn)層。解決方案:對(duì)癥下藥,分而治之。經(jīng)過(guò)仔細(xì)排查、分析定
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 微特電機(jī)在高精度伺服系統(tǒng)中的應(yīng)用考核試卷
- 有機(jī)合成原料在綠色建筑材料的創(chuàng)新開(kāi)發(fā)趨勢(shì)預(yù)測(cè)分析預(yù)測(cè)考核試卷
- 冷凍飲品企業(yè)的品牌維權(quán)與法律事務(wù)考核試卷
- 木質(zhì)素在土壤改良劑中的作用考核試卷
- 外貿(mào)生鮮類(lèi)合同范本
- 梁板安裝合同范本
- 檔案提成合同范本
- 外墻水性氟碳漆合同范本
- 金融門(mén)面轉(zhuǎn)讓合同范本
- 水管改造施工合同
- 初中中考語(yǔ)文記敘文閱讀訓(xùn)練訓(xùn)練及答案
- 圍手術(shù)期高血壓患者管理專(zhuān)家共識(shí)
- 中國(guó)城市人口排名表
- 人教版六年級(jí)下冊(cè)數(shù)學(xué)(全冊(cè))同步隨堂練習(xí)一課一練
- GB/T 2573-2008玻璃纖維增強(qiáng)塑料老化性能試驗(yàn)方法
- GB/T 1265-2003化學(xué)試劑溴化鈉
- 工程建設(shè)項(xiàng)目管理培訓(xùn)教材課件
- 11-化學(xué)動(dòng)力學(xué)基礎(chǔ)-2-考研試題資料系列
- 《簡(jiǎn)愛(ài)》課本劇劇本
- 社區(qū)獲得性肺炎臨床路徑
評(píng)論
0/150
提交評(píng)論