版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
整理?MYSQLo索引?索引原理?B-Tree索引o所有的值都是按順序存儲(chǔ),每一個(gè)葉子頁到根的距離相同?Hash索引o只有精確匹配所有的列查詢才會(huì)有效?如何查創(chuàng)建高性能索引?查詢優(yōu)化?緩存原理o四大特性?原子性?事務(wù)開始后所有操作,要么全部做完,要么全部不做?一致性?事務(wù)開始前和結(jié)束后,數(shù)據(jù)庫(kù)的完整性約束沒有被破壞?隔離性?同一時(shí)間,只允許一個(gè)事務(wù)請(qǐng)求同一數(shù)據(jù),不同事務(wù)之間彼此沒有任何干擾?持久性?事務(wù)完成后,事務(wù)對(duì)數(shù)據(jù)庫(kù)的更新保存到數(shù)據(jù)庫(kù),不能回滾o事務(wù)隔離級(jí)別?讀未提交?事務(wù)可以讀取未提交的數(shù)據(jù),產(chǎn)生臟讀?不可重復(fù)讀?同一事務(wù)的其他實(shí)例在該實(shí)例處理期間可能會(huì)有新的commit,同一select可能會(huì)返回不同結(jié)果?可重復(fù)讀?mysql默認(rèn)?產(chǎn)生幻讀?串行化?JVMo垃圾回收算法?引用計(jì)數(shù)法?無法處理循環(huán)問題?每次操作時(shí)都伴隨一個(gè)加法或減法操作,影響系統(tǒng)性能?標(biāo)記清除法?標(biāo)記階段o通過根節(jié)點(diǎn),標(biāo)記從根節(jié)點(diǎn)可達(dá)的對(duì)象?清除階段o清除所有未被標(biāo)記的對(duì)象?會(huì)產(chǎn)生大量的空間碎片?復(fù)制算法?eden空間中存活的對(duì)象恢復(fù)復(fù)制到未使用的survivor空間中(假設(shè)是oo正在使用的survivor中的年輕對(duì)象也會(huì)被復(fù)制到同to空間?此時(shí)eden空間和from空間中剩余的對(duì)象就是垃圾對(duì)象?適用于新生代?標(biāo)記壓縮算法?最終效果等同于用標(biāo)記清除算法執(zhí)行完成后,再進(jìn)行一次內(nèi)存碎片整理?分代算法?是一種思想o根據(jù)垃圾回收對(duì)象的特性選擇合適的回收算法?分區(qū)算法?將整個(gè)堆空間劃分成連續(xù)不同的小區(qū)間,每一個(gè)小區(qū)間獨(dú)立使用,獨(dú)立回收o對(duì)象引用?強(qiáng)引用?程序中使用的一般引用,可觸及不會(huì)被回收?軟引用?當(dāng)堆空間不足時(shí)就會(huì)被回收?使用java.lang.ref.SoftReference類實(shí)現(xiàn)?弱引用?發(fā)現(xiàn)即回收o由于垃圾回收器通常優(yōu)先級(jí)很低,可以存在較長(zhǎng)時(shí)間?軟應(yīng)用和弱引用非常適合保存可有可無的緩存數(shù)據(jù)?虛引用?可以跟蹤對(duì)象的回收時(shí)間,可以將一些資源釋放操作放置在虛引用中o垃圾回收器?串行收集器?-XX:+UseSerialGCo新生代和老年代都使用串行收集器?并行收集器?新生代ParNewo將串行回收器多線程化o配合老年代CMS工作o-XX:+UseConcMarkSweepGC-XX:UseParNewGC?新生代ParallelGCo關(guān)注系統(tǒng)吞吐量?-XX:MaxGCPauseMillis?設(shè)置最大垃圾停頓時(shí)間?-XX:+GCTimeRatio?設(shè)置吞吐量大小?老年代ParallelOldGC回收器?CMS?關(guān)注系統(tǒng)停頓時(shí)間基于標(biāo)記清除算法?工作步驟o初始標(biāo)記o獨(dú)占資源?并發(fā)標(biāo)記?預(yù)清理?為正式清理做檢查和準(zhǔn)備,嘗試控制一次停頓時(shí)間,避免新生代GC后,立即觸發(fā)一次重新標(biāo)記,導(dǎo)致系統(tǒng)停頓時(shí)間過長(zhǎng)o重新標(biāo)記o獨(dú)占資源?并發(fā)清理?并發(fā)重置o參數(shù)設(shè)置?-XX:+UseConcMarkSweepGC?新生代使用ParNew回收器,老年代使用CMS收集器?-XX:ConcGCThreads或者-XX:parallelCMSThreads?并發(fā)線程數(shù)量?-XX:CMSInitationOccupancyFraction?老年代空間使用率達(dá)到閾值時(shí)實(shí)行CMS回收,默認(rèn)68%?-XX:UseCMSCompactAtFullCollection?垃圾回收器在垃圾收集完成后進(jìn)行一次內(nèi)存碎片整理?-XX:CMSFullGCsBeforeCompaction?多少次CMS后進(jìn)行一次內(nèi)存壓縮?G1o使用分區(qū)算法,兼顧吞吐量和停頓時(shí)間的GC實(shí)現(xiàn)o問題?region大小和大對(duì)象很難保證一致,這會(huì)導(dǎo)致空間的浪費(fèi)o工作步驟?初始標(biāo)記?根區(qū)域掃描o并發(fā)標(biāo)記?重新標(biāo)記?獨(dú)占清理o并發(fā)清理o參數(shù)設(shè)置?-XX:UseG1GC?-XX:MaxGCPauseMillis?目標(biāo)最大停頓時(shí)間?-XX:ParallelGCThreads?GC工作線程數(shù)量?對(duì)象何時(shí)進(jìn)入老年代o新創(chuàng)建的對(duì)象進(jìn)入eden區(qū)o老年對(duì)象進(jìn)入老年代?MaxTenuringThreshold(新生代最大年齡)默認(rèn)15超過則進(jìn)入老年代o大對(duì)象直接進(jìn)入老年代?PretenureSizeThreshold設(shè)置閾值況決定?常用GC參數(shù)o-XX:UseSerialGC?新生代和老年代都使用串行收集器o-XX:SurvivorRatio?設(shè)置Eden區(qū)和survivior區(qū)大小比例o-XX:PretenureSizeThreadOld?大對(duì)象進(jìn)入老年代的閾值o-XX:MaxTenuringThreshold?對(duì)象進(jìn)入老年代年齡的最大值?常用jvm虛擬機(jī)參數(shù)?性能監(jiān)控工具olinux下?top?顯示系統(tǒng)整體資源使用情況?vmstat?統(tǒng)計(jì)cpu、內(nèi)存的使用情況?pidstat工具oCPU使用率監(jiān)控oI/O使用監(jiān)控o內(nèi)存監(jiān)控oJDK性能監(jiān)控工具?jps?查看java進(jìn)程?jstat?查看虛擬機(jī)運(yùn)行時(shí)信息?jinfo?查看虛擬機(jī)參數(shù)?jmap?導(dǎo)出堆文件?jstack?導(dǎo)出線程堆棧?堆內(nèi)存分析o堆溢出?javaheapspace?-Xmx指定一個(gè)更大的堆外使用MAT等工具分析找打大量占用堆空間對(duì)象o直接內(nèi)存溢出?java.lang.OutOfMemoryError?合理的進(jìn)行FullGC?設(shè)定一個(gè)系統(tǒng)實(shí)際可達(dá)的-XX:MaxDirectMemorySize值o過多線程導(dǎo)致OOM?為支持更多的線程使用一個(gè)較小的堆空間o永久區(qū)溢出?PermGenspace?增加MaxPermSize的值?減少類的數(shù)量?使用ClassLoader合理的加載各個(gè)類,并定期回收oGC效率低下引起OOM?GCoverheadlimitexceed?class文件結(jié)構(gòu)o魔數(shù)?class文件的標(biāo)識(shí)(4字節(jié))oclass文件版本?由那個(gè)本本的編譯器編譯產(chǎn)生o常量池o類的訪問標(biāo)記o......?calss裝載系統(tǒng)o裝載流程?加載?通過類的全名獲取類的二進(jìn)制數(shù)據(jù)流?解析類的二進(jìn)制數(shù)據(jù)流為方法區(qū)內(nèi)的數(shù)據(jù)結(jié)構(gòu)?創(chuàng)建java.lang.Class類的實(shí)例,表示該類型?驗(yàn)證?格式驗(yàn)證o魔數(shù)、版本號(hào)、長(zhǎng)度檢查?語義驗(yàn)證o是否繼承final、抽象方法是否有實(shí)現(xiàn)等?字節(jié)碼驗(yàn)證o跳轉(zhuǎn)指令是否指向正確的位置?符號(hào)引用驗(yàn)證o符號(hào)引用的直接引用是否存在?準(zhǔn)備?分配相應(yīng)的內(nèi)存空間,并設(shè)置初始值?如果為final的常量會(huì)在此階段賦值?解析?將類、接口、字段、方法的符號(hào)引用轉(zhuǎn)為直接引用?初始化?主要執(zhí)行類的初始化方法<clinit>o整合static賦值語句以及static語句塊oClassLoader?主要方法?loadClasso給定一個(gè)類名,加載一個(gè)類,返回這個(gè)類的實(shí)例?如果找不到會(huì)拋出ClassNotFoundException?findClasso重載classLoader的主要擴(kuò)展點(diǎn)?定義查找類的邏輯?findLoadedClasso尋找已加載的類?分類?啟動(dòng)類加載器o由C代碼實(shí)現(xiàn),java中沒有與之對(duì)應(yīng)的對(duì)象?加載系統(tǒng)核心的類(如rt.jar)?擴(kuò)展類加載器olib/ext/*.jar?應(yīng)用類加載器o用戶程序的類?自定義類加載器o特殊的類,一般也是用戶程序類?雙親委派模式?概念o進(jìn)行類加載時(shí)如果已經(jīng)被加載直接返回可用的類,負(fù)責(zé)會(huì)請(qǐng)求雙親處理,如果雙親處理失敗,則由自己加載?弊端o檢查類是否已經(jīng)加載是單向的,頂層的ClassLoder無法訪問底層ClassLoader加載的類?突破雙親模式o重載loadClass,改變類的加載次序?熱替換的實(shí)現(xiàn)o重載findClass?調(diào)優(yōu)o調(diào)優(yōu)的目標(biāo)?內(nèi)存占用?延遲?吞吐量o思路?理解應(yīng)用需求和問題,確定調(diào)優(yōu)目標(biāo)?通過JVM和GC狀態(tài),定位具體問題?通過Jstat等工具查看GC等相關(guān)狀態(tài),開啟GC日志?選擇的GC類型是否符合我們的應(yīng)用特征?MinorGC過長(zhǎng)還是MixedGC出現(xiàn)異常停頓?通過分析具體調(diào)整參數(shù)或者軟硬件配置?如果達(dá)到目標(biāo)則結(jié)束調(diào)優(yōu),否則重新完成分析、調(diào)整驗(yàn)證?hadoopoMapReduce?執(zhí)行過程?作業(yè)提交o客戶端向資源管理器申請(qǐng)新應(yīng)用IDo檢查作業(yè)有沒有指定輸出目錄,如果沒有返回錯(cuò)誤給MapReduceo計(jì)算作業(yè)的輸入分片,如果指定的分片路徑不存在則返回錯(cuò)誤給Mapreduce程序o將運(yùn)行做需要的資源(JAR、配置文件、計(jì)算所得的輸入分片)復(fù)制到一個(gè)以ID命名的目錄下的共享文件系統(tǒng)?作業(yè)初始化o資源管理器收到調(diào)用submitApplication消息后,將請(qǐng)求傳遞給Yarn的調(diào)度器o調(diào)度器分配一個(gè)容器啟動(dòng)applicationmaster進(jìn)程?applicationmaster是一個(gè)java應(yīng)用,主類是MRAppMaster,負(fù)責(zé)接收任務(wù)進(jìn)度和狀態(tài)oapplicationmaster接收任務(wù)的進(jìn)度和完成報(bào)告o接收共享文件系統(tǒng)在客戶端計(jì)算的輸入分片,并且為每個(gè)輸入分片創(chuàng)建一個(gè)map任務(wù)o在運(yùn)行之前applicationmaster調(diào)用setupJob設(shè)置最終的輸o如果任務(wù)很小就會(huì)選擇和自己同一jvm上運(yùn)行?少于10個(gè)mapper并且只有一個(gè)reduce輸出大小小于一個(gè)HDFS數(shù)據(jù)塊的屬于小任務(wù)?任務(wù)分配oapplicationmaster向資源管理器申請(qǐng)map任務(wù)運(yùn)行的容器,有5%的map任務(wù)完成時(shí)為reduce任務(wù)的請(qǐng)求才會(huì)發(fā)出omap任務(wù)數(shù)據(jù)本地化,任務(wù)和分片駐留的統(tǒng)計(jì)階段運(yùn)行o請(qǐng)求會(huì)為任務(wù)指定內(nèi)存需求和cpu數(shù)(可配置)?任務(wù)執(zhí)行oapplicationmaster直接和節(jié)點(diǎn)管理器通信啟動(dòng)容器o任務(wù)運(yùn)行之前會(huì)將任務(wù)需要的資源(作業(yè)的配置、jar文件等)本地化o推測(cè)執(zhí)行(可關(guān)閉)?一種優(yōu)化措施?一個(gè)任務(wù)運(yùn)行比預(yù)期慢的時(shí)候,啟動(dòng)另一個(gè)相同的任務(wù)作為備份o通過提交協(xié)議確保作業(yè)和任務(wù)完成成功或者失敗?outputcommitter實(shí)現(xiàn)?成功調(diào)用commitJob方法,刪除臨時(shí)空間目錄?進(jìn)度和狀態(tài)更新omap和reduce任務(wù)運(yùn)行時(shí),子進(jìn)程和父applicationmaster通過umbilical通信oapplicationmaster會(huì)形成一個(gè)作業(yè)的匯聚視圖o客戶端每秒鐘(可配置)輪詢一次applicationmaster接收最新狀態(tài)?完成o收到最后一個(gè)任務(wù)已完成通知把作業(yè)設(shè)置為成功o完成后applicationmaster和任務(wù)容器清理工作狀態(tài)(中間結(jié)果被刪除)?失敗o任務(wù)運(yùn)行失敗?失敗類型?用戶代碼拋出異常ojvm退出之前向父applicationmaster發(fā)送錯(cuò)誤報(bào)告oapplicationmaster嘗試將此次任務(wù)標(biāo)?jvm突然退出o節(jié)點(diǎn)管理器注意到進(jìn)程已退出,并通知applicationmaster?任務(wù)掛起oapplicationmaster注意到一段時(shí)間沒收到進(jìn)度更新通知,將任務(wù)標(biāo)記為失敗?自動(dòng)殺死jvm進(jìn)程o失敗處置?applicationmaster避免在以前失敗過的節(jié)點(diǎn)管理器上重新運(yùn)行任務(wù)?默認(rèn)嘗試次數(shù)為4(可配置),超過則整個(gè)作業(yè)失敗?可配置失敗最大百分比?有少數(shù)任務(wù)失敗不影響整個(gè)作業(yè)?applicationmaster運(yùn)行失敗o默認(rèn)重試2次oapplicationmaster向資源管理器發(fā)送周期性心跳o資源管理器檢測(cè)到該失敗并在新的容器中開啟新的master實(shí)例o使用作業(yè)歷史恢復(fù)所運(yùn)行任務(wù)狀態(tài),使其不必重新運(yùn)行o客戶端輪詢進(jìn)度失敗就會(huì)向資源管理器重新詢問master地址并緩存?節(jié)點(diǎn)管理器失敗o節(jié)點(diǎn)管理器會(huì)停止向資源管理器發(fā)送心跳o資源管理器將其從自己的節(jié)點(diǎn)池中移出o在失敗的節(jié)點(diǎn)上運(yùn)行的所有任務(wù)或者applicationmaster如前面機(jī)制進(jìn)行恢復(fù)?資源管理器運(yùn)行失敗o雙機(jī)熱備運(yùn)行一對(duì)資源管理器o運(yùn)行中的應(yīng)用程序信息存儲(chǔ)在高可用狀態(tài)存儲(chǔ)區(qū)中 (ZooKeeper或HDFS備份)o新資源管理器啟動(dòng)后,從存儲(chǔ)區(qū)讀取應(yīng)用程序信息并且為所有應(yīng)用重啟applicationmastero使用Zookeeper的leader選舉機(jī)制切換oshuffle和排序?map端?將輸出數(shù)據(jù)寫入緩沖區(qū)o達(dá)到閾值會(huì)溢出到磁盤?寫磁盤之前根據(jù)最終傳入的reduce將數(shù)據(jù)分區(qū)?每個(gè)分區(qū)中后臺(tái)線程按鍵排序o有combiner函數(shù)就在排序后運(yùn)行o減少寫到磁盤的數(shù)據(jù)和傳遞給reduce的數(shù)據(jù)?將輸出寫入磁盤過程中壓縮(默認(rèn)未開啟)o節(jié)約磁盤空間o減少傳給reduce的數(shù)據(jù)量?輸出文件位于運(yùn)行map任務(wù)的本地磁盤?reduce端?復(fù)制階段o每個(gè)map任務(wù)完成后reduce任務(wù)就復(fù)制其輸出o默認(rèn)開啟5個(gè)線程,可以通過mapreduce.reduce.shuffle.parallelcopies設(shè)置如何知道從那臺(tái)機(jī)器獲取輸出結(jié)果呢?map任務(wù)完成后,會(huì)使用心跳機(jī)制通知它們的applicationmaster,applicationmaster知道m(xù)ap輸出和主機(jī)之間的映射關(guān)系,reduce的一個(gè)線程定期詢問master獲取map輸出的主機(jī)位置?如果map輸出相當(dāng)小,會(huì)被復(fù)制到reduce任務(wù)jvm內(nèi)存,否則輸出到磁盤?合并階段o后臺(tái)線程將副本合并為更大,排好序的文件o為了合并,壓縮的map輸出必須在內(nèi)存中解壓?reduce階段o直接把數(shù)據(jù)輸入reduce函數(shù)處理?對(duì)已排序輸出中的每個(gè)鍵調(diào)用reduce函數(shù),直接輸出到文件系統(tǒng)o調(diào)優(yōu)?mapreduce.task.io.sort.mb?排序map輸出所使用的內(nèi)存緩沖區(qū)大小?press?是否壓縮map輸出?mapreduce.reduce.shuffle.parallelcopies?復(fù)制map輸出到reduce的線程數(shù)?總的原則給shuffle過程盡量提供多的內(nèi)存空間o類型格式?輸入格式?輸入分片oInputSplit?getLength?分片大小,用來排序優(yōu)先處理大分片?getLocations?分片存儲(chǔ)位置,將map任務(wù)放在分片附近執(zhí)行oInputFormat?getSplits?客戶端獲取分片,將他們發(fā)送到applicationmaster,applicationmaster使用其存儲(chǔ)位置調(diào)度map處理這些任務(wù)?createRecordReader?獲取迭代器,將數(shù)據(jù)傳給map函數(shù)oFileInputFormat?InputFormat的子類?用于指定作業(yè)的輸入文件位置oaddInputPath等四個(gè)方法設(shè)置路徑o使用setInputPathFilter設(shè)置過濾器o如果未設(shè)置過濾器也會(huì)使用默認(rèn)的過濾器排除隱藏的文件?為輸入文件生成代碼片段o只切割超過HDFS塊的文件o過多的小文件浪費(fèi)namenode內(nèi)存,還還增加尋址次數(shù)o避免切分?增加最小分片大小,設(shè)置為處理的最大文件大小oFileInputFormat子類重寫isSplitable將返回值設(shè)置為falseo文本輸入?TextInputFormato二進(jìn)制輸入?SequenceFileInputFormato多個(gè)輸入?MultipleInputs?數(shù)據(jù)庫(kù)輸入oDBInputFormato輸出格式?二進(jìn)制輸出?SequenceFileOutPutFormato順序文件,格式緊湊容易壓縮?MapFileOutputFormato把map文件作為輸出?必須保證reduce輸出的鍵已經(jīng)是排好序的?文本輸出?TextOutPutFormat?多個(gè)輸出?MultipleOutputFormat?數(shù)據(jù)庫(kù)輸出?DBOutputFormat?高級(jí)特性o計(jì)數(shù)器?內(nèi)置計(jì)數(shù)器?多輸入?任務(wù)計(jì)數(shù)器?作業(yè)計(jì)數(shù)器?用戶定義的java計(jì)數(shù)器o排序?部分排序?MapReduce根據(jù)輸入的鍵對(duì)數(shù)據(jù)排序o排序順序由RawComparator控制?全排序?使用一個(gè)分區(qū)o處理大型文件時(shí)效率極低?partitioner均勻劃分多個(gè)分區(qū)前一個(gè)分區(qū)的數(shù)據(jù)大于后一個(gè)分區(qū)最后串聯(lián)這些分區(qū)?寫一個(gè)mapreduce作業(yè)計(jì)算落入分區(qū)的記錄數(shù)?此方法需要遍歷整個(gè)數(shù)據(jù)集,并不推薦使用?對(duì)鍵進(jìn)行采樣,獲取近似分布?Hadoop內(nèi)置若干采樣器Sampler接口?輔助排序?按值排序o定義包括自然鍵和自然值的組合鍵o根據(jù)組合鍵對(duì)記錄進(jìn)行排序(同時(shí)使用自然鍵和自然值進(jìn)行排序)o針對(duì)組合鍵進(jìn)行分區(qū)和分組時(shí)只考慮自然鍵o連接?map端?map的輸入數(shù)據(jù)必須先分區(qū)并且以特定方式排序?各個(gè)輸入數(shù)據(jù)集被劃分成數(shù)量相同的分區(qū)且按照相同的鍵(連接鍵)排序?使用COmpositeInputFormat運(yùn)行一個(gè)map端連接?reduce端o使用MultipleInputs?輔助排序o一個(gè)源的數(shù)據(jù)排列在另一個(gè)源的數(shù)據(jù)前是非常重要的o邊數(shù)據(jù)?作業(yè)所需的額外只讀數(shù)據(jù)?JobConf配置作業(yè)o加大mapreduce內(nèi)存開銷壓力,不適合傳輸大數(shù)據(jù)?Hadoop分布式緩存o使用?使用-files選項(xiàng)指定待分發(fā)的文件?使用-archives向自己的任務(wù)中復(fù)制存檔文件o工作機(jī)制指定的文件復(fù)制到分布式文件系統(tǒng)?任務(wù)運(yùn)行之前節(jié)點(diǎn)管理器將文件從分布式文件系統(tǒng)復(fù)制到本地磁盤?節(jié)點(diǎn)管理器為緩存中的文件維護(hù)一個(gè)計(jì)數(shù)器,當(dāng)任務(wù)運(yùn)件?HDSFo基礎(chǔ)概念?數(shù)據(jù)塊M以最小化尋址開銷?文件所在的數(shù)據(jù)塊可以存儲(chǔ)在網(wǎng)絡(luò)任意位置提高容錯(cuò)和可用性?namenode和datanode?namenodeo維護(hù)文件系統(tǒng)樹和整棵樹內(nèi)所有文件和目錄o命名空間鏡像文件和編輯日志文件保存整棵樹內(nèi)容o保存每個(gè)文件中各個(gè)數(shù)據(jù)塊所在的節(jié)點(diǎn)信息o備份機(jī)制?通過原子操作同時(shí)寫入多個(gè)文件(一般是NFS)?輔助namenode?定期合并編輯日志和命名空間鏡像?把存儲(chǔ)在NFS元數(shù)據(jù)復(fù)制到輔助namenode?datanodeo定期向namenode發(fā)送存儲(chǔ)的塊列表o接收客戶端和namenode調(diào)度?聯(lián)邦HDFS?每個(gè)namenode維護(hù)一個(gè)命名空間卷,相互獨(dú)立?一個(gè)namenode失效不會(huì)影響其他o高可用?活動(dòng)-備用namenode?NFS?日志管理器(QJM)o保證每次編輯寫入多個(gè)日志節(jié)點(diǎn)?使用Zookeeper實(shí)現(xiàn)namenode選取o文件讀取原理?客戶端Filesysteopen()?遠(yuǎn)程RPC調(diào)用namenodeo根據(jù)namenode獲取最佳datanode地址?反復(fù)調(diào)用read讀取內(nèi)容,失敗會(huì)重新選擇并告知namenode失敗節(jié)點(diǎn)o文件寫入原理?客戶端create()?PRC調(diào)用namenode(文件、權(quán)限檢查)o創(chuàng)建記錄并返回FSDataOutPutStream對(duì)象?分成數(shù)據(jù)包寫入內(nèi)部隊(duì)列?DataStreamer挑選適合的數(shù)據(jù)副本組成管線(按順序?qū)懭胨泄芫€)oDFSDataOutPutStream收到管線中所有datanode確認(rèn)消息后刪除數(shù)據(jù)包?寫入datanode異常處理?關(guān)閉管線o把數(shù)據(jù)包添加回?cái)?shù)據(jù)隊(duì)列的最前端?為正常的datanode數(shù)據(jù)塊指定新的標(biāo)識(shí),并傳遞給namenode?基于正常的datanode構(gòu)建新管線?YARNo運(yùn)行機(jī)制?資源管理器?客戶端聯(lián)系資源管理器運(yùn)行applicationmaster進(jìn)程o資源管理器找到節(jié)點(diǎn)管理器運(yùn)行applicationmaster?簡(jiǎn)單運(yùn)算將結(jié)果返回客戶端?向資源管理器請(qǐng)求更多的容器運(yùn)行分布式計(jì)算任務(wù)?本地限制(HDSF數(shù)據(jù)塊所在的節(jié)點(diǎn)申請(qǐng)容器)ospark一開始啟動(dòng)固定數(shù)量的執(zhí)行器oMapReduce最開始申請(qǐng)map任務(wù)容?節(jié)點(diǎn)管理器?運(yùn)行在集群所有節(jié)點(diǎn)?啟動(dòng)和監(jiān)控容器?應(yīng)用生命周期?一個(gè)用戶作業(yè)對(duì)應(yīng)一個(gè)應(yīng)用oMaperReduce默認(rèn)?作業(yè)的每個(gè)工作流或者用戶會(huì)話對(duì)應(yīng)一個(gè)應(yīng)用ospark默認(rèn)o容器可以在作業(yè)之間重用,會(huì)緩存作業(yè)之間的結(jié)果數(shù)據(jù)?多個(gè)用戶共享一個(gè)長(zhǎng)期運(yùn)行的應(yīng)用o通常作為協(xié)調(diào)者角色運(yùn)行o調(diào)度類型?FIFO調(diào)度器?將所有應(yīng)用放到一個(gè)隊(duì)列中,按照提交的順序運(yùn)行應(yīng)用?優(yōu)點(diǎn)o簡(jiǎn)單易懂、不需要任何配置?缺點(diǎn)o不適合共享集群?大應(yīng)用一直占用集群所有資源,小作業(yè)會(huì)被阻塞?容量調(diào)度器?一個(gè)獨(dú)立隊(duì)列專門保證小作業(yè)運(yùn)行?優(yōu)點(diǎn)o小作業(yè)有專門的隊(duì)列運(yùn)行會(huì)比較快?缺點(diǎn)o犧牲整個(gè)集群的利用率o大作業(yè)的執(zhí)行時(shí)間會(huì)比較長(zhǎng)?隊(duì)列放置oMapReduce中可以通過配置maperduce.job.queuename指定隊(duì)列?公平調(diào)度器?在所有運(yùn)行的應(yīng)用之間動(dòng)態(tài)平衡資源o第一個(gè)大作業(yè)啟動(dòng)時(shí)獲得集群所有資源,第二個(gè)小作業(yè)啟動(dòng)時(shí)分配到一半的資源,小作業(yè)運(yùn)行完成之后又得到所有資源?得到了較高的集群利用率,也保證了小作業(yè)能及時(shí)完成?隊(duì)列放置o基于規(guī)則?hiveo安裝?下載直接解壓?本地、偽分布式、分布式o配置?hivesite.xml?存放集群連接信息o指定文件系統(tǒng)和資源管理器?執(zhí)行引擎(hive.execution.engine指定)oMapreduce(默認(rèn))osparkoTezoMetastore?元數(shù)據(jù)存放地?內(nèi)嵌配置o以本地磁盤作為存儲(chǔ)的Derby數(shù)據(jù)庫(kù)實(shí)例?本地metaStore配置ometaStore和hive服務(wù)仍運(yùn)行在同一個(gè)進(jìn)程中,但連接的是另一個(gè)進(jìn)程的數(shù)據(jù)庫(kù)?一般使用mysql?遠(yuǎn)程metaStore配置o一個(gè)或多個(gè)metaStore服務(wù)器和Hive運(yùn)行在不同的進(jìn)程內(nèi)?數(shù)據(jù)庫(kù)層可以安全置于防火墻后o表?托管表?將數(shù)據(jù)放置在自己的倉(cāng)庫(kù)目錄?執(zhí)行drop命令會(huì)刪除元數(shù)據(jù)和表數(shù)據(jù)?外部表?創(chuàng)建表時(shí)使用external關(guān)鍵字?執(zhí)行drop不會(huì)碰數(shù)據(jù),只會(huì)刪除元數(shù)據(jù)?分區(qū)和桶?分區(qū)o分區(qū)只是表目錄下嵌套的子目錄o創(chuàng)建表時(shí)使用partitionedby定義?桶o使用clusteredby指定劃分桶作用的列和要?jiǎng)澐值耐暗膫€(gè)數(shù)oclusteredby(id)into4bucketso獲取更高的查詢效率o使采樣更加高效o優(yōu)化?盡早過濾數(shù)據(jù),減少每個(gè)階段的數(shù)據(jù)量?只讀取查詢中所需要的列?減少不必要的分區(qū)?在join前過濾不需要的數(shù)據(jù)?減少job數(shù)?如果joib的key相同,不管多少表都會(huì)合并成一個(gè)MapReduce任務(wù)?在join前過濾不需要的數(shù)據(jù)?解決數(shù)據(jù)傾斜問題?大表和小表join時(shí)使用mapJoin?使用leftsemijoin替代in/existso只能在on中設(shè)置過濾條件oselect和where中不能引用右邊表的字段?sparko彈性分布式數(shù)據(jù)集?創(chuàng)建?來自內(nèi)存中的對(duì)象集合?使用外部存儲(chǔ)器(如HDFS)?對(duì)現(xiàn)有RDD轉(zhuǎn)換?轉(zhuǎn)換?從現(xiàn)有RDD生成新的RDDomapoflodBykeyoaggregatebyKeyo......?動(dòng)作ocollectofirstosaveAsTextFileoforeachoo共享變量?經(jīng)過序列化后被發(fā)送到各個(gè)executor,然后緩存?類似Mapreduce的分布式緩存o運(yùn)行機(jī)制?基本概念?Driver(驅(qū)動(dòng)程序)o運(yùn)行程序Main函數(shù)o創(chuàng)建SparkContext?準(zhǔn)備spark運(yùn)行環(huán)境?與ClusterManager通信?資源申請(qǐng)?任務(wù)分配與監(jiān)控?ClusterManager(資源管理器)ospark原生資源管理器oHadoopYarno......?Executor(執(zhí)行器)o工作節(jié)點(diǎn)上的一個(gè)進(jìn)程,該進(jìn)程負(fù)責(zé)運(yùn)行tasko將數(shù)據(jù)存儲(chǔ)在內(nèi)存或者磁盤上o每個(gè)應(yīng)用都有獨(dú)立的一批Executor?窄依賴o一個(gè)父RDD的分區(qū)對(duì)應(yīng)于一個(gè)子RDD的分區(qū)o兩個(gè)父RDD的分區(qū)對(duì)應(yīng)于一個(gè)子RDD的分區(qū)ojoin(父RDD是hash-partitioned:如果JoinAPI之前被調(diào)用的RDDAPI是寬依賴(存在shuffle),而且兩個(gè)join的RDD的分區(qū)數(shù)量一致,join結(jié)果的rdd分區(qū)數(shù)量也一樣,這個(gè)時(shí)候joinapi是窄依賴)?寬依賴o父RDD的每個(gè)分區(qū)都可能被多個(gè)子RDD分區(qū)所使用,子RDD分區(qū)通常對(duì)應(yīng)所有的父RDD分區(qū)yojoin(父RDD不是hash-partitioned:除此之外的,rdd的joinapi是寬依賴)?DAG(有向無環(huán)圖)o反應(yīng)Rdd之間的依賴關(guān)系?有向無環(huán)圖調(diào)度器o基于DAG劃分Stage并以TaskSet的形勢(shì)提交Stage給TaskScheduler?TaskScheduler(任務(wù)調(diào)度器)o將taskSet提交給Woker(集群)運(yùn)行,并匯報(bào)結(jié)果o負(fù)責(zé)具體任務(wù)的實(shí)際調(diào)度?Stage(調(diào)度階段)askstageo劃分核心算法?從后往前回溯,遇到窄依賴加入本stage,遇見寬依賴進(jìn)行Stage切分?TaskSet(任務(wù)集)o由一組關(guān)聯(lián)的,但相互之間沒有Shuffle依賴關(guān)系的任務(wù)所組成的任務(wù)集?運(yùn)行流程?sparkContext提交作業(yè)到DAGSchedulero分析RDD構(gòu)建DAG圖?拆分Stage?生成作業(yè)o提交任務(wù)集TaskSet到任務(wù)調(diào)度器?任務(wù)調(diào)度器構(gòu)建一個(gè)TaskSetManager的實(shí)例來管理這個(gè)任務(wù)集的生命周期?任務(wù)調(diào)度器得到計(jì)算資源后通過taskSetmanager調(diào)度具體的任務(wù)到對(duì)應(yīng)的Executor節(jié)點(diǎn)上進(jìn)行計(jì)算?RPC框架實(shí)現(xiàn)原理o建立通信(TCP)?服務(wù)尋址?網(wǎng)絡(luò)傳輸?序列化、反序列化o服務(wù)調(diào)用o使用到的技術(shù)?動(dòng)態(tài)代理?我們可以使用JDK原生的動(dòng)態(tài)代理機(jī)制,可以使用一些開源字節(jié)碼工?序列化?可以使用Java原生的序列化機(jī)制,但是效率非常低,推薦使用一些開?NIO?使用Netty作為底層通信框架?服務(wù)注冊(cè)中心?Zookeeper?面試經(jīng)典題oHashMap7和8的區(qū)別?插入順序?1.7插入在鏈表的頭部o不需要遍歷整個(gè)鏈表,效率高?1.8插入鏈表尾部o鏈表大于8的時(shí)候需要樹化,本身就需要計(jì)算長(zhǎng)度oHashMap死循環(huán)的bug不會(huì)有了?只有平移,沒有調(diào)換順序?hash算法簡(jiǎn)化?1.7oJDK初始大小為16.加載因子0.75o用Hash值和需要擴(kuò)容的二進(jìn)制數(shù)進(jìn)行&。只有2的n次冪的情況最后一位二進(jìn)制數(shù)一定是1,這樣能最大程度減少Hash碰撞o用9次擾動(dòng)處理=4次位運(yùn)算+6次異或?1.8o原始位置+擴(kuò)容的大小值o2次擾動(dòng)處理=1次位運(yùn)算+1次異或oConcurrentHashMap?早期實(shí)現(xiàn)?分離鎖,內(nèi)部進(jìn)行分段里面則是HashEntry的數(shù)組?HashEntry內(nèi)部使用volatile的Value字段保證可見性?Segment本身基于ReenTrantLock擴(kuò)展實(shí)現(xiàn),并發(fā)修改時(shí)Segment被鎖定?JAVA8后?內(nèi)部仍有SegMent定義,僅僅是為了保證序列化的兼容性?初始化修改為lazy_load形式,避免初始開銷?數(shù)據(jù)存儲(chǔ)利用Volatile來保證可見性?使用CAS等操作在的定場(chǎng)景進(jìn)行無鎖并發(fā)操作?segment數(shù)量與桶數(shù)量一致oB樹和B+樹?區(qū)別?B+樹只有葉子節(jié)點(diǎn)會(huì)帶有指向記錄的指針,B樹所有的節(jié)點(diǎn)都帶有,在內(nèi)部出現(xiàn)的索引項(xiàng)不會(huì)出現(xiàn)在葉子節(jié)點(diǎn)中?B+樹中所有葉子節(jié)點(diǎn)都是通過指針連接在一起而B樹不會(huì)?子主題o什么情況下產(chǎn)生死鎖,如何定位以及如何避免?產(chǎn)生條件環(huán)境下,由于互相持有對(duì)方需要的鎖。而永久處于阻塞狀態(tài)?如何定位?jstack工具直接定位?類似JConsole等圖形化工具?如何避免?避免使用多個(gè)鎖,嵌套非常容易出問題?如果比較使用多個(gè)鎖,盡量設(shè)置好鎖的獲取順序,可以將鎖和對(duì)象之前的關(guān)系用圖形化的方式抽取出來?使用帶超時(shí)的方法,為程序帶來更多可控性odubbo負(fù)載均衡策略?按權(quán)重隨機(jī)調(diào)用?如果權(quán)重相同隨機(jī)調(diào)用,如果權(quán)重不同,則按權(quán)重隨機(jī)數(shù)調(diào)用?輪詢?計(jì)算服務(wù)實(shí)例的最大最小權(quán)重,如果權(quán)重都一樣,則直接取模輪詢。如果權(quán)重不一樣,每一輪調(diào)用,都計(jì)算出一個(gè)基礎(chǔ)權(quán)重值,然后篩選出權(quán)重值大于基礎(chǔ)權(quán)重值取模隨機(jī)調(diào)用?最少活躍次數(shù)?查找最少活躍次數(shù)的服務(wù)并統(tǒng)計(jì)權(quán)重和出現(xiàn)頻次,如果最少活躍次數(shù)只出現(xiàn)一次,直接使用該服務(wù)里如果出現(xiàn)多次,如果出現(xiàn)多次并且權(quán)重不同,則按總權(quán)重隨機(jī)調(diào)用?一致性hash?子主題?分布式ID生成策略oUUID?以連字號(hào)分為5段包含32個(gè)16進(jìn)制數(shù)字?優(yōu)點(diǎn)?性能非常高o本地生成,沒有網(wǎng)絡(luò)消耗?缺點(diǎn)?不易于存儲(chǔ)oUUID太長(zhǎng)12字節(jié)128位?信息不安全o基于mac地址生成的UUID可能造成MAC地址泄漏?不適合做BD主鍵omysql在InnoDB引擎下,UUID無序會(huì)造成頁分裂osnowflake?以劃分命名空間來生成ID?頭部1位的正負(fù)標(biāo)識(shí)位?41位時(shí)間戳o通常System.currentTimeMillis()?10位的WorkerIDo5位數(shù)據(jù)中心o5位機(jī)器ID?12位的自增序列號(hào)?優(yōu)點(diǎn)?毫秒數(shù)在高位,自增序列在低位,整個(gè)ID都是趨勢(shì)遞增的?不依賴第三方數(shù)據(jù)庫(kù),穩(wěn)定性比較高,生成ID性能也很高?根據(jù)吱聲業(yè)務(wù)特性分配bit位,非常靈活?缺點(diǎn)?強(qiáng)制依賴時(shí)鐘,如果機(jī)器上時(shí)鐘回?fù)埽瑫?huì)導(dǎo)致?lián)芴?hào)重復(fù)o數(shù)據(jù)庫(kù)生成?mySqlID自增,每次使用時(shí)先讀寫mysql獲取ID號(hào)?優(yōu)點(diǎn)?非常簡(jiǎn)單,利用現(xiàn)有系統(tǒng)數(shù)據(jù)庫(kù)功能,成本小,有DBA專門維護(hù)?ID單調(diào)遞增?缺點(diǎn)?強(qiáng)制依賴DB,當(dāng)DB不可用是整個(gè)系統(tǒng)不可用,致命問題?ID發(fā)號(hào)性能瓶頸限制在單臺(tái)MySQL的讀寫性能?針對(duì)性能優(yōu)化方案?多部署幾臺(tái)機(jī)器,沒太機(jī)器設(shè)置不同的初始值,且補(bǔ)長(zhǎng)和機(jī)器數(shù)相等oLeaf-segment?各個(gè)業(yè)務(wù)不同的發(fā)號(hào)需求用biz_tag字段?互不影響o壓力大只需對(duì)biz_tag分庫(kù)分表?優(yōu)化?批量獲取,做雙buggfer優(yōu)化oID分號(hào)段加載,當(dāng)號(hào)段消費(fèi)到某個(gè)點(diǎn)是酒異步把下一個(gè)號(hào)段加載到內(nèi)存中oLeaf-snowflake?使用Zookeeper持久順序節(jié)點(diǎn)?啟動(dòng)服務(wù),連接Zookeeper,在父節(jié)點(diǎn)下檢查自己是否注冊(cè)過(是否有順序子節(jié)點(diǎn))o如果注冊(cè)過取回自己的workId,啟動(dòng)服務(wù)?沒有注冊(cè)過,在父節(jié)點(diǎn)下創(chuàng)建一個(gè)持久的順序節(jié)點(diǎn),創(chuàng)建成果后取回順序號(hào)當(dāng)做自己的workerID?解決時(shí)鐘問題?每個(gè)一段時(shí)間(3s)上報(bào)自身系統(tǒng)時(shí)間,并寫入Zookeeper子節(jié)點(diǎn)?分布式鎖的實(shí)現(xiàn)方式o基于Zookeeper?指定一個(gè)作為鎖的znode節(jié)點(diǎn)?客戶端在該znode下創(chuàng)建一個(gè)順序短暫znodeo查詢znode子節(jié)點(diǎn)并設(shè)置一個(gè)觀察?如果步驟1中創(chuàng)建的znode是步驟2中返回的最小節(jié)?等待步驟2中所設(shè)的觀察通知,轉(zhuǎn)到步驟2oredis?獲取鎖的時(shí)候使用setnx加鎖,并使用expire為鎖設(shè)置一個(gè)超時(shí)時(shí)間?獲取鎖的時(shí)候還需要設(shè)置一個(gè)超時(shí)時(shí)間,超過這個(gè)時(shí)間則放棄獲取鎖o釋放鎖的時(shí)候通過鎖的value值判斷是不是這個(gè)鎖,如果是則deleteo數(shù)據(jù)庫(kù)?樂觀鎖?在表中添加版本號(hào)字段,每次更新前都查詢出版本號(hào)數(shù)據(jù),更新是where帶版本號(hào),如果更新成功就表示獲取鎖,如果失敗,則重試?悲觀鎖?select...forupdate(X鎖)/select...lockinsharemode(S鎖)?秒殺系統(tǒng)設(shè)計(jì)o架構(gòu)原則?數(shù)據(jù)要盡量少?用戶的請(qǐng)求數(shù)據(jù)能少就少?依賴的數(shù)據(jù)能少就少o讀取、保存的數(shù)據(jù),調(diào)用會(huì)涉及到序列化和反序列化?路徑盡量要短?依賴盡量要少?不要有單點(diǎn)o動(dòng)靜分離?如何緩存靜態(tài)數(shù)據(jù)?把靜態(tài)數(shù)據(jù)緩存到離用戶最近的地方o瀏覽器oCDNo服務(wù)器Cache?直接緩存HTTP連接ohttp協(xié)議不用重新組裝,請(qǐng)求頭也不用解析?由誰來緩存?如何做動(dòng)靜分離的改造?URL唯一化o可以以URL做為key緩存整個(gè)http連接?分離瀏覽者相關(guān)因素o是否已登錄,登錄身份等可以單獨(dú)拆出來,通過動(dòng)態(tài)請(qǐng)求獲取?分離時(shí)間因素o服務(wù)端輸出的時(shí)間通過動(dòng)態(tài)請(qǐng)求獲取?異步化地域因素o地域相關(guān)因素可以做成異步方式獲取?去掉Cookieo緩存的靜態(tài)數(shù)據(jù)中不含Cookie?動(dòng)態(tài)數(shù)據(jù)處理方案?ESI或SSIo在Web服務(wù)器上做動(dòng)態(tài)內(nèi)容請(qǐng)求,并將請(qǐng)求插入靜態(tài)頁面?對(duì)服務(wù)器性能有影響,單用戶體驗(yàn)好?CSIo單獨(dú)發(fā)起一個(gè)異步JavaScript請(qǐng)求?服務(wù)端性能更佳,用戶端頁面可能會(huì)有延遲?架構(gòu)方案?實(shí)體機(jī)單機(jī)部署o將虛擬機(jī)改為實(shí)體機(jī)增大Cache容量?一致性Hash分組來實(shí)現(xiàn)命中率o優(yōu)點(diǎn)?沒有網(wǎng)絡(luò)瓶頸,能夠使用大內(nèi)存?提高命中率?減少Cache失效壓力o缺點(diǎn)?造成CPU浪費(fèi),單個(gè)java進(jìn)程很難用完真?zhèn)€實(shí)體機(jī)的部署java又作為Cache,運(yùn)維高度復(fù)雜?統(tǒng)一Cache層o將單機(jī)的Cache統(tǒng)一分離出來,形成單獨(dú)的Cache集群o優(yōu)點(diǎn)?減少多個(gè)應(yīng)用接入時(shí)使用Cache成本,接入的應(yīng)用只要維護(hù)自己的java系統(tǒng)就好?更于維護(hù),可以配置自動(dòng)化,加強(qiáng)監(jiān)控?可以共享內(nèi)存,最大化利用內(nèi)存,不同系統(tǒng)之間可以動(dòng)態(tài)切換o缺點(diǎn)?Cache內(nèi)部交換網(wǎng)絡(luò)會(huì)成為瓶頸?緩存服務(wù)器的網(wǎng)卡也會(huì)成為瓶頸?機(jī)器少風(fēng)險(xiǎn)大,掛掉一臺(tái)會(huì)影響很大一部分緩存數(shù)據(jù)?上CDNo將Cache緩存到CDN上,離用戶最近,效果會(huì)更好o處理熱點(diǎn)數(shù)據(jù)?發(fā)現(xiàn)熱點(diǎn)數(shù)據(jù)?靜態(tài)熱點(diǎn)數(shù)據(jù)o強(qiáng)制讓賣家通過報(bào)名參加的商業(yè)手段o通過大數(shù)據(jù)計(jì)算?動(dòng)態(tài)熱點(diǎn)數(shù)據(jù)o構(gòu)建一個(gè)異步系統(tǒng),收集交易鏈路中各個(gè)環(huán)節(jié)的熱點(diǎn)key,如o建立一個(gè)熱點(diǎn)上報(bào)、訂閱熱點(diǎn)服務(wù)的下發(fā)規(guī)范,把上游穎發(fā)現(xiàn)o將上游發(fā)現(xiàn)的任店數(shù)據(jù)發(fā)送到熱點(diǎn)服務(wù)臺(tái),下游系統(tǒng)做熱點(diǎn)保護(hù)?處理熱點(diǎn)數(shù)據(jù)?優(yōu)化o緩存熱點(diǎn)數(shù)據(jù),可以用一個(gè)隊(duì)列緩存數(shù)秒中,由于隊(duì)列長(zhǎng)度有限,可以使用LRU淘汰算法替換?限制oID做一致性Hash,根據(jù)hash分桶,每個(gè)分桶設(shè)置一個(gè)處理隊(duì)列,把熱點(diǎn)商品限制在一個(gè)請(qǐng)求隊(duì)列中?隔離o業(yè)務(wù)隔離o系統(tǒng)隔離o數(shù)據(jù)隔離o流量消峰?排隊(duì)?把同步的直接調(diào)用轉(zhuǎn)換成異步的間接推送o利用線程池加鎖等待o先進(jìn)先出、先進(jìn)后出等內(nèi)存片段算法o把請(qǐng)求序列化到文件,然后再順序讀文件?答題?增加購(gòu)買的復(fù)雜度?防止秒殺器作弊?延緩請(qǐng)求?分層過濾?在不同的層次盡可能過濾掉無效請(qǐng)求,讓露頭最末端才是有效請(qǐng)求o將動(dòng)態(tài)請(qǐng)求的讀數(shù)據(jù)緩存在web端,過濾掉無效的數(shù)據(jù)讀o對(duì)讀數(shù)據(jù)不做強(qiáng)一直性校驗(yàn),減少一致性校驗(yàn)產(chǎn)生的系統(tǒng)瓶頸o對(duì)寫數(shù)據(jù)進(jìn)行基于時(shí)間的合理分片,過濾掉過期的實(shí)現(xiàn)請(qǐng)求o減庫(kù)存o對(duì)寫數(shù)據(jù)做限流保護(hù),將超出系統(tǒng)承載能力的請(qǐng)求過濾掉o對(duì)數(shù)據(jù)進(jìn)行強(qiáng)一致性校驗(yàn),只保留最后有效數(shù)據(jù)o提高系統(tǒng)性能?如何發(fā)現(xiàn)CPU瓶頸?Jprofiler和Yourkit,列出請(qǐng)求中每個(gè)函數(shù)的cpu執(zhí)行時(shí)間?jstack定時(shí)地打印調(diào)用棧,多的函數(shù)會(huì)多吃出現(xiàn)在系統(tǒng)調(diào)用棧?如何判斷是否是CPU瓶頸?QPS當(dāng)大極限時(shí)服務(wù)器CPU利用率是否超過95%?如何優(yōu)化?減少編碼o每個(gè)字符的編碼需要查表,查表操非常消耗資源o網(wǎng)頁輸出可以直接用流輸出,resp.getOutputStream寫數(shù)據(jù),把靜態(tài)數(shù)據(jù)提前轉(zhuǎn)化為字節(jié),等到真正往外寫的時(shí)候直接用outoutStream寫,減少靜態(tài)數(shù)據(jù)編碼轉(zhuǎn)化?減少序列化o關(guān)聯(lián)性比較強(qiáng)的應(yīng)用合并部署?java極致優(yōu)化o對(duì)大流量的web系統(tǒng)做靜態(tài)化改造,大部分請(qǐng)求和數(shù)據(jù)直接在Nginx服務(wù)器或者web代理服務(wù)器上直接返回,java層處理少量動(dòng)態(tài)請(qǐng)求堆復(fù)雜且無用的處理邏輯o直接輸出流數(shù)據(jù)?并發(fā)讀優(yōu)化o秒殺系統(tǒng)的單機(jī)上緩存商品相關(guān)數(shù)據(jù)?標(biāo)題、描述等不變的數(shù)據(jù),秒殺之前全量推到秒殺機(jī)器上并一直緩存到秒殺結(jié)束?減庫(kù)存的方式?下單減庫(kù)存o不會(huì)出現(xiàn)超賣,但是有些人下單可能不會(huì)付款?付款減庫(kù)存o會(huì)出現(xiàn)買家下單之后付不了款的情況?預(yù)扣庫(kù)存o下單后庫(kù)存為其保留一定時(shí)間,超過則自動(dòng)釋放庫(kù)存?秒殺系統(tǒng)如何減?搶到就是賺到,一般下單減庫(kù)存更加合理?如果沒有復(fù)雜的聯(lián)動(dòng)關(guān)系,完全可以將減庫(kù)存放到緩存系統(tǒng)(redis)實(shí)現(xiàn)?在mysql中會(huì)有大量的線程去競(jìng)爭(zhēng)InnoDB行鎖,數(shù)據(jù)庫(kù)吞吐量嚴(yán)重受影響?解決并發(fā)鎖方案o應(yīng)用層排隊(duì)?按商品維度設(shè)置對(duì)壘順序執(zhí)行,減少同一臺(tái)機(jī)器對(duì)數(shù)據(jù)庫(kù)同一行記錄的并發(fā)操作o數(shù)據(jù)庫(kù)層做排隊(duì)?應(yīng)用層只能做單機(jī)排隊(duì),數(shù)據(jù)庫(kù)補(bǔ)丁程序可以在數(shù)據(jù)庫(kù)層上對(duì)單行記錄做并發(fā)排隊(duì)o兜底方案?高可用建設(shè)?架構(gòu)階段o考慮擴(kuò)展和容錯(cuò)性?編碼階段o保證代碼的健壯性?涉及遠(yuǎn)程調(diào)用是,設(shè)置合理的超時(shí)時(shí)間,防止被其他系統(tǒng)拖垮?調(diào)用的返回結(jié)果集有預(yù)期,防止超出程序處理范圍?測(cè)試階段o保證測(cè)試用例的覆蓋度,保證最壞情況的發(fā)生?運(yùn)行階段o對(duì)系統(tǒng)的監(jiān)控及時(shí)準(zhǔn)確,發(fā)現(xiàn)問題能后準(zhǔn)備報(bào)警?故障發(fā)生o及時(shí)止損o及時(shí)恢復(fù)服務(wù)、并定位原因解決問題?降級(jí)?當(dāng)系統(tǒng)容量達(dá)到一定程度,限制或關(guān)閉系統(tǒng)非核心功能?設(shè)置降級(jí)開關(guān)?限流?支持方法以及URL方式限流也要支持基于QPS和線程的限流?客戶端限流o優(yōu)點(diǎn)?限制請(qǐng)求的發(fā)出,減少無用請(qǐng)求從而減少系統(tǒng)的消耗o缺點(diǎn)?客戶端比較分散,無法設(shè)置合理的閾值?服務(wù)端限流o優(yōu)點(diǎn)?可以根據(jù)服務(wù)端性能設(shè)置合理的閾值o缺點(diǎn)?被限制的請(qǐng)求是無效請(qǐng)求,處理這些請(qǐng)求也會(huì)消耗服務(wù)器資源?拒絕服務(wù)?如果限流無法解決問題,直接拒絕服務(wù)?可以zaiNginx設(shè)置過載保護(hù),當(dāng)機(jī)器負(fù)載達(dá)到某個(gè)值時(shí)就直接拒絕?緩存o緩存穿透?緩存和數(shù)據(jù)庫(kù)都沒有數(shù)據(jù),而用戶不斷發(fā)起請(qǐng)求,導(dǎo)致數(shù)據(jù)庫(kù)壓力過大?解決方案?接口層增加校驗(yàn),如用戶鑒權(quán)校驗(yàn),數(shù)據(jù)基礎(chǔ)校驗(yàn)?將key-value改為key-null,緩存有效時(shí)間設(shè)置短點(diǎn),如30秒o緩存擊穿?緩存中沒,數(shù)據(jù)庫(kù)中用(一般是緩存時(shí)間到期),由于并發(fā)用戶特別多,引起數(shù)據(jù)庫(kù)壓力瞬間增大?解決方案?設(shè)置熱點(diǎn)數(shù)據(jù)永不過期?加互斥鎖,緩存中沒數(shù)據(jù),獲取鎖從數(shù)據(jù)庫(kù)讀,讀到之后更新緩存,其他等待線程等待100ms再去緩存中讀,o緩存雪崩?緩存中數(shù)據(jù)大批量到過去時(shí)間,并且查詢數(shù)據(jù)量巨大,引起數(shù)據(jù)庫(kù)壓力過大?解決方案?緩存數(shù)據(jù)過期時(shí)間設(shè)置隨機(jī),防止同一時(shí)間大量數(shù)據(jù)過期現(xiàn)象發(fā)生?如果緩存數(shù)據(jù)庫(kù)是分布式部署,將任店數(shù)據(jù)均勻分布在不同緩存數(shù)據(jù)庫(kù)中?設(shè)置熱點(diǎn)數(shù)據(jù)永不過期?volatileovolatile變量修飾的共享變量進(jìn)行寫操作是會(huì)生成lock匯編指令?將當(dāng)前處理器緩存的數(shù)據(jù)行寫會(huì)內(nèi)存?一個(gè)處理器緩存寫會(huì)內(nèi)存導(dǎo)致其他處理器緩存失效?原子操作類o原子更新基本類型?AtomicBoolean?原子更新布爾類型?AtomicInteger?原子更新整型oaddAndGet?以原子的輸入將輸入的數(shù)值與實(shí)例中的數(shù)值相加ocompareAndSet?如果輸入的值等于預(yù)期值,則以原子的方式將該值設(shè)置為輸入值ogetAndIncrement?以原子方式將當(dāng)前值加1?使用空循環(huán),獲取AtomicInteger中的值,將當(dāng)期值o......?AtomicLong?原子更新長(zhǎng)整型o原子更新數(shù)組oAtomicInterArray會(huì)將當(dāng)前數(shù)組負(fù)責(zé)一份,所有當(dāng)AtomicInterArray對(duì)內(nèi)部元素修改時(shí),不會(huì)影響傳入的數(shù)組?AtomicIntegerArray?原子更新整型數(shù)組中元素?AtomicLongArray?原子更新長(zhǎng)整型整數(shù)數(shù)組元素?AtomicReferenceArray?原子更新應(yīng)用類型數(shù)組元素o原子更新字段類?AtomicIntegerFieldUpdater?原子更新整型的字段更新器?AtomicLongFileUpdater?原子更新長(zhǎng)整型字段的更新器?AtomicStampedReference?原子更新帶版本號(hào)的應(yīng)用類型o可以解決CAS的ABA問題?多線程o線程的優(yōu)先級(jí)?操作系統(tǒng)分出一個(gè)個(gè)時(shí)間片,線程會(huì)分配到若干時(shí)間片,優(yōu)先級(jí)高的分配到的時(shí)間片越多?構(gòu)建線程的時(shí)候通過時(shí)間setPriority方法來修改優(yōu)先級(jí)?偏重計(jì)算的線程設(shè)置較低的優(yōu)先級(jí),頻繁阻塞的設(shè)置較高的優(yōu)先級(jí)o線程的狀態(tài)?NEW?初始狀態(tài)o線程被構(gòu)建,但未調(diào)用start?RUNNABLE?運(yùn)行狀態(tài)o將就緒和運(yùn)行統(tǒng)稱為運(yùn)行中?BLOCKED?阻塞狀態(tài)o表示線程阻塞與鎖?進(jìn)入synchronize?WAITING?等待狀態(tài)o進(jìn)入該狀態(tài)表示當(dāng)前線程需要等待其他線程做出一定動(dòng)作(中斷、喚醒)?Lock接口?Lock對(duì)于阻塞的實(shí)現(xiàn)使用了LockSupport類?TIME_WAINTING?超時(shí)等待o可以在指定時(shí)間自行返回?TERMINATED?終止?fàn)顟B(tài)oDaemon線程?一種支持性線程,用于程序中后臺(tái)調(diào)度以及支持性工作?Thread.setDaemon(true)將線程設(shè)置為Daemon線程?不能依靠finally中的內(nèi)容確保關(guān)閉或者清理資源?與非守護(hù)線程區(qū)別?jvm監(jiān)測(cè)到僅剩一個(gè)守護(hù)線程,而其他用戶線程都退出時(shí)jvm就會(huì)退出,因?yàn)闆]有守護(hù)的對(duì)象了o中斷操作?表示一個(gè)運(yùn)行中的線程是否被其他線程進(jìn)行了中斷操作?線程通過檢查自身是否被中斷來進(jìn)行響應(yīng)oisInterrupt判斷是否被中斷oTerrupt對(duì)中斷標(biāo)識(shí)復(fù)位o線程間通信?volatile和synchronized關(guān)鍵字?等待、通知機(jī)制?notifyo通知一個(gè)在對(duì)象上等待的線程,使其從wait返回?notifyAllo通知所有等待在該對(duì)象上的線程?waito是線程進(jìn)入等待狀態(tài),只有等待通知或被中斷才會(huì)返回,會(huì)釋放對(duì)象的鎖?wait(long)o超時(shí)一段時(shí)間,如果沒有通知就超時(shí)返回?Thread.join?當(dāng)前線程A等待thread線程終止后才從thread.join返回?ThreadLocal?線程變量o是一個(gè)以threadLocal對(duì)象為鍵、任意對(duì)象為值的存儲(chǔ)結(jié)構(gòu)?實(shí)現(xiàn)原理oThread的對(duì)象都有一個(gè)ThreadLocalMap,最終的變量是放在了當(dāng)前線程的ThreadLocalMap中oThreadLocalMap中使用的key為ThreadLocal的弱引用,在下一次垃圾回收的時(shí)候必然會(huì)被清理掉?線程池o實(shí)現(xiàn)原理?如果當(dāng)前運(yùn)行的線程少于corePoolSize,則創(chuàng)建新線程來執(zhí)行任務(wù)?如果運(yùn)行的線程等于或多余corePoolSize,則將任務(wù)加入BLockingQueueo如果隊(duì)列已滿,則創(chuàng)建新的線程來處理(需要獲取全局鎖)?如果創(chuàng)建線程超過MaxImumPoolSize,任務(wù)將被拒絕,并調(diào)用拒絕策略執(zhí)行oThreadPoolExecutor?FixedThreadPool?可重用固定線程數(shù)的線程池?使用無界隊(duì)列LinkedBlockingQuery作為線程池的工作隊(duì)列o當(dāng)線程池中的線程數(shù)到達(dá)CorePoolSize后,新任務(wù)將在無界隊(duì)列中等待,線程數(shù)不會(huì)超過corePoolSizeomaximumPoolSize將是無效參數(shù)okeepAliveTime將是一個(gè)無效參數(shù)o不會(huì)調(diào)用拒絕策略?SingleThreadExecutor?使用單個(gè)WorKer的線程池?corePoolSize和maximumPoolSize都被設(shè)置為1?實(shí)現(xiàn)時(shí),定義了FinalizableDelegatedExecutorService包裝類o實(shí)現(xiàn)了finalize方法?進(jìn)行垃圾回收的時(shí)候自動(dòng)shutdown線程?CachedThreadPool?根據(jù)需要?jiǎng)?chuàng)建線程的線程池為Integer.MAX_VALUE,即無界,keepAliveTimes設(shè)置為60L,意味著corePoolSize中的空閑線程等待任務(wù)的最長(zhǎng)時(shí)間為60秒,超過被終止o使用沒有容量的SynchronousQueue作為線程池工作隊(duì)列?ScheduledThreadExecutor?給定的延遲之后運(yùn)行任務(wù),或者定期執(zhí)行任務(wù)?使用DelayQueue無界隊(duì)列作為線程池的工作隊(duì)列oTutureTask?實(shí)現(xiàn)了Future接口外還實(shí)現(xiàn)了Runnable接口?FutureTask可以交給Executor執(zhí)行?ExecutorService.submit返回FutureTask?實(shí)現(xiàn)?基于AQSAQS實(shí)現(xiàn)oFutureTask聲明了一個(gè)私有的繼承于AQS的子類Sync,對(duì)FutureTask的調(diào)用都委托給這個(gè)內(nèi)部類o子主題?java中的鎖osynchronized(JVM層面)?對(duì)于普通方法鎖的是當(dāng)前實(shí)例對(duì)象?對(duì)于靜態(tài)同步方法,鎖的是當(dāng)前類的Class對(duì)象?對(duì)于同步方法塊鎖的是Synchonized括號(hào)中配置的的對(duì)象?實(shí)現(xiàn)原理?JVM基于進(jìn)入和退出Monitor對(duì)象實(shí)現(xiàn)方法同步和代碼塊同步?JAVA對(duì)象頭ossynchronized鎖存在JAVA對(duì)象頭oMarkWord中存儲(chǔ)對(duì)象的HashCode、分代年齡、鎖標(biāo)記位?鎖的升級(jí)?偏向鎖?,因?yàn)槠蜴i不會(huì)主動(dòng)釋放,所以線程再次訪問代碼塊時(shí)檢查對(duì)象頭中的鎖和當(dāng)前線程ID是否一致,如果一致則獲取鎖,不一致檢查對(duì)象頭中的線程是否存活,如果沒有存活那么鎖對(duì)象被重置為無鎖狀態(tài),其他線程可以競(jìng)爭(zhēng)將其設(shè)置為偏向鎖,如果存活,那么查看該線程的棧幀信息如果還是需要繼續(xù)持有這個(gè)鎖對(duì)象那么暫停當(dāng)前線程1,撤銷偏向鎖,升級(jí)為輕量級(jí)鎖,如果線程1不再使用該鎖對(duì)象,那么將鎖對(duì)象狀態(tài)設(shè)為無鎖狀態(tài),重新偏向新的線程o加鎖?當(dāng)線程訪問代碼塊并獲取鎖時(shí),會(huì)在對(duì)象頭和棧幀的鎖線程ID,下次訪問時(shí)只需簡(jiǎn)單測(cè)IDID獲取鎖o解鎖?偏向鎖不會(huì)主動(dòng)撤銷,只有等到競(jìng)爭(zhēng)時(shí)才會(huì)撤銷?檢查對(duì)象頭中的線程是否存活,如果沒有存活那么鎖對(duì)象被重置為無鎖狀態(tài),其他線程可以競(jìng)爭(zhēng)將其設(shè)置為偏向鎖,如果存活,那么查看該線程的棧幀信息如果還是續(xù)持有這個(gè)鎖對(duì)象那么暫停當(dāng)前線程1,撤銷偏向鎖,升級(jí)為輕量級(jí)鎖,如果線程1不再使用該鎖對(duì)?setState象,那么將鎖對(duì)象狀態(tài)設(shè)為無鎖狀態(tài),重新偏向新的線程?輕量級(jí)鎖o加鎖?JVM在當(dāng)前棧幀中創(chuàng)建存儲(chǔ)鎖記錄的空間,并將對(duì)象頭中的markword復(fù)制到鎖記錄中?嘗試使用CAS替換對(duì)象頭中的markwordo如果成功則獲取鎖,如果失敗嘗試使用o解鎖?使用CAS將棧幀中的markword替換回對(duì)象頭,如果成功,則表示沒有競(jìng)爭(zhēng)發(fā)生,如果失敗則膨脹為重量級(jí)鎖?重量級(jí)鎖o其他線程試圖獲取鎖的操作都會(huì)被阻塞oLock(java類)?synchronized不具備的特性?嘗試非阻塞獲取鎖?能夠中斷獲取鎖?超時(shí)獲取鎖?可以選擇公平性?實(shí)現(xiàn)原理?隊(duì)列同步器(AQS)?基于模板方法模式o主要方法?基礎(chǔ)方法?getStateo獲取當(dāng)前同步狀態(tài)o設(shè)置當(dāng)前同步狀態(tài)?compareAndStateo使用CAS設(shè)置同步狀態(tài)?可重寫方法?tryAcquireo獨(dú)占式獲取同步狀態(tài)?查詢當(dāng)前狀態(tài),并判斷是否符合預(yù)期,然后使用CAS判斷同步狀態(tài)?tryRelease?獨(dú)占式釋放同步狀態(tài)?tryAcquireShared?共享式獲取同步狀態(tài)?tryReleaseShared?共享式釋放同步狀態(tài)?實(shí)現(xiàn)邏輯o同步隊(duì)列?使用FIFO的雙向隊(duì)列完成線程同步?獲取同步狀態(tài)失敗是會(huì)將當(dāng)前線程以及等待信息組成Node入其隊(duì)列?Node中保存獲取同步狀態(tài)失敗的線程引用、等待狀態(tài)、前驅(qū)節(jié)點(diǎn)、后繼節(jié)點(diǎn)?加入隊(duì)列過程使用CAS保證正線程安全?首節(jié)點(diǎn)是獲取同步狀態(tài)成功的節(jié)點(diǎn),首節(jié)點(diǎn)的線程釋放同步狀態(tài)后會(huì)喚醒后繼節(jié)點(diǎn)o獨(dú)占式同步狀態(tài)的獲取與釋放?通過調(diào)用同步器的acquire獲取同步狀態(tài),對(duì)中斷不敏感?對(duì)線程進(jìn)行中斷操作,線程不會(huì)從隊(duì)列中移出?acquire中通過調(diào)用自定義同步器實(shí)現(xiàn)的tryacquire?獲取失敗,則構(gòu)造同步節(jié)點(diǎn)Node,通過addWaiter將改節(jié)點(diǎn)加入隊(duì)列尾部?調(diào)用acquireQueued使該節(jié)點(diǎn)以死循環(huán)的方式獲取同步狀態(tài),如果獲取不到則阻塞節(jié)點(diǎn)中的線程,通過前驅(qū)節(jié)點(diǎn)出隊(duì)來喚醒?獲取鎖并且處理完相應(yīng)邏輯之后調(diào)用同步器的release釋放同步狀態(tài)?喚醒后繼節(jié)點(diǎn)(LockSupport.unpark)o共享式同步狀態(tài)的獲取與釋放?通過調(diào)用同步去的acquireShare獲取同步狀態(tài)?acquireShare中通過調(diào)用自定義同步器tryAcquireShare方法獲取同步狀態(tài)?當(dāng)tryAcquireShare大于等于0時(shí)獲取同步狀態(tài)?調(diào)用同步器的releaseShared釋放同步狀態(tài)?必須保證安全的釋放一般使用循環(huán)和CAS保證o獨(dú)占式超時(shí)獲取同步狀態(tài)?主要計(jì)算需要睡眠的時(shí)間間隔?nanosTimeOut=now-lastTimeo如果nanosTimeOut>0則表示睡眠時(shí)間未到,需要繼續(xù)睡眠,反之超時(shí)?now為當(dāng)前喚醒時(shí)間,lastTime為上次喚醒oReentrantLock(重入鎖)?判斷當(dāng)前線程是否為獲得鎖的線程,如果是,則將同步狀態(tài)值增加并返回true?釋放鎖時(shí),只有將同步狀態(tài)修改為0才算釋放成功o公平鎖?多個(gè)hasQueuedPredecessors判斷?加入同步隊(duì)列中的當(dāng)前節(jié)點(diǎn)是否有前驅(qū)的判斷o如果返回ture說明有線程比當(dāng)前線程更早的獲取鎖,因此需要繼續(xù)等待oReentrantReadWriteLock(讀寫鎖)?按位切割使用同步變量,搞16位表示讀,低16位表示寫?LockSupport工具o基礎(chǔ)方法?park?阻塞當(dāng)前線程o如果調(diào)用unpark方法或者當(dāng)前線程被中斷,才會(huì)返回?parkNanos(longnanos)?阻塞當(dāng)前線程,最長(zhǎng)不能超過nanos納秒?parkUntil(longdeadline)?阻塞當(dāng)前線程,直到deadline時(shí)間?unpark?喚醒處于阻塞狀態(tài)的線程o和wait區(qū)別可以先調(diào)用unpark釋放一個(gè)許可證,后面線程調(diào)用park時(shí)發(fā)現(xiàn)許可證直接進(jìn)入休眠?wait方法會(huì)釋放持有的鎖,park進(jìn)入休眠后并不會(huì)釋放持有的鎖?park會(huì)響應(yīng)中斷,當(dāng)外部線程對(duì)阻塞線程調(diào)用interrupt時(shí),park阻塞線程會(huì)立即得到返回?Conditiono實(shí)現(xiàn)原理?是AQS的內(nèi)部類?等待隊(duì)列?FIFO的隊(duì)列,每個(gè)節(jié)點(diǎn)都包含了一個(gè)在condition對(duì)象上等待的線程o只保存nextWaiter,condition擁有首節(jié)點(diǎn)和尾節(jié)點(diǎn)?condition.await?該線程釋放鎖o構(gòu)造成節(jié)點(diǎn)加入等待隊(duì)列并進(jìn)入等待狀態(tài)?從AQS角度,相當(dāng)于從同步隊(duì)列的首節(jié)點(diǎn)異動(dòng)到Condition的等待隊(duì)列?Condition.signal?喚醒等待隊(duì)列中等待時(shí)間最長(zhǎng)的節(jié)點(diǎn),喚醒之前加入同步隊(duì)列?鎖在應(yīng)用層的優(yōu)化思路o減少鎖持有時(shí)間?只有需要時(shí)進(jìn)行同步o減少鎖粒度?ConcurrentHashMapo鎖分離?LinkedBlockingQueue實(shí)現(xiàn)o鎖粗化?多次加鎖合并為一次oCAS?并發(fā)容器oConcurrentHashMap?結(jié)構(gòu)?Segment數(shù)組o可重入鎖?為了通過按位與的散列算法定位到Segment數(shù)組索引,必須保證Segment數(shù)組長(zhǎng)度是2的N次方?HashEntry數(shù)組o用于存儲(chǔ)鍵值對(duì)數(shù)據(jù)?操作?
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 建筑工地基坑支護(hù)安全技術(shù)方案
- 中小企業(yè)信息化建設(shè)規(guī)劃方案
- 平安保險(xiǎn)知識(shí)培訓(xùn)
- 如何講解旅游方案
- 精益管理在醫(yī)療供應(yīng)鏈中的滲透
- 精準(zhǔn)營(yíng)養(yǎng):高血壓個(gè)體化DASH飲食方案
- 精準(zhǔn)醫(yī)療資源的優(yōu)化配置:國(guó)際模式與本地策略
- 精準(zhǔn)醫(yī)療背景下臨床技能轉(zhuǎn)化體系
- 精準(zhǔn)醫(yī)療時(shí)代復(fù)發(fā)監(jiān)測(cè)的技術(shù)革新
- 精準(zhǔn)醫(yī)療個(gè)體化健康管理的多組學(xué)方案
- 擋土墻施工培訓(xùn)
- 企業(yè)環(huán)保管理制度(2025年版)
- 各種挖機(jī)租賃合同范本
- 油料運(yùn)輸應(yīng)急預(yù)案
- 自來水維修搶修知識(shí)培訓(xùn)課件
- 化水安全操作規(guī)程
- 2025浙江紹興市新聞傳媒中心(傳媒集團(tuán))招聘6人筆試題庫(kù)歷年考點(diǎn)版附帶答案詳解
- 第四單元民族關(guān)系與國(guó)家關(guān)系(任務(wù)型復(fù)習(xí)課件)歷史統(tǒng)編版選擇性必修1
- 2025至2030中國(guó)掃雪車行業(yè)發(fā)展趨勢(shì)分析與未來投資戰(zhàn)略咨詢研究報(bào)告
- 刮板撈渣機(jī)課件
- 《城市軌道交通全自動(dòng)運(yùn)行系統(tǒng)驗(yàn)收規(guī)范》
評(píng)論
0/150
提交評(píng)論