Java基础知识详解
一、基礎(chǔ)
1、Java都有哪些數(shù)據(jù)類型?基本數(shù)據(jù)類型有哪些?分別占多少字節(jié)?多少位?引用數(shù)據(jù)類型又有哪些?
Java的數(shù)據(jù)類型:基本數(shù)據(jù)類型和引用數(shù)據(jù)類型
基本數(shù)據(jù)類型:byte(1),short(2),int(4),long(8),float(4),double(8),char(2),boolean(1)
引用數(shù)據(jù)類型:類,接口,數(shù)組
2、Java語言的幾大特性是什么?分別怎么理解?(封裝、繼承、多態(tài)的好處)繼承、封裝、多態(tài)繼承:繼承是從已有類得到繼承信息新創(chuàng)類的過程。提供繼承信息的類被稱為父類(超類、基類);得到繼承信息的類被稱為子類(派生類)。繼承讓變化中的軟件系統(tǒng)有了一定的延續(xù)性,同時繼承也是封裝程序中可變因素的重要手段。封裝:通常認為封裝是把數(shù)據(jù)和操作數(shù)據(jù)的方法綁定起來,對數(shù)據(jù)的訪問只能通過已定義的接口。面向?qū)ο蟮谋举|(zhì)就是將現(xiàn)實世界描繪成一系列的完全自治、封閉的對象。在類中編寫的方法就是對實現(xiàn)細節(jié)的一種封裝,編寫的一個類就是對數(shù)據(jù)和數(shù)據(jù)操作的封裝。可以說,封裝就是隱藏一切可隱藏的東西,只向外界提供最簡單的編程接口。多態(tài):多態(tài)性是指允許不同子類型的對象對同一消息做出不同的響應(yīng)。 簡單地說就是用同樣的對象引用調(diào)用同樣的方法,但做了不同的事情。多態(tài)性分為編譯時的多態(tài)性和運行時的多態(tài)性。如果將對象的方法視為對象向外界提供的服務(wù),那么運行時的多態(tài)性可以解釋為:當(dāng)A系統(tǒng)訪問B系統(tǒng)提供的服務(wù)時,B系統(tǒng)有多種提供服務(wù)的方式,但一切對A系統(tǒng)來說都是透明的。方法重載(overload)實現(xiàn)的是編譯時的多態(tài)性(也就是前綁定),而方法的重寫(override)實現(xiàn)的是運行時的多態(tài)性(也稱為后綁定)。運行時的多態(tài)時面向?qū)ο笞罹璧臇|西,要實現(xiàn)多態(tài)需要做兩件事:1)、方法重寫(子類繼承父類并重寫父類中已有的或抽象的方法)2)、對象造型(用父類引用引用子類對象,這樣同樣的引用調(diào)用同樣的方法就會根據(jù)子類對象的不同而表現(xiàn)出不同的行為)3、Java的權(quán)限修飾符有哪些?都能加在哪些地方?分別代表什么意義?Java的權(quán)限修飾符有4種:public、protected、default、private都能加在哪些地方:類、方法、成員變量分別代表的意義:public:公共的,任意位置都能訪問protected:當(dāng)前類、同一個包下、子類都能訪問,其他包下不能訪問default:當(dāng)前類、同一個包下可訪問,子類和其他包下不能訪問private:私有的,只能當(dāng)前類中訪問4、什么是重寫?什么是重載?重寫:重寫發(fā)生在子類和父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的返回類型;比父類被重寫方法更好訪問,不能比父類被重寫方法聲明更多的異常重載:重載發(fā)生在一個類中,同名的方法如果有不同的參數(shù)列表,則視為重載5、final關(guān)鍵字能加在哪些地方?分別代表什么?屬性:屬性不可變方法:方法不可覆蓋類:被其修飾的類不可繼承6、static關(guān)鍵字能加在哪些地方?分別代表什么?成員變量:使其變成靜態(tài)變量,該類的所以實例都將共享此變量方法:使其變成靜態(tài)方法,類加載后,便可以直接調(diào)用此方法,而不需要一個該類的實例代碼塊:類加載時,會執(zhí)行這一段代碼7、接口中可以有哪些成員?抽象類呢?接口和抽象類又有什么區(qū)別?(注意JDK1.8接口中是可以出現(xiàn)非抽象方法的:default方法、靜態(tài)方法)接口:在接口類中,成員變量必須是常量,也就是final修飾的接口中的方法默認都是 public abstract 都是抽象的抽象類:抽象方法(包含)成員變量(可包含,子類可以直接繼承)成員方法(可包含,子類可以直接繼承,提高子類的功能)常量(可包含,子類可以直接繼承)靜態(tài)方法(可擁有,子類可以直接繼承,抽象類的類名也可以直接調(diào)用)構(gòu)造方法(可包含,因為抽象類中可能包含成員變量,成員變量需要初始化和二次賦值)區(qū)別:1、接口中不能定義構(gòu)造器;抽象類中可以定義構(gòu)造器2、接口中方法全部都是抽象方法;抽象類中可以有抽象方法和具體方法3、接口中的成員都是 public 的;抽象類中的成員可以是 private、默認、protected、public4、接口中定義的成員變量實際上都是常量;抽象類中可以定義成員變量5、接口中不能有靜態(tài)方法;抽象類中可以包含靜態(tài)方法6、一個類可以實現(xiàn)多個接口;一個類只能繼承一個抽象類8、Java異常體系是什么? 運行時異常和檢查(編譯)異常有什么區(qū)別?常見的運行時異常有哪些?異常體系:Thorwable類是所以異常和錯誤的父類兩個直接子類為 Error和 Exception ,分別表示錯誤和異常。其中異常類 Exception 又分為運行時異常和編譯時異常運行時異常和檢查(編譯)異常的區(qū)別:編譯時異常:是Java要求必須處理的,如果程序在編譯時期未處理,該程序編譯時就會發(fā)生錯誤無法編譯,try...catch或throw拋出。運行時異常:是代碼在運行是才會出現(xiàn)的異常,編譯時不需要try...catch。如:除數(shù)是0,數(shù)組角標(biāo)越界,其產(chǎn)生頻繁,處理麻煩,若顯示聲明或者捕獲將會對程序的可讀性和運行效率影響很大。所以由系統(tǒng)自動檢測并將它們交給缺少的異常處理程序。如果有處理要求也可顯示捕獲。9、== 和 equals的異同?==:== 是運算符,如果比較的對象是基本數(shù)據(jù)類型,則比較的是數(shù)值是否相等;如果比較的是引用數(shù)據(jù)類型,則比較的是對象的地址值equals:equals 是方法,用來比較兩個對象的內(nèi)容是否相等equals 方法不能用于基本數(shù)據(jù)類型的變量,如果沒有對 equals 方法進行重寫,則比較的是引用類型的變量所指向的對象的地址值10、&與&&、|與||的區(qū)別?&:左右兩邊的布爾值都是true,整個表達式的值才是true&&:如果左邊的表達式的值為false,右邊的表達式會被直接短路掉,不會進行運算,整個表達式的值就是false|:左右兩邊的布爾值只要有一個為true,整個表達式的值就是true||:如果左邊的表達式的值為true,右邊的表達式會被直接短路掉,不會進行運算,整個表達式的值就是true11、String可以修改本身嗎?為什么?不可以字符串內(nèi)部其實就是一個使用final關(guān)鍵字定義的char[]數(shù)組,數(shù)組長度一但聲明則不可改變字符串一旦聲明則不可改變,變的只是引用變量所指向的對象12、StringBuffer和StringBuilder的區(qū)別是什么?StringBuilder是在單線程環(huán)境下使用的,因為它的使用方法都沒有被 synchronized 修飾,因此理論上它的效率比 StringBuffer 高13、valueOf和toString的區(qū)別?toString:變換的值是 null 的情況,則會拋出 NullPointerException 異常valueOf:會首先對轉(zhuǎn)換的對象進行非空判斷,如果為 null 則返回 "null" 字符串,以至于不拋出 NullPointerException 異常14、大量字符串用 "+" 號進行拼接效率高嗎?為什么?應(yīng)該用什么替代?為什么?不高大量字符串用 "+" 號進行拼接,每次拼接一次都會創(chuàng)建一個 StringBuilder 對象,時間和空間開銷太大大量字符串拼接可以使用 StringBuilder 中的 append() 方法代替append( )方法其實是創(chuàng)建了一個新的數(shù)組,擴大了長度,將需要添加的字符串給復(fù)制到這個新的數(shù)組中15、創(chuàng)建一個類的實例都有哪些辦法?1、new 關(guān)鍵字。工廠模式是對這種方式的包裝2、類實現(xiàn)克隆接口,克隆一個實例3、用該類的加載器,newinstance()方法。反射,反射使用實例:Spring的依賴注入、切面編程中的動態(tài)代理4、sun.misc.Unsafe類,allocateInstance()方法創(chuàng)建一個實例5、實現(xiàn)序列化接口的類,通過IO流反序列化讀取一個類,獲得實例16、Java集合的體系是什么樣的?Java集合的體系分為兩大部分:Collection 和 MapCollection 接口下常見的子類有 List、Set 接口List 接口下有 ArrayList、LinkedList 等實現(xiàn)類Set 接口下有 HashSet、LinkedHashSet、TreeSet 等實現(xiàn)類Map 接口下有 HashMap、TreeMap、Hashtable 等實現(xiàn)類17、Set和List分別有哪些特點?Set去重的原理?List 中存儲的數(shù)據(jù)是有順序,并且允許重復(fù);Set 中存儲的數(shù)據(jù)是無序的,且不允許有重復(fù)Set的去重是通過 hash 和 eq 結(jié)合實現(xiàn)的當(dāng)兩個變量的哈希值不相同時,就認為這兩個變量不同 當(dāng)兩個變量哈希值一樣時,調(diào)用 eq 方法,放返回值為 true 時,去除一個;返回 false 時,不去重18、ArrayList底層原理是什么?擴容原理?構(gòu)造方法:空參構(gòu)造:new 一個空參 ArrayList 的時候,系統(tǒng)內(nèi)部使用了一個 new Object[0]數(shù)組帶參構(gòu)造1:傳入一個 int 值,該值作為數(shù)組的長度值。如果該值小于0,則拋出一個運行時異常。如果等于0,則使用一個空數(shù)組。如果大于0,則創(chuàng)建一個長度為該值的新數(shù)組帶參構(gòu)造2:如果調(diào)用構(gòu)造方法時傳入了一個 Collection 的子類,那么先判斷該集合是否為null,為null則拋出空指針異常。如果不是null則將該集合轉(zhuǎn)為數(shù)組a,然后將該數(shù)組賦值為成員變量array,將該數(shù)組的長度作為成員變量size。add 方法:1、首先將成員變量 array 賦值給局部變量 a,將成員變量 size 賦值給局部變量 s 2、判斷集合長度 s 是否等于數(shù)組的長度(如果集合的長度已經(jīng)等于數(shù)組的長度了,說明數(shù)組已滿,該重新分配新數(shù)組了),重新分配數(shù)組的時候需要計算新分配內(nèi)存的空間大小,如果當(dāng)前的長度小于 MIN_CAPACITY_INCREMENT/2 ,(這個常量值是12,除以2就是6,也就是如果當(dāng)前集合長度小于6)則分配12個長度,如果集合長度大于6則分配當(dāng)前長度s的一半3、將新添加的 object 對象作為數(shù)組的 a[s] 個元素4、修改集合長度 size 為 s+1 5、modCotun++,該變量是父類中聲明的,用于記錄集合修改的次數(shù),記錄集合修改的次數(shù)是為了在用迭代器迭代集合時避免并發(fā)修改異常,或者說用于判斷是否出現(xiàn)并發(fā)修改異常的6、return true,這個返回值意義不大,因為一直返回true,除非報了一個運行時異常remove 方法:1、先將成員變量 array 和 size 賦值給局部變量 a 和 s2、判斷形參 index 是否大于等于集合的長度,如果成立則拋出運行時異常3、獲取數(shù)組中角標(biāo)為 index 的對象 result,該對象作為方法的返回值4、調(diào)用 System 的 arraycopy 方法,將刪除的元素后面的所有元素全部往前移一位5、因為刪了一個元素,而且集合整體向前移動了一位,因此要將集合最后一個元素置為 null,否則就會內(nèi)存泄漏6、重新給成員變量 array 和 size 賦值7、記錄修改次數(shù)8、返回刪除的元素clear 方法:如果集合長度不等于0,則將數(shù)組所有的值都為 null,然后將成員變量 size 設(shè)置為0,最后將修改記錄加119、LinkedList底層原理是什么?和ArrayList的區(qū)別是什么?LinkedList底層原理:LinkedList 的底層是通過雙向鏈表實現(xiàn)的。鏈表的單元是節(jié)點,鏈表由多個節(jié)點構(gòu)成,每個節(jié)點都包含三個部分,頭節(jié)點指向上一個節(jié)點的尾節(jié)點,中間節(jié)點指向該節(jié)點,尾節(jié)點指向下一個節(jié)點的頭節(jié)點和ArrayList的區(qū)別:1、數(shù)據(jù)結(jié)構(gòu)實現(xiàn):ArrayList是動態(tài)數(shù)組的數(shù)據(jù)結(jié)構(gòu)實現(xiàn);LinkedList是雙向鏈表的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)2、隨機訪問效率:ArrayList比LinkedList在隨機訪問的時候效率要高,因為LinkedList是線性的數(shù)據(jù)存儲方式,使用需要移動指針從前向后一次查找3、增加和刪除效率:在非首尾的增刪操作,LinkedList要比ArarryList的效率高,因為ArrayList增刪操作要影響數(shù)組內(nèi)其他數(shù)據(jù)的角標(biāo)綜合來說,在需要頻繁讀取集中的元素時,更推薦使用ArrayList,而在增刪操作比較多時,更加推薦使用LinkedList20、HashMap的底層原理是什么?擴容原理?HashMap的底層采用了一個數(shù)組,該數(shù)組的默認大小為16且每一個元素都是一個鏈表的頭節(jié)點,每當(dāng)添加一個元素,就先計算元素Key的hash值,以此確定存放在數(shù)組的位置,如果出現(xiàn)了同一hash值的元素時,這時新元素就會掛在老元素的下面,形成鏈表,當(dāng)鏈表的長度太長(>64),大于8時,鏈表就會轉(zhuǎn)換為紅黑樹,就能提高查找的效率擴容閾值:當(dāng)前容量 * 加載因子 = 閾值,默認的加載因子為0.75擴容的機制:當(dāng)數(shù)組中的元素達到閾值時,第一次擴容即16 * 0.75 = 12時,就會觸發(fā)擴容機制,擴大到元素組的2倍加載因子:- 加載因子的大小決定了HashMap的數(shù)據(jù)密度。- 加載因子越大HashMap的數(shù)據(jù)密度也大,發(fā)生碰撞的幾率越高,數(shù)組中的鏈表越容易長,造成查詢或插入的次數(shù)增多,性能下降。- 加載因子越小,就越容易觸發(fā)擴容,數(shù)據(jù)密度也就越小,發(fā)生碰撞的幾率越小,數(shù)組中的鏈表就越短,查詢和插入時比較的次數(shù)也越小,性能會更高,但是會浪費一定的內(nèi)容空間。而且經(jīng)常擴容也會影響性能,建議初始化預(yù)留大一點的空間。- 所以會將加載因子設(shè)置為0.7-0.75,此時平均檢索長度接近于常數(shù)。21、concurrentHashMap原理是什么?底層采用分段的數(shù)組+鏈表實現(xiàn),線程安全通過把整個Map分為N個Segment,可以提供相同的線程安全,但是效率提升N倍,默認提升16倍。Hashtable的synchronized是針對整張Hash表的,即每次鎖住整張表讓線程獨占,ConcurrentHashMap允許多個修改操作并發(fā)進行,其關(guān)鍵在于使用了鎖分離技術(shù)有些方法需要跨段,比如size()和containsValue(),它們可能需要鎖定整個表而而不僅僅是某個段,這需要按順序鎖定所有段,操作完畢后,又按順序釋放所有段的鎖擴容:段內(nèi)擴容(段內(nèi)元素超過該段對應(yīng)Entry數(shù)組長度的75%觸發(fā)擴容,不會對整個Map進行擴容),插入前檢測需不需要擴容,有效避免無效擴容22、JDK8對于HashMap做了哪些優(yōu)化?JDK8之前采用的是數(shù)組加鏈表,JDK8之后采用的是數(shù)據(jù)加鏈表加紅黑樹23、什么是socket?什么是IO/NIO/BIO/AIO?區(qū)別是什么?socket:socket是一個接口,在用戶進程與TCP/IP協(xié)議之間充當(dāng)中間人,完成TCP/IP協(xié)議的書寫IO:在Java中,用流的方式完成IO。所有IO都被視為單個的字節(jié)的移動,通過一個稱為Stream的對象一次移動一個字節(jié)。流I/O用于與外部世界接觸。它也在內(nèi)部使用,用于將對象轉(zhuǎn)換為字節(jié),然后再轉(zhuǎn)換回對象。NIO:NIO不需要為每個連接開啟一個線程,而是統(tǒng)一由Selector管理,當(dāng)連接沒有IO操作時,不需要阻塞線程等待數(shù)據(jù),只有當(dāng)Selector檢測到呢個Channel有有效的IO請求時,再為其開啟線程操作,節(jié)省線程的開銷,操作結(jié)束后返回結(jié)果,故為同步非阻塞。BIO:在BIO通信模式下,服務(wù)端每收到一個鏈接(socket),就會創(chuàng)建專門的線程(serverssocket)響應(yīng)該連接。這個連接會一直存在等待讀取發(fā)來的數(shù)據(jù),這個過程會阻塞搜在線程,不能做別的事,直到操作結(jié)束后返回結(jié)果值,因此這是同步阻塞。BIO模式下,服務(wù)端連接多個客戶端時,會開啟多個線程響應(yīng)連接。AIO:沒有線程阻塞,與AIO不同的是NIO會主動輪詢操作系統(tǒng)數(shù)據(jù)是否準(zhǔn)備完畢,而AIO則是等待系統(tǒng)主動通知,再去讀取數(shù)據(jù)24、什么是反射?可以用來干嘛?列舉一下反射應(yīng)用場景?什么是暴力反射?反射:00反射的核心是 JVM 在運行時才動態(tài)加載類或調(diào)用方法/訪問屬性,它不需要事先(寫代碼的時候或編譯期)知道運行對象是誰Java 中的反射首先是能夠獲取到 Java 中要反射類的字節(jié)碼,獲取字節(jié)碼有三種方法:1、Class.forName(className) 2、類名.class 3、this.getClass()然后將字節(jié)碼中的方法,變量,構(gòu)造函數(shù)等映射成相應(yīng)的Method,Filed,Constructor等類,這些類中提供了豐富的方法供使用反射的作用:1、在運行時判定任意一個對象的所屬類2、在運行時構(gòu)造任意一個類的對象3、在運行時判定任意一個類所有具有的成員變量和方法4、在運行時調(diào)用任意一個對象的方法5、生成動態(tài)代理應(yīng)用場景:反射最重要的用途就是開發(fā)各種通用框架。很多框架(比如 Spring)都是配置化的(比如通過 XML 文件配置 Bean),為了保證框架的通用性,它們可能需要根據(jù)配置文件加載不同的對象或類,調(diào)用不同的方法,這個時候就必須用到反射,運行時動態(tài)加載需要加載的對象。暴力反射:反射里的Constructor,Field,Method三個類都有一個 getDeclaredXxx 方法,可以不受權(quán)限控制的獲取類的構(gòu)造函數(shù),字段,方法,如果想要私有構(gòu)造函數(shù)創(chuàng)建對象,字段賦值,方法調(diào)用的話,會自動的訪問類的isAccessable,默認的是false,所以,想要訪問類中的私有成員的時候,就要調(diào)用setAccessable()方法,將其改為true,這樣,就可以對類中的私有成員進行操作了25、算法了解過嗎?冒泡排序、選擇排序、快排原理?冒泡排序:1、比較相鄰的元素。如果第一個比第二個大,就交換它們兩個;2、對每一對相鄰元素作同樣的工作,從開始第一對到結(jié)尾的最后一對,這樣在最后的元素應(yīng)該會是最大的數(shù);3、針對所有的元素重復(fù)以上的步驟,除了最后一個;4、重復(fù)步驟1~3,直到排序完成。選擇排序:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再從剩余未排序元素中繼續(xù)尋找最小(大)元素,再放到已排序序列的末尾。以此類推,直到所有元素均排序完畢快速排序:1、從數(shù)列中挑出一個元素,稱為 “基準(zhǔn)”(pivot);2、重新排序數(shù)列,所有元素比基準(zhǔn)值小的擺放在基準(zhǔn)前面,所有元素比基準(zhǔn)值大的擺在基準(zhǔn)的后面(相同的數(shù)可以到任一邊)。在這個分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置。這個稱為分區(qū)(partition)操作;3、遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。26、JDK1.8的新特性有哪些?(lamda表達式、stream流、函數(shù)式接口、接口中默認方法、方法引用等等)Lambda表達式,函數(shù)式接口,方法引用和構(gòu)造器調(diào)用,Stream API,接口中的默認方法和靜態(tài)方法,新時間日期API27、IO流體系1、按流向分:輸入流:程序可以從內(nèi)存中讀取數(shù)據(jù)的流輸出流:程序可以向磁盤中寫入數(shù)據(jù)的流2、按數(shù)據(jù)傳輸單位分:字節(jié)流:以字節(jié)為單位傳輸數(shù)據(jù)的流字符流:以字符為單位傳輸數(shù)據(jù)的流28、如何實現(xiàn)分布式主鍵自增?Redis和IdWork工具類
二、JVM
1、JDK和JRE的區(qū)別是什么?
JDK:開發(fā)工具
JRE:運行時環(huán)境
2、JVM內(nèi)存模型是什么樣的?1、線程隔離私有數(shù)據(jù)區(qū)1、程序計數(shù)器2、棧1、線程棧2、本地方法棧2、線程數(shù)據(jù)共享區(qū)1、堆1、新生代區(qū)2、老年代區(qū)2、方法區(qū)3、JVM雙親委派加載機制,為什么JVM這么做?有違反雙親委派的例子嗎?雙親委派加載機制:加載某個類時會先委托父加載器尋找目標(biāo)類,找不到再委托上層父加載器加載,如果所有父加載器在自己的加載類路徑下都找不到目標(biāo)類,則在自己的類加載路徑中查找并載入目標(biāo)類為什么JVM這么做:1、可以防止核心API庫被隨意篡改2、避免類的重復(fù)加載:當(dāng)父親已經(jīng)加載了該類時,就沒有必要子 ClassLoader 再加載一次,保證被加載類的唯一性違反雙親委派的例子:服務(wù)供應(yīng)商接口 SPI,常見的 SPI 有 JDBC、JNDI、JAXP 等4、類的加載流程是什么樣的,每個階段解釋一下1、加載:通過一個類的全限定名獲取該類的二進制流;將該二進制流的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)運行時數(shù)據(jù)結(jié)構(gòu);在內(nèi)存中生成該類的Class對象,作為該類的數(shù)據(jù)訪問入口;2、鏈接:驗證:驗證的目的是為了確保Class文件的字節(jié)流中的信息不會危害到虛擬機;準(zhǔn)備:準(zhǔn)備階段是為類的靜態(tài)變量分配內(nèi)存并將其初始化為默認值,這些內(nèi)存都將在方法區(qū)中進行分配。準(zhǔn)備階段不分配類中的實例變量的內(nèi)存,實例變量將會在對象實例化時隨著對象一起分配在Java堆中。解析:主要完成符號引用到直接引用的轉(zhuǎn)換動作。解析動作并不一定在初始化動作完成之前,也有可能在初始化之后。3、初始化:初始化是類加載的最后一步,真正開始執(zhí)行類中定義的Java程序代碼5、JVM的GC的主要區(qū)域以及各自的GC機制是什么樣的?GC的主要區(qū)域:堆內(nèi)存各自的GC機制:新生代區(qū):Minor GC1、當(dāng)Eden區(qū)滿了時,觸發(fā)一次MG,即:還存活的對象從Eden或者Survivor From/Survivor To區(qū)中用copy復(fù)制算法移至Survivor To/Survivor From區(qū)中Eden中剩下的待回收的對象進行回收,且存活對象的MG次數(shù)+1,當(dāng)對象上的MG次數(shù)大于15次時,該對象將會移至老年代區(qū)2、JVM每次只會使用Eden和其中的一塊Suivivor區(qū)域來為對象服務(wù),所以無論什么時候,總是有一塊Survivor區(qū)域是空閑的因此,新生代實際可用的內(nèi)存空間為90%的新生代空間,所以這種回收機制是比較浪費內(nèi)存的,優(yōu)點是簡單高效老年代區(qū):Full GC當(dāng)老年代沒有內(nèi)存空間容納新進來的對象時,觸發(fā)一次FG,即:1、首先stop the world:暫停GC回收線程外的所有線程;2、然后使用標(biāo)記-清除/整理算法,標(biāo)記出6、JVM的GC算法都有哪些?1、確定哪些是垃圾的算法:1、引用計數(shù)法:每被引用一次,引用次數(shù)+1, 弊端:無法解決對象相互循環(huán)引用而無法被回收問題2、GC Root可達性算法:從根節(jié)點出發(fā),給所有可達對象做標(biāo)記(解決對象相互循環(huán)引用而無法被回收問題)Java中可作為GC Root的對象有:1、虛擬機棧中引用的對象(本地變量表)2、方法區(qū)中靜態(tài)屬性引用的對象3、方法區(qū)中常量引用的對象4、本地方法棧中引用的對象(Native對象)2、最終回收垃圾的算法1、標(biāo)記-清除:效率較高,但最后得到的內(nèi)存空間不連續(xù)2、標(biāo)記-整理:最后得到的內(nèi)存空間是連續(xù)的,但整理壓縮耗費性能,效率較低3、復(fù)制算法:將內(nèi)存空間分為兩塊,每次只使用其中的一塊,回收時,將存活的對象復(fù)制到另一塊中,簡單高效,但是浪費內(nèi)存空間針對以上的回收算法的利弊,引出分代算法,新生代區(qū)使用復(fù)制算法,老年代區(qū)使用標(biāo)記-清除/標(biāo)記-整理算法
三、Spring & SpringBoot
1、說下對SpringIOC的理解,怎么理解控制反轉(zhuǎn)?IOC容器中Bean的生命周期?
IOC:
是spring的核心,Ioc意味著將你設(shè)計好的對象交給容器控制,而不是傳統(tǒng)的在對象內(nèi)部直接控制
控制反轉(zhuǎn):
所有的類都會在spring容器中登記,告訴spring你是什么,你需要什么,然后spring會在系統(tǒng)運行到適當(dāng)?shù)臅r候,把你要的東西主動給你,
同時也把你交給其他需要你的東西。
所有的類的創(chuàng)建、銷毀都由spring來控制,也就是說控制對象生存周期的不再是引用它的對象,而是spring。
對于某個具體的對象而言,以前是它控制其他對象,現(xiàn)在是所有對象都被spring控制,所以這叫控制反轉(zhuǎn)
生命周期:
1、通過構(gòu)造器或工廠方法創(chuàng)建Bean的實例
2、為Bean的屬性賦值或?qū)ζ渌鸅ean的引用
3、調(diào)用Bean的初始化方法4、使用Bean5、當(dāng)容器關(guān)閉時,調(diào)用Bean的銷毀方法2、Spring如何解決IOC中的循環(huán)依賴問題?三級緩存。比如說:實例化A的時候,先將A創(chuàng)建(早期對象)放入一個池子中。這個時候雖然屬性沒有賦值,但是容器已經(jīng)能認識這個是A對象,只是屬性全是null而已。在populateBean 方法中對屬性賦值的時候,發(fā)現(xiàn)A依賴了B,那么就先去創(chuàng)建B了,又走一遍bean的創(chuàng)建過程(創(chuàng)建B)。同樣也會把B的早期對象放入緩存中。當(dāng)B又走到 populateBean 方法的時候,發(fā)現(xiàn)依賴了A,又去創(chuàng)建A,但是這個時候去創(chuàng)建A,發(fā)現(xiàn)我們在緩存能找到A(早期對象)。就可以把B的A屬性賦值了,這個時候B就初始化完成了。現(xiàn)在回到A調(diào)用的populateBean方法中。返回的就是B對象了,對A的B屬性進行賦值就可以了。3、說下對SpringAOP的理解、有哪些通知?使用場景有哪些?(底層原理:兩種動態(tài)代理)AOP 面向切面編程:將與業(yè)務(wù)無關(guān),卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯封裝起來,便于減少系統(tǒng)的重復(fù)代碼,降低模塊間的耦合度,并有利于可操作性和可維護性有哪些通知:1、前置通知:在目標(biāo)方法執(zhí)行之前執(zhí)行執(zhí)行的通知2、環(huán)繞通知:在目標(biāo)方法執(zhí)行之前和之后都可以執(zhí)行額外代碼的通知3、后置通知:在目標(biāo)方法執(zhí)行之后執(zhí)行的通知4、異常通知:在目標(biāo)方法拋出異常時執(zhí)行的通知5、最終通知:最終通知無論如何都會在目標(biāo)方法調(diào)用過后執(zhí)行,即使目標(biāo)方法沒有正常的執(zhí)行完成使用場景有哪些:事務(wù)、日志、緩存4、說下SpringMvc的流程(從訪問一個URL到得到頁面結(jié)果的具體流程:DispatcherServlet的職責(zé)流程)1、用戶發(fā)送請求至前端控制器DispatcherServlet2、前端控制器DispatcherServlet收到請求調(diào)用HandlerMapping處理器映射器3、處理器映射器找到具體的處理器(可以根據(jù)xml配置、注解進行查找),生成處理器對象及處理器攔截器(如果有則生成),一并返回給DispatcherServlet4、DispatcherServlet調(diào)用HandlerAdapter處理器適配器5、HandlerAdapter經(jīng)過適配調(diào)用具體的處理器(Controller,也叫后端控制器)6、Controller執(zhí)行完成返回ModelAndView7、HandlerAdapter將controller執(zhí)行結(jié)果ModelAndView返回給DispatcherServlet8、DispatcherServlet將ModelAndView傳給ViewReslover視圖解析器9、ViewReslover解析后返回具體View10、DispatcherServlet根據(jù)View進行渲染視圖(即將模型數(shù)據(jù)填充至視圖中)11、DispatcherServlet響應(yīng)用戶5、對Spring聲明式事務(wù)的理解?Spring的事務(wù)隔離級別?Spring事務(wù)傳播行為?理解:Spring事務(wù)的本質(zhì)其實就是數(shù)據(jù)庫對事務(wù)的支持,沒有數(shù)據(jù)庫的事務(wù)支持,spring是無法提供事務(wù)功能的Spring的事務(wù)隔離級別:默認、讀未提交、讀已提交、可重復(fù)讀、串行化Spring事務(wù)傳播行為:1、required(默認屬性)<必須的>如果存在一個事務(wù),則支持當(dāng)前事務(wù),如果沒有事務(wù),則開啟一個新的事務(wù)2、Mandatory <強制的>支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就拋出異常3、Never <從不>以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常4、Not_supports <不支持>以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起5、requires_new <需要新的>新建事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起6、Supports <支持>支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就以非事務(wù)方式執(zhí)行7、Nested <嵌套?>支持當(dāng)前事務(wù),新增Savepoint點,與當(dāng)前事務(wù)同步提交或者回滾6、什么情況下會讓spring事務(wù)失效1、發(fā)生自調(diào)用,類里面使用this調(diào)用本類中的方法,此時這個this不是代理對象,所以事務(wù)失效2、方法不是public的3、數(shù)據(jù)庫不支持事務(wù)4、沒有被spring管理5、異常被try、catch,事務(wù)不會回滾7、Spring有哪些核心注解?分別的作用?@Controller:Web控制器模式注解@Service:服務(wù)模式注解@Configuration:配置類模式注解@Component:通用組件模式注解@Autowired: Bean依賴注入,支持多種依賴查找方式@Bean:替換XML元素<bean/>@Import:限定@Autowired依賴注入范圍(導(dǎo)入對應(yīng)的 @Configuration 標(biāo)識類)@ComponentScan:掃描制定package下標(biāo)注Spring模式注解的類8、Spring和SpringBoot的關(guān)系?Spring Boot不是一門新技術(shù)。從本質(zhì)上來說,Spring Boot就是Spring,它做了一些對Spring Bean的默認配置。它消除了設(shè)置 Spring 應(yīng)用程序所需的 XML配置,為更快,更高效的開發(fā)生態(tài)系統(tǒng)鋪平了道路。9、SpringBoot的自動裝配原理是什么?@EnableAutoConfiguration 這個注解通過 @springbootapplication 這個注解被間接的標(biāo)記在了springboot的啟動類上,在springapplication.run(…)的內(nèi)部就會執(zhí)行selectimports()方法,找到所有javaconfig自動配置類的全限定類名對應(yīng)的class,然后將所有的自動配置類加載到spring容器中10、SpringBoot的核心注解是哪個?詳細說下核心注解是@SpringBootApplication,它主要由 @SpringBootConfiguration,@EnableAutoConfiguration、@ComponentScan 這三個構(gòu)成@SpringBootConfiguration:里面就只有一個 @Configuration 主要注解,也就是把該類變成一個配置類所以 @SpringBootConfiguration 就相當(dāng)于 @Configuration@EnableAutoConfiguration:是由 @AutoConfigurationPackage 和 @Import(EnableAutoConfigurationImportSelector.class) 這兩個組成的@AutoConfigurationPackage :是自動配置包,包括了一個@Import注解,給容器導(dǎo)入了自動配置包的注冊器AutoConfigurationPackages.Registrar.class:將主啟動類的所在包及包下面所有子包里面的所有組件掃描到Spring容器@Import(AutoConfigurationImportSelector.class):導(dǎo)入自動配置導(dǎo)入選擇器組件AutoConfigurationImportSelector.class:自動配置導(dǎo)入選擇器,主要是從類路徑下的META-INF/spring.factories中獲取資源@ComponentScan:掃描包,該注解默認會掃描該類所在的包下所有的配置類11、SpringBoot項目的啟動加載流程大概說下第一部分: SpringApplication初始化模塊,配置一些基本的環(huán)境變量、資源、監(jiān)聽器、構(gòu)造器第二部分:實現(xiàn)了應(yīng)用具體的啟動方案,包括流程的監(jiān)聽模塊,加載配置環(huán)境模塊以及上下文環(huán)境模塊第三部分:自動化配置模塊,這個模塊是實現(xiàn)SpringBoot的自動裝配12、SpringBoot項目讀取配置文件的方式有幾種?@Value@ConfigurationProperties13、如何自定義SpringBoot starter?1、引入 SpringBoot 自動化配置依賴2、創(chuàng)建配置屬性類3、創(chuàng)建 Starter 包的服務(wù)類4、創(chuàng)建自動配置類5、配置 spring.factories
四、Mysql & Mybatis?
1、什么是索引?
本質(zhì)是幫助MySQL高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)
2、Mysql的數(shù)據(jù)結(jié)構(gòu)是什么(mysql索引的數(shù)據(jù)結(jié)構(gòu))?為什么用這種結(jié)構(gòu)?(如何提高磁盤IO效率)Mysql的數(shù)據(jù)結(jié)構(gòu):MySql中主要應(yīng)用的索引數(shù)據(jù)結(jié)構(gòu)為B+Tree為什么用這種結(jié)構(gòu):由于數(shù)據(jù)存儲于物理磁盤,所以要盡量減少從磁盤IO數(shù)據(jù)的次數(shù)IO次數(shù)取決于B+Tree的高度B+Tree把真實的數(shù)據(jù)放到葉子節(jié)點,數(shù)據(jù)項占的空間越小,數(shù)據(jù)項的數(shù)量越多,樹的高度越低3、Mysql的數(shù)據(jù)IO查找流程是什么樣的?1、對于聚集索引(主鍵索引)來說,也就是通過主鍵查詢,一次查詢就能查詢到具體的行數(shù)據(jù)信息;2、對于非聚集索引來說(唯一索引、普通索引、全文索引),如果需要查詢的數(shù)據(jù)列在索引中,如A+B聯(lián)合索引,根據(jù)A去查詢B,則通過一次查詢就能直接拿到索引上的數(shù)據(jù),也就是覆蓋索引現(xiàn)象;如果需要查詢的數(shù)據(jù)不在索引中,則需要先去普通索引樹中進行第一次查找得到行數(shù)據(jù)的主鍵值,然后通過主鍵值去主鍵索引樹中第二次搜索得到真實數(shù)據(jù),這種需要二次查詢的現(xiàn)象叫做回表查詢4、B+tree和Btree由什么組成?他們的異同?異同:1、B+tree是Btree的變體2、在Btree的基礎(chǔ)上增加了葉子節(jié)點的順序訪問指針,B+Tree提高了順序訪問的性能3、Btree每個節(jié)點的指針上限為2d+1,B+Tree每個節(jié)點的指針上限為2d4、B+Tree非葉子節(jié)點只存儲索引值,葉子節(jié)點存儲真實數(shù)據(jù),Btree所有節(jié)點上都存儲數(shù)據(jù)5、Mysql兩種存儲引擎(InnoDB和Mysiam)的區(qū)別?這兩種引擎B+tree的葉子結(jié)點和非葉子結(jié)點分別存儲的什么?區(qū)別:1、InnoDB支持事務(wù)和外鍵,MySIAM不支持2、InnoDB支持行鎖,MySIAM只支持表鎖3、InnoDB的真實數(shù)據(jù)和索引都存儲在同一個文件中,MMySIAM存儲在兩個文件中4、InnoDB不支持全文索引,MySIAM支持InnoDB:葉節(jié)點data域保存了完整的數(shù)據(jù)記錄9+6+99999+MySIAM:葉節(jié)點的data域存放的是數(shù)據(jù)記錄的地址6、Mysql索引有哪些類型?什么場景使用哪種索引?普通索引、唯一索引、主鍵索引、聯(lián)合索引、全文索引7、如何進行Mysql優(yōu)化?(sql優(yōu)化層面和服務(wù)器優(yōu)化層面)SQL層面:1、盡量避免使用select *2、規(guī)范sql語句大小寫,sql時有緩存的,避免每次都需要解析3、使用exsits代替in4、mysql sql解析執(zhí)行過程是從右到左,from后面能過濾掉更多數(shù)據(jù)的基礎(chǔ)表放在后面,where后面能過濾掉更多數(shù)據(jù)的查詢條件放在后面5、查詢條件中用相同類型去查詢,比如避免數(shù)值列用字符串查詢條件6、合理使用索引7、explain命令進行sql慢查詢排查服務(wù)器優(yōu)化層面:1、讀寫分離:主節(jié)點寫,從節(jié)點讀2、分庫:根據(jù)業(yè)務(wù)或者其他維度把數(shù)據(jù)存放到不同數(shù)據(jù)庫3、分表:1、水平分表:字段都一樣,分多張表存放不同時間范圍或不同維度的數(shù)據(jù),如實時數(shù)據(jù)表、歷史數(shù)據(jù)表2、垂直分表:將不同字段放在多張表,使用外鍵關(guān)聯(lián)4、常用分庫分表中間件:阿里的Cobar及開源社區(qū)基于Cobar維護的Mycat8、Sql調(diào)優(yōu)你會從何入手(措施)?explain命令進行sql慢查詢排查:1、id:select查詢的序列號,包含一組數(shù)字,表示查詢中執(zhí)行select子句或操作表的順序,id相同,執(zhí)行順序從上至下,id值越大,優(yōu)先級越高,越先執(zhí)行2、select_type:查詢類型 SIMPLE、PRIMARY、SUBQUERY、DERIVED、UNION、UNION RESULTSIMPLE:表示簡單杳詢,其中不包括連接查詢和子查詢;PRIMARY:表示主查詢,或者最外層的查詢語句;SUBQUERY:子查詢中的第一個SELECT語句;DERIVED:導(dǎo)出表的SELECT (FROM語句的子查詢);UNION:表示連接查詢的第2個或后面的查詢語句;UNION RESULT:連接查詢的結(jié)果;3、table:正在訪問哪個表4、partitions:匹配的分區(qū)5、type:訪問的類型,效率從快到慢:NULL>system>const>eq_ref>ref>ref_or_null>index_merge>range>index>ALL6、possible_keys:顯示可能應(yīng)用在這張表中的索引,一個或多個,但不一定實際使用到7、key:實際使用到的索引,如果為NULL,則沒有使用索引8、key_len:表示索引中使用的字節(jié)數(shù),可通過該列計算查詢中使用的索引的長度9、ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數(shù),哪些列或常量被用于查找索引列上的值10、rows:根據(jù)表統(tǒng)計信息及索引選用情況,大致估算出找到所需的記錄所需讀取的行數(shù),這個數(shù)量越小越好11、filtered:查詢的表行占表的百分比12、Extra:包含不適合在其它列中顯示但十分重要的額外信息9、Mysql中如何合理使用索引?有哪些會使索引失效的情況?何合理使用索引1、為合適的列添加索引(主鍵、唯一索引、組合索引)2、盡量建立聯(lián)合索引,也省空間成本3、盡量使用覆蓋索引4、避免會使索引失效的操作會使索引失效的情況:1、索引列有null值不走索引2、使用is null或is not null不走索引3、各種負向查詢not ,not in, not like ,<> ,!= ,!> ,!< 不會使用索引4、like將%放左邊不走索引5、查詢條件的數(shù)據(jù)類型做了隱式轉(zhuǎn)換6、使用in或union代替or,or兩側(cè)有非索引列就不會走索引7、盡量保持索引列干凈,不在索引列上使用函數(shù)轉(zhuǎn)換、運算8、聯(lián)合索引要遵循最左匹配原則9、使用比較運算或between會使聯(lián)合索引從使用比較運算的下一個索引處斷開10、Mysql如何排查慢查詢(哪個關(guān)鍵字)?分別會列出來哪些信息項?explain命令進行sql慢查詢排查:1、id:select查詢的序列號,包含一組數(shù)字,表示查詢中執(zhí)行select子句或操作表的順序,id相同,執(zhí)行順序從上至下,id值越大,優(yōu)先級越高,越先執(zhí)行2、select_type:查詢類型 SIMPLE、PRIMARY、SUBQUERY、DERIVED、UNION、UNION RESULTSIMPLE:表示簡單杳詢,其中不包括連接查詢和子查詢;PRIMARY:表示主查詢,或者最外層的查詢語句;SUBQUERY:子查詢中的第一個SELECT語句;DERIVED:導(dǎo)出表的SELECT (FROM語句的子查詢);UNION:表示連接查詢的第2個或后面的查詢語句;UNION RESULT:連接查詢的結(jié)果;3、table:正在訪問哪個表4、partitions:匹配的分區(qū)5、type:訪問的類型,效率從快到慢:NULL>system>const>eq_ref>ref>ref_or_null>index_merge>range>index>ALL6、possible_keys:顯示可能應(yīng)用在這張表中的索引,一個或多個,但不一定實際使用到7、key:實際使用到的索引,如果為NULL,則沒有使用索引8、key_len:表示索引中使用的字節(jié)數(shù),可通過該列計算查詢中使用的索引的長度9、ref:顯示索引的哪一列被使用了,如果可能的話,是一個常數(shù),哪些列或常量被用于查找索引列上的值10、rows:根據(jù)表統(tǒng)計信息及索引選用情況,大致估算出找到所需的記錄所需讀取的行數(shù),這個數(shù)量越小越好11、filtered:查詢的表行占表的百分比12、Extra:包含不適合在其它列中顯示但十分重要的額外信息11、事務(wù)的特性是什么?Mysql事務(wù)隔離級別有哪幾種?分別會產(chǎn)生什么問題?Mysql默認隔離級別是什么?Oracle呢?事務(wù)的特性:原子性、一致性、隔離性、永久性Mysql事務(wù)隔離級別:讀未提交、不可重復(fù)讀、可重復(fù)讀、串行化分別會產(chǎn)生什么問題:讀未提交:一個事物讀到了另一個事務(wù)尚未提交的數(shù)據(jù),不符合事務(wù)的隔離性不可重復(fù)讀:同一個事務(wù)中針對同一行記錄兩次讀出來的結(jié)果不一樣,原因就是第二次讀到了其他事務(wù)修改提交的數(shù)據(jù)可重復(fù)讀:同一個事務(wù)中針對同一范圍內(nèi)的數(shù)據(jù)兩次讀出來的結(jié)果不一樣,原因就是第二次讀到了其他事務(wù)新增提交的數(shù)據(jù)mysql默認隔離級別:可重復(fù)讀,但是一般會設(shè)置為不可重復(fù)讀,因為在實際業(yè)務(wù)中常常是,一個事務(wù)中需要讀到別的事務(wù)提交修改的數(shù)據(jù)oraclel默認隔離級別:不可重復(fù)讀12、Mysql的行鎖、表鎖,悲觀鎖、樂觀鎖?行鎖:訪問數(shù)據(jù)庫的時候,鎖定整個行數(shù)據(jù),防止并發(fā)錯誤。表鎖:訪問數(shù)據(jù)庫的時候,鎖定整個表數(shù)據(jù),防止并發(fā)錯誤。樂觀鎖:樂觀的認為本次事務(wù)操作數(shù)據(jù)不會有別的事務(wù)干擾,操作數(shù)據(jù)前不進行加鎖,只是預(yù)先記錄版本號,真正修改數(shù)據(jù)時再進行比對,如果版本號沒變則修改數(shù)據(jù),版本號變了則表名別的事務(wù)在本次事務(wù)過程中修改了數(shù)據(jù),本次事務(wù)不修改數(shù)據(jù)。悲觀鎖:悲觀的認為本次事務(wù)一定會有別的事務(wù)干擾,操作數(shù)據(jù)前必須先加鎖13、Mysql的vachar和char的區(qū)別?vachar:長度為可變的,實際使用多少空間就占多少空間。char:列長度固定,為創(chuàng)建表時聲明的長度,長度值范圍是1到255,當(dāng)char值未填滿指定長度時,其他空間會用空格進行填充,檢索CHAR值時需刪除尾隨空格。14、什么是內(nèi)連接(inner join)、外連接(left join)?內(nèi)連接:只顯示左右兩表中匹配條件的行,在結(jié)果表中刪除與其他被連接表中沒有匹配行的所有行左外連接:把左邊表的數(shù)據(jù)全部取出來,而右邊表的數(shù)據(jù)有相等的,顯示出來,如果沒有,顯示NULL15、平時Mysql的sql練習(xí)要練到位!!牛客網(wǎng),練習(xí)SQL語句16、Mybatis底層的原理?一級緩存和二級緩存是什么?Mybatis底層的原理:動態(tài)代理一級緩存:Mybatis中sqlSession對象的緩存,當(dāng)執(zhí)行查詢以后,查詢的結(jié)果會同時存入到Sql++++ Session提供的一塊區(qū)域中,該區(qū)域的結(jié)構(gòu)是一個Map,當(dāng)我們再次查詢同樣的數(shù)據(jù),mybatis會先去sqlsession中查詢是否有,的話直接拿出來用,當(dāng)SqlSession對象消失時,mybatis的一級緩存也就消失了,同時一級緩存是SqlSession范圍的緩存,當(dāng)調(diào)用SqlSession的修改、添加、刪除、commit(),close等方法時,就會清空一級緩存。二級緩存:Mybatis中SqlSessionFactory對象的緩存,由同一個SqlSessionFactory對象創(chuàng)建的SqlSession共享其緩存,但是其中緩存的是數(shù)據(jù)而不是對象17、mybatis #{}和${}的區(qū)別?#{}方式能夠很大程度防止sql注入${}的方式無法防止Sql注入18、Mysql存儲過程、存儲函數(shù)、觸發(fā)器分別用來干嘛的?創(chuàng)建語法是什么? 存儲過程:存儲過程把經(jīng)常使用的SQL語句或業(yè)務(wù)邏輯封裝起來,預(yù)編譯保存在數(shù)據(jù)庫中,當(dāng)需要時從數(shù)據(jù)庫中直接調(diào)用,省去了編譯的過程。提高了運行速度同時降低網(wǎng)絡(luò)數(shù)據(jù)傳輸量存儲函數(shù):參數(shù)可以有多個,也可以沒有參數(shù),必須有且只有一個返回值觸發(fā)器:觸發(fā)器的執(zhí)行不是由程序調(diào)用,也不是由手工啟動,而是由事件來觸發(fā)、激活從而實現(xiàn)執(zhí)行19、union和unionAll有什么區(qū)別?Union:對兩個結(jié)果集進行并集操作,不包括重復(fù)行,同時進行默認規(guī)則的排序在進行表鏈接后會篩選掉重復(fù)的記錄,所以在表鏈接后會對所產(chǎn)生的結(jié)果集進行排序運算,刪除重復(fù)的記錄再返回結(jié)果Union All:對兩個結(jié)果集進行并集操作,包括重復(fù)行,不進行排序如果返回的兩個結(jié)果集中有重復(fù)的數(shù)據(jù),那么返回的結(jié)果集就會包含重復(fù)的數(shù)據(jù)了20、創(chuàng)建表、刪除表、更新表字段語句?、創(chuàng)建表:create table 表名刪除表:drop table 表名更新表字段:修改字段名稱:ALTER TABLE 表名 CHANGE 舊字段名 新字段名 數(shù)據(jù)類型;修改字段數(shù)據(jù)類型:ALTER TABLE 表名 MODIFY 字段名 新數(shù)據(jù)類型;21、mysql左外連接語句的寫法?Select A.name,B.name from A Left Join B on A.id=B.id;22、聽過InnoDB的Mvcc技術(shù)嗎?說下是什么?Mvcc:多版本并發(fā)控制技術(shù),它使得大部分支持行鎖的事務(wù)引擎,不再單純的使用行鎖來進行數(shù)據(jù)庫的并發(fā)控制,取而代之的是把數(shù)據(jù)庫的行鎖與行的多個版本結(jié)合起來,只需要很小的開銷,就可以實現(xiàn)非鎖定讀,從而大大提高數(shù)據(jù)庫系統(tǒng)的并發(fā)性能23、Java實現(xiàn)動態(tài)代理有哪些方式?區(qū)別是什么?Java實現(xiàn)動態(tài)代理有哪些方式:jdk動態(tài)代理、cglib動態(tài)代理區(qū)別:jdk動態(tài)代理是由java內(nèi)部的反射機制來實現(xiàn)的,cglib動態(tài)代理底層則是借助asm來實現(xiàn)的。總的來說,反射機制在生成類的過程中比較高效,而asm在生成類之后的相關(guān)執(zhí)行過程中比較高效。還有一點必須注意:jdk動態(tài)代理的應(yīng)用前提,必須是目標(biāo)類基于統(tǒng)一的接口。如果沒有上述前提,jdk動態(tài)代理不能應(yīng)用。由此可以看出,jdk動態(tài)代理有一定的局限性,cglib這種第三方類庫實現(xiàn)的動態(tài)代理應(yīng)用更加廣泛,且在效率上更有優(yōu)勢。
五、多線程
1、創(chuàng)建線程的方式有哪些?相比繼承Thread類,實現(xiàn)Runable接口的好處是什么?
創(chuàng)建線程的方式:
1、實現(xiàn)Runnable接口
2、繼承Thread類
好處:
1、適合多個相同程序代碼的線程去處理同一個資源
2、可以避免由于Java的單繼承性帶來的局限性
3、增強了程序的健壯性,代碼能夠被多個線程共享,代碼與數(shù)據(jù)是獨立的
2、線程的狀態(tài)有哪些?1、新建狀態(tài)2、就緒狀態(tài)3、運行狀態(tài)4、阻塞狀態(tài)5、死亡狀態(tài)3、run()和start()方法有哪些區(qū)別?run():是來完成實際的業(yè)務(wù)邏輯,當(dāng)run()方法結(jié)束后,此線程就會終止start():是用來開啟一個線程的,使線程處于就緒狀態(tài),即可以被JVM來調(diào)度執(zhí)行4、實現(xiàn)線程間通訊的方法有哪些?1、wait():讓線程處于凍結(jié)狀態(tài),被wait的線程會被存儲到線程池中2、notify():喚醒線程池中的一個線程3、notifyAll():喚醒線程池中的所有線程5、wait、notify、notifyAll分別的作用是什么?可以用在同步代碼塊之外嗎?為什么?分別的作用:wait():讓線程處于凍結(jié)狀態(tài),被wait的線程會被存儲到線程池中notify():喚醒線程池中的一個線程notifyAll():喚醒線程池中的所有線程可以用在同步代碼塊之外嗎:不行為什么:因為這些方法是用于操作線程狀態(tài)的方法,必須要明確到底操作的是哪個鎖上的線程6、Sleep和Wait的區(qū)別?sleep():1、屬于Thread類,表示讓一個線程進入睡眠狀態(tài),等待一定的時間之后,自動醒來進入到可運行狀態(tài),不會馬上進入運行狀態(tài)2、sleep方法沒有釋放鎖3、sleep必須捕獲異常4、sleep可以在任何地方使用wait:1、屬于Object,一旦一個對象調(diào)用了wait方法,必須采用notify()和notifyAll()方法喚醒該進程2、wait方法釋放了鎖3、wait不需要捕獲異常4、wait、notify、notifyAll只能在同步控制方法或者同步控制塊中使用7、什么是線程安全問題?什么情況下會產(chǎn)生?如何解決?線程安全問題:多個線程同時訪問共享數(shù)據(jù)時可能會出現(xiàn)問題,稱為線程安全問題什么情況下會產(chǎn)生:當(dāng)多線程訪問共享數(shù)據(jù)時,由于CPU的切換,導(dǎo)致一個線程只執(zhí)行了關(guān)鍵代碼的一部分,還沒執(zhí)行完此時另一個線程參與進來,導(dǎo)致共享數(shù)據(jù)發(fā)生異常如何解決:通過線程同步機制synchronized + 鎖來解決線程安全問題8、什么是死鎖?如何防止產(chǎn)生死鎖?什么是死鎖:死鎖是指兩個或兩個以上的進程在執(zhí)行過程中,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無外力作用,它們都將無法推進下去如何防止產(chǎn)生死鎖:1、設(shè)置超時時間2、使用JUC包提供的并發(fā)類,而不是自己設(shè)計鎖3、盡量降低鎖的粒度4、盡量使用同步代碼塊,而不是同步方法5、給線程其有意義的名字6、避免的嵌套7、分配鎖資源之前先看能不能回收回來資源8、專鎖專用9、Synchronized關(guān)鍵字的底層原理是什么?當(dāng)一個線程第一次運行到 synchronized 代碼,獲取到了 myObject 對象的 monitor 的鎖,然后計數(shù)器就會加1,然后第二次運行到 synchronized 代碼,會再次獲取 myObject 對象的 monitor 的鎖,這個就是重入加鎖了,然后計數(shù)器會再次加1,變成2,這個時候,其他的線程運行到第一次 synchronized 代碼,會發(fā)現(xiàn) myObject 對象的 monitor 鎖的計數(shù)器是大于0的,就意味著被別人給加鎖了,然后此時線程就會進入 block 阻塞狀態(tài),什么都干不了,就是等待獲取鎖如果第一個線程出了 synchronized 修飾范圍的話,就會有一個 moninorexit 的指令,此時,在底層獲取鎖的線程就會對那個對象的 monitor 的計數(shù)器減1,如果有多次重入加鎖,就會對應(yīng)多次減1,直到最后,計數(shù)器是0然后,后面 block 阻塞的線程,會再次嘗試獲取鎖,但是只有一個線程可以獲取鎖10、Synchronized可以用在哪些地方?分別的鎖對象是什么?1、同步代碼塊:鎖對象為括號中的對象2、同步方法:鎖對象為當(dāng)前對象this3、靜態(tài)同步方法:鎖對象為class字節(jié)碼文件對象11、Synchronized和JUC下Lock鎖的異同?1、Lock是JUC包下提供的封裝好的鎖,是類的概念,而synchronized是一個虛擬機層面的關(guān)鍵字。2、Lock顯示的加鎖和解鎖,且解鎖要在finally代碼塊中,否則可能會死鎖,而synchronized為隱式的上鎖和解鎖。3、Lock鎖提供了嘗試獲取鎖和設(shè)置獲取鎖時間的機制,可返回取鎖狀態(tài),當(dāng)獲取不到鎖的時候也可以選擇放棄取鎖,而synchronized無法判斷返回取鎖狀態(tài),取鎖不成功只能阻塞,沒有Lock靈活。4、Lock鎖阻塞可被打斷,而synchronized阻塞不可被打斷。5、Lock可實現(xiàn)可重入、可公平鎖,而synchronized是可重入、非公平鎖。6、Lock可以很靈活的根據(jù)線程角色類型去創(chuàng)建Condition監(jiān)視器對象,調(diào)用await()、signal()、signalAll()進行線程通訊調(diào)度,而synchronized使用Object對象本身作為監(jiān)視器對象去調(diào)用wait() 、notify()、notifyAll()進行線程通訊調(diào)度。7、Lock提供了更豐富的鎖分類,如讀鎖、寫鎖,可以更細粒度的關(guān)注線程安全問題。13、Synchronized在JDK1.6做了什么優(yōu)化?自適應(yīng)的CAS自旋、鎖消除、鎖粗化、偏向鎖、輕量級鎖12、Synchronized是公平鎖還是非公平鎖?獲取不到鎖時會阻塞嗎?非公平,會阻塞13、同步代碼塊中執(zhí)行完wait/notify/notifyAll后會立馬釋放鎖嗎?不會,必須等其所在的同步代碼塊執(zhí)行完才會釋放鎖14、Lock鎖有哪些實現(xiàn)?分別的特點是什么?1、ReentrantLock2、ReentrantReadWriteLock類中的靜態(tài)內(nèi)部類ReadLock(讀-寫鎖)3、ReentrantReadWriteLock類中的靜態(tài)內(nèi)部類WriteLock(讀-寫鎖)15、JUC下Lock的監(jiān)視器對象是哪個類?與Synchronized的監(jiān)視器有什么異同?JUC下Lock的監(jiān)視器對象:Condition異同:Lock可以很靈活的根據(jù)線程角色類型去創(chuàng)建Condition監(jiān)視器對象,調(diào)用await()、signal()、signalAll()進行線程通訊調(diào)度,而synchronized使用Object對象本身作為監(jiān)視器對象去調(diào)用wait() 、notify()、notifyAll()進行線程通訊調(diào)度。16、什么是線程可重入?Synchronized具備嗎?Lock呢?重入鎖就是一個線程能否獲取一個已經(jīng)由它自己持有的鎖。如果可以,就是可重入鎖,否則為不可重入鎖。它的作用就是能夠避免重復(fù)獲取的時候出現(xiàn)死鎖synchronized 是可重入鎖Lock 是可重入鎖17、什么是AQS?是一個用于構(gòu)建鎖和同步容器的隊列同步器,它是整個JUC包下Lock體系的核心,如ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Semaphore都是基于它來實現(xiàn)的,它解決了在實現(xiàn)同步容器時設(shè)計的大量細節(jié)問題,它的核心構(gòu)成部分為:使用一個 先進先出的FIFO的隊列存儲排隊等待鎖的線程,使用一個用volatile修飾的int類型的state同步狀態(tài)來記錄當(dāng)前是否有線程持有鎖,0表示沒有線程獲得鎖,1表示有,上鎖state就加1,釋放鎖就對應(yīng)減1,有重入鎖現(xiàn)象,這個值就大于1,然后需要逐級去釋放。18、什么是CAS?什么是CAS的ABA問題?如何解決?CAS:CAS其實就是樂觀鎖的一種實現(xiàn)方式ABA問題:1、線程1讀取出指定內(nèi)存地址的數(shù)據(jù)A,加載到寄存器,此時讀取出來的原值不僅將作為要被計算的值A(chǔ),還會作為比較值A(chǔ)。2、此時線程1的cpu被線程2搶占了,線程2也從同樣的內(nèi)存地址中讀取了同樣的數(shù)據(jù)A,線程2還比線程1先執(zhí)行完,線程2產(chǎn)生了新數(shù)據(jù)B,并且遵守了CAS原理把新數(shù)據(jù)B存入該內(nèi)存地址。 (這個時候內(nèi)存的值由A被改為B)3、還沒完,線程2執(zhí)行完之后,線程1又沒搶過其它線程,此時cpu被線程3搶占,之后步驟和第 2 步一樣,線程3從同樣的內(nèi)存地址中讀取了數(shù)據(jù)B,線程3還比線程1先執(zhí)行完,線程3產(chǎn)生了新數(shù)據(jù)A(沒錯,與一開始的A相等,但值相等并不意味著此A就是彼A,已經(jīng)被替換了),并且遵守了CAS原理把新數(shù)據(jù)A存入該內(nèi)存地址。(這個時候內(nèi)存的值由B又變?yōu)锳)4、這個時候線程1執(zhí)行完了,要遵守CAS原理存入數(shù)據(jù),然后比較值A(chǔ)是原來的A(簡稱原A),而執(zhí)行內(nèi)存地址中的A是被替換過的了,但原A的值與內(nèi)存中的A值是相等的,根據(jù)CAS,線程1會把新的執(zhí)行結(jié)果存入該內(nèi)存地址在實際業(yè)務(wù)中,兩個數(shù)的值相等,但這兩個數(shù)并不是同一個數(shù)解決方案:加個版本號,多一步比較版本號即可解決19、你了解JUC下的哪些工具類,分別有什么作用?(CountdownLatch、Cyclicbarrier、Simephore)CountdownLatch:利用它可以實現(xiàn)類似計數(shù)器的功能Cyclicbarrier:字面意思回環(huán)柵欄,通過它可以實現(xiàn)讓一組線程等待至某個狀態(tài)之后再全部同時執(zhí)行Simephore:信號量,Sem、aphore可以控同時訪問的線程個數(shù),通過 acquire() 獲取一個許可,如果沒有就等待,而 release() 釋放一個許可20、說下volatile關(guān)鍵字,有什么作用?原理是什么?是一個變量類型修飾符,被voltile修飾的變量具有以下特性:可見性:保證了不同線程對這個變量進行操作時的可見性,即一個線程修改了某個變量的值,這新值對其他線程來說是立即可見的。實現(xiàn)(緩存共享協(xié)議):對于用volatile形容的變量,線程寫入本地內(nèi)存中的同時會將數(shù)據(jù)立即刷新到主內(nèi)存中。他線程讀取該變量時,發(fā)現(xiàn)被volatile修飾,會將本地變量值置為無效,然后從主內(nèi)存中讀取。有序性:禁止進行指令重排序。為提高執(zhí)行效率,在不影響最終執(zhí)行結(jié)果的前提下,代碼在編譯成字節(jié)碼的時候有可能進行指令重新排序,這在單線程情況下是沒有問題的,但是在多線程的情況下會出現(xiàn)問題。volatile修飾的變量則可以避免這個問題。不保證原子性:volatile 只能保證對單次讀/寫的原子性。i++ 這種操作不能保證原子性。關(guān)于volatile 原子性可以理解為把對volatile變量的單個讀/寫,看成是使用同一個鎖對這些單個讀/寫操作做了同步。21、說下ThreadLocal,有什么作用?有哪些主要方法,實現(xiàn)原理是什么?為什么會有內(nèi)存泄漏問題?如何解決?ThreadLocal:ThreadLocal是除了加鎖這種同步方式之外的另一種可以規(guī)避出現(xiàn)多線程安全問題的思路。ThreadLocal是JDK包提供的,它提供線程本地變量,如果創(chuàng)建一個ThreadLocal變量,那么訪問這個變量的每個線程都會有這個變量的一個副本,在實際多線程操作的時候,操作的是自己本地內(nèi)存中的變量,從而規(guī)避了線程安全問題主要方法:get()、set()、remove()實現(xiàn)原理:每個線程都有屬于自己的一個ThreadLocalMap,可通過Thread獲得,這個map存儲著以threadLock對象為key、以設(shè)置的值為value的鍵值對。調(diào)用get或者set還有remove方法都是操作這個map內(nèi)存泄漏:對于線程池里面不會銷毀的線程, 里面總會存在著<ThreadLocal, LocalVariable>的強引用, 因為 final static 修飾的 ThreadLocal 并不會釋放,而 ThreadLocalMap 對于 Key 雖然是弱引用, 但是強引用不會釋放, 弱引用當(dāng)然也會一直有值,同時創(chuàng)建的 LocalVariable 對象也不會釋放, 就造成了內(nèi)存泄露; 解決方案:為了避免出現(xiàn)內(nèi)存泄露的情況, ThreadLocal 提供了一個清除線程中對象的方法, 即 remove, 其實內(nèi)部實現(xiàn)就是調(diào)用 ThreadLocalMap 的 remove 方法:22、說下線程池的幾大核心參數(shù)?分別有什么作用?有幾種默認的線程池?他們的7個核心參數(shù)為什么要那么設(shè)置?線程池的七大核心參數(shù):1、核心線程數(shù):沒達到核心線程數(shù)時,會創(chuàng)建新的線程。當(dāng)達到核心線程數(shù)時,任務(wù)會進去隊列2、最大核心線程數(shù):當(dāng)達到核心線程數(shù)時,會去創(chuàng)建額外的線程來執(zhí)行任務(wù),最多不超過最大線程數(shù)3、存活時間:當(dāng)任務(wù)處理完成,額外的線程存活一段時間后,會自行銷毀4、存活時間單位:空閑等待時間的單位5、阻塞隊列:利用什么隊列來存放任務(wù),有界隊列、無界隊列等6、線程池工廠:線程創(chuàng)建工廠7、拒絕策略:分為四大策略:1、AbortPolicy(默認策略):直接拋出異常,阻止系統(tǒng)正常運行2、CallerRunsPolicy 策略:等線程池處理不了的任務(wù),誰提交的任務(wù),就給誰拿回去,讓其自己執(zhí)行3、DiscardPolicy 策略:直接拋棄策略,異常也不會拋,什么都不做4、DiscardOldestPolicy 策略:丟棄最老的一個請求,也就是即將被執(zhí)行的一個任務(wù),并嘗試再次提交當(dāng)前任務(wù)有幾種默認的線程池:1、newCachedThreadPool:可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程2、newFixedThreadPool:指定工作線程數(shù)量的線程池。每當(dāng)提交一個任務(wù)就創(chuàng)建一個工作線程,如果工作線程數(shù)量達到線程池初始的最大數(shù),則將提交的任務(wù)存入到池隊列中3、newSingleThreadExecutor:單線程化的Executor,即只創(chuàng)建唯一的工作者線程來執(zhí)行任務(wù),它只會用唯一的工作線程來執(zhí)行任務(wù),保證所有任務(wù)按照指定順序執(zhí)行。4、newScheduleThreadPool:定長的線程池,而且支持定時的以及周期性的任務(wù)執(zhí)行,支持定時及周期性任務(wù)執(zhí)行23、單例模式寫法有哪幾種?(懶漢和餓漢式)那么懶漢式中保證線程安全的寫法是什么?為什么要用雙重檢查模式?單例模式寫法:1、懶漢式直到使用前才會創(chuàng)建實例2、餓漢式類加載的時候就創(chuàng)建實例懶漢式中保證線程安全:在 getInstance() 方法添加 synchronized 關(guān)鍵字,可以解決線程安全問題為什么要用雙重檢查模式:第一次校驗:由于單例模式只需要創(chuàng)建一次實例,如果后面再次調(diào)用getInstance方法時,則直接返回之前創(chuàng)建的實例,因此大部分時間不需要執(zhí)行同步方法里面的代碼,大大提高了性能。如果不加第一次校驗的話,那跟上面的懶漢模式?jīng)]什么區(qū)別,每次都要去競爭鎖。
第二次校驗:
如果沒有第二次校驗,假設(shè)線程t1執(zhí)行了第一次校驗后,判斷為null,這時t2也獲取了CPU執(zhí)行權(quán),也執(zhí)行了第一次校驗,判斷也為null。
接下來t2獲得鎖,創(chuàng)建實例。
這時t1又獲得CPU執(zhí)行權(quán),由于之前已經(jīng)進行了第一次校驗,結(jié)果為null(不會再次判斷),獲得鎖后,直接創(chuàng)建實例。
結(jié)果就會導(dǎo)致創(chuàng)建多個實例。所以需要在同步代碼里面進行第二次校驗,如果實例為空,則進行創(chuàng)建。
六、Redis & 多級緩存
1、Redis是一個什么樣的數(shù)據(jù)庫?讀寫速度怎么樣?
非關(guān)系型型數(shù)據(jù)庫
Redis將數(shù)據(jù)存儲在內(nèi)存上,避免了頻繁的IO操作
2、Redis有哪些數(shù)據(jù)類型,分別的特點?在你們項目中常見的應(yīng)用場景有哪些?請列舉數(shù)據(jù)類型:1、string(字符串):一個key對應(yīng)一個value2、hash(哈希):是一個鍵值對集合3、list(列表):簡單的字符串列表,按照插入順序排序。你可以添加一個元素導(dǎo)列表的頭部(左邊)或者尾部(右邊)4、set(集合):string類型的無序集合,且不允許重復(fù)的成員5、zset(有序集合):string類型元素的集合,且不允許重復(fù)的成員不同的是每個元素都會關(guān)聯(lián)一個double類型的分數(shù)redis正是通過分數(shù)來為集合中的成員進行從小到大的排序zset的成員是唯一的,但分數(shù)(score)卻可以重復(fù)項目有哪些應(yīng)用場景:1、計數(shù)器:對 string 進行自增自減運算,從而實現(xiàn)計數(shù)器功能redis 內(nèi)存型數(shù)據(jù)庫的讀寫性能非常高,很適合存儲頻繁讀寫的計數(shù)量。如每日登錄次數(shù)計數(shù)2、熱點數(shù)據(jù)緩存:將熱點數(shù)據(jù)放到內(nèi)存中。如首頁排行榜數(shù)據(jù),具有很大訪問頻次,使用zset可以實現(xiàn)基于score分數(shù)排序3、會話緩存:用redis統(tǒng)一存儲多臺應(yīng)用服務(wù)器的會話信息當(dāng)應(yīng)用服務(wù)器不再存儲用戶的會話信息,也就不再具有狀態(tài),一個用戶可以請求任意一個應(yīng)用服務(wù)器,從而更容易實現(xiàn)高可用性以及可伸縮性4、取數(shù)據(jù)交集、并集:基于 redis set 的特性可以對共同好友進行很方便的查詢5、分布式事務(wù)鎖的使用:基于 set lock requestId nx ex time 模式可以很方便編寫分布式事務(wù)鎖3、Redis的持久化機制是什么樣的?1)、什么是RDB?RDB的持久化機制(Save、bgSave)?RDB:把內(nèi)存中的所有數(shù)據(jù)都記錄到磁盤中。當(dāng)Redis實例故障重啟后,從磁盤讀取快照文件,恢復(fù)數(shù)據(jù)。快照文件稱為RDB文件,默認是保存在當(dāng)前運行目錄。save:save命令會導(dǎo)致主進程執(zhí)行RDB,這個過程中其它所有命令都會被阻塞。只有在數(shù)據(jù)遷移時可能用到。bgSave:bgSave命令執(zhí)行后會開啟獨立進程完成RDB,主進程可以持續(xù)處理用戶請求,不受影響。2)、觸發(fā)RDB的時間點是什么?save:關(guān)機時會save一次,會阻塞主線程,影響效率。bgsave:與配置有關(guān):save m n,當(dāng)m秒內(nèi)有n個key發(fā)生修改會觸發(fā),后臺會fork出一個子線程完成快照3)、RDB的優(yōu)缺點分別有哪些?優(yōu)點:由于快照是二進制的,所以加載速度很快缺點:由于快照的時間間隔比較長,所以有可能會丟失大量數(shù)據(jù)4)、什么是AOF?分為幾個階段?(命令寫入緩沖區(qū)、同步至日志文件、文件重寫)AOF:將redis數(shù)據(jù)以 操作 + 數(shù)據(jù)的命令形式存在日志文件中(appendonly.aof),默認是關(guān)閉的三個階段:1、命令寫入緩沖區(qū)2、文件命令同步(刷盤策略)3、文件重寫5)、AOF命令同步至日志文件分為哪幾種?1、always 2、everyseconds3、no6)、AOF文件重寫時間點?重寫做了什么?重寫的時機:1、文件大小超過64M2、跟上次文件大小相比,增長比例超過100%,也就是原來的2倍重寫干了什么:刪除沒用的命令、合并多條命令以縮小文件大小7)、AOF的優(yōu)缺點分別有哪些?優(yōu)點:數(shù)據(jù)實時性高,不易丟失數(shù)據(jù)缺點:加載速度慢,文件體積大8)、AOF和RDB同時開啟會優(yōu)先使用哪種進行數(shù)據(jù)恢復(fù)?AOF9)、RDB-AOF混合模式是什么?優(yōu)點有哪些?RDB-AOF混合模式:是在AOF重寫階段創(chuàng)建一個同時包含RDB數(shù)據(jù)和AOF數(shù)據(jù)的AOF文件,其中RDB數(shù)據(jù)位于AOF文件的開頭,他存儲了服務(wù)器開始執(zhí)行重寫操作時Redis服務(wù)器的數(shù)據(jù)狀態(tài)(RDB 快照方案),重寫操作執(zhí)行之后的Redis命令,則會繼續(xù) append 在AOF文件末尾,一般這部分數(shù)據(jù)都會比較小。優(yōu)點:這樣在Redis重啟的時候,則可以先加載RDB的內(nèi)容,然后再加載AOF的日志內(nèi)容,這樣重啟的效率則會得到很大的提升,而且由于在運行階段 Redis 命令都會以 append 的方式寫入AOF文件,保證了數(shù)據(jù)的實時性和安全性4、Redis主從結(jié)構(gòu)能解決什么問題?提高并發(fā)讀寫效率5、Redis主從同步具體流程是什么?1)、建立連接2)、數(shù)據(jù)同步(全量同步、增量同步)【runid運行ID、offset偏移量、復(fù)制積壓緩沖區(qū)】1、全量同步具體場景有哪些?流程?如何避免全量同步次數(shù)(全量同步非常耗時)具體場景:1、slave節(jié)點第一次連接master節(jié)點時2、slave節(jié)點斷開時間太久,repl_baklog中的offset已經(jīng)被覆蓋時流程:1、從服務(wù)器向主服務(wù)器發(fā)送SYNC請求2、主服務(wù)器創(chuàng)建快照,并將快照生成期間產(chǎn)生的寫命令存儲到緩沖區(qū)3、主服務(wù)器向從服務(wù)器發(fā)送同步快照命令4、從服務(wù)器加載解析快照5、主服務(wù)器將從服務(wù)器同步快照期間產(chǎn)生的寫命令存儲到緩沖區(qū)6、主服務(wù)器向從服務(wù)器發(fā)送緩沖區(qū)中存儲的命令7、從服務(wù)器加載緩沖8、完成,主服務(wù)器向從服務(wù)器同步寫操作命令如何避免全量同步次數(shù):增大復(fù)制緩沖區(qū)的配置2、增量同步具體場景有哪些?流程?具體場景:slave節(jié)點斷開又恢復(fù),并且在repl_baklog中能找到offset時流程:Slave完成初始化后開始正常工作時,Master每執(zhí)行一個寫命令就會向Slave發(fā)送相同的寫命令,然后Slave接收并執(zhí)行3)、命令傳播6、如何優(yōu)化主從同步效率?1)、從盡量避免全量同步的方面入手(安全重啟使runid不發(fā)生變化、調(diào)大復(fù)制積壓緩沖區(qū))安全重啟使runid不發(fā)生變化、調(diào)大復(fù)制積壓緩沖區(qū)2)、避免slave從結(jié)點太多造成復(fù)制風(fēng)暴(使用樹狀拓補結(jié)構(gòu))1.主節(jié)點分散多機器(將master分散到不同機器上部署)2.還有我們可以采用高可用手段(slave晉升master)7、Redis的故障恢復(fù)依靠什么機制?哨兵機制的主要工作范圍、工作流程和作用?Redis的故障恢復(fù)機制:哨兵機制工作范圍:監(jiān)控、故障轉(zhuǎn)移、通知工作流程: 1、每個 Sentinel 進程每秒向整個集群中的主、從服務(wù)器以及其他 Sentinel 進程發(fā)送一個 PING 命令2、如果一個實例距離最后一次有效回復(fù) PING 命令的時間超過所指定的值, 則這個實例會被 Sentinel 進程標(biāo)記為主觀下線3、如果一個主服務(wù)器被標(biāo)記為主觀下線,則正在監(jiān)視這個主服務(wù)器的所有 Sentinel 進程要每秒確認主服務(wù)器的確進入了主觀下線狀態(tài)4、當(dāng)有足夠數(shù)量的 Sentinel 進程在指定的時間范圍內(nèi)確認主服務(wù)器進入了主觀下線狀態(tài), 則主服務(wù)器會被標(biāo)記為客觀下線5、每個 Sentinel 進程會以每 10 秒向集群中的所有主服務(wù)器、從服務(wù)器發(fā)送 INFO 命令,更新redis主從最新的一個拓補情況6、當(dāng)主服務(wù)器被 Sentinel 進程標(biāo)記為客觀下線時,Sentinel 進程向下線的主服務(wù)器的所有從服務(wù)器發(fā)送 INFO 命令的頻率會從 10 秒一次改為每秒一次7、若沒有足夠數(shù)量的 Sentinel 進程同意主服務(wù)器下線,主服務(wù)器的客觀下線狀態(tài)就會被移除。若主服務(wù)器重新向 Sentinel 進程發(fā)送 PING 命令返回有效回復(fù),Master主服務(wù)器的主觀下線狀態(tài)就會被移除。作用:1、監(jiān)控:3個心跳10秒一次:更新redis主從最新的一個拓補情況3秒一次:用于Sentinel哨兵節(jié)點之間交流對redis數(shù)據(jù)節(jié)點的看法1秒一次:用于發(fā)出ping,檢測redis節(jié)點是否還存活(主觀下線、客觀下線)2、故障轉(zhuǎn)移:當(dāng)對主節(jié)點進行客觀下線后,選舉出一個新的主節(jié)點,并且將其他節(jié)點連接上新的主節(jié)點,最后將原來的master標(biāo)記為從結(jié)點3、通知:用于master發(fā)生了變動,將變化推送給客戶端8、什么是緩存雪崩?緩存擊穿?緩存穿透?分別如何解決?什么是緩存預(yù)熱?緩存雪崩:Redis掛掉了,請求全部走數(shù)據(jù)庫。對緩存數(shù)據(jù)設(shè)置相同的過期時間,導(dǎo)致某段時間內(nèi)緩存失效,請求全部走數(shù)據(jù)庫解決方案:1、緩存數(shù)據(jù)的過期時間設(shè)置隨機,防止同一時間大量數(shù)據(jù)過期現(xiàn)象發(fā)生2、如果緩存數(shù)據(jù)庫是分布式部署,將熱點數(shù)據(jù)均勻分布在不同搞得緩存數(shù)據(jù)庫中3、允許的話,設(shè)置熱點數(shù)據(jù)永遠不過期4、要保證redis的高可用,可以使用主從+哨兵或redis cluster,避免服務(wù)器不可用5、使用redis的持久化RDB+AOF組合策略,防止緩存丟失并且可以快速恢復(fù)數(shù)據(jù)緩存擊穿:緩存中沒有但數(shù)據(jù)庫中有的數(shù)據(jù),這時由于并發(fā)用戶特別多,同時讀緩存沒讀到數(shù)據(jù),又同時去數(shù)據(jù)庫去取數(shù)據(jù),引起數(shù)據(jù)庫壓力瞬間增大,造成過大壓力解決方案:1)、設(shè)置熱點數(shù)據(jù)不過期;2)、第一時間去數(shù)據(jù)庫獲取數(shù)據(jù)填充到redis中,但是這個過程需要加鎖,防止所有線程都去讀取數(shù)據(jù)庫,一旦有一個線程去數(shù)據(jù)庫獲取數(shù)據(jù)了,其他線程取鎖失敗后可設(shè)置一個合理睡眠時間之后再去嘗試去redis中獲取數(shù)據(jù);緩存穿透:緩存和數(shù)據(jù)庫中都沒有的數(shù)據(jù),而用戶不斷發(fā)起請求,如發(fā)起為id為 -1 的數(shù)據(jù)或id為特別大不存在的數(shù)據(jù)。這時的用戶很可能是攻擊者,攻擊會導(dǎo)致數(shù)據(jù)庫壓力過大解決方案:1、接口層增加校驗,如用戶鑒權(quán)校驗,id做基礎(chǔ)校驗,id<=0的直接攔截;2、從緩存取不到的數(shù)據(jù),在數(shù)據(jù)庫中也沒有取到,這時也可以將 key-value 對寫為 key-null,緩存有效時間可以設(shè)置短點,設(shè)置太長會導(dǎo)致正常情況也沒法使用。這樣可以防止攻擊用戶反復(fù)用同一個id暴力攻擊;3、引入布隆過濾器,過濾一些異常的請求。9、Redis是單線程的,為什么讀寫效率還那么高?基于非阻塞的IO多路復(fù)用機制的線程模型10、Redis的線程模型是什么樣的?(典型的NIO,非阻塞式IO)基于非阻塞的IO多路復(fù)用機制的線程模型,單線程11、Redis過期數(shù)據(jù)的刪除策略是什么?有哪些?定時刪除、惰性過期、定期過期12、Redis的數(shù)據(jù)淘汰策略是什么?有哪些?1、volatile-lru:從已設(shè)置過期時間的數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰2、volatile-ttl:從已設(shè)置過期時間的數(shù)據(jù)集中挑選將要過期的數(shù)據(jù)淘汰3、volatile-random:從已設(shè)置過期時間的數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰4、allkeys-lru:從數(shù)據(jù)集中挑選最近最少使用的數(shù)據(jù)淘汰5、allkeys-random:從數(shù)據(jù)集中任意選擇數(shù)據(jù)淘汰6、no-enviction(驅(qū)逐):禁止驅(qū)逐數(shù)據(jù)13、Redis的慢查詢?nèi)绾闻挪?#xff1f;Redis 慢查詢可通過配置兩個參數(shù)進行:slowlog-log-slower-than:設(shè)置慢查詢預(yù)設(shè)的超時閾值,單位是微秒slowlog-max-len:表示慢查詢?nèi)罩敬鎯Φ臈l數(shù)14、如何正確使用Redis的分布式事務(wù)鎖?(Zookeeper也可以實現(xiàn)分布式鎖)正確使用redis分布式事務(wù)鎖需要保證兩個原子性:1、上鎖和設(shè)置過期時間需要保證原子性;2、 判斷鎖ID是否為自己所有和解鎖需要保證原子性15、Redis的雙寫一致性如何保證?采用延時雙刪策略:1、先淘汰緩存2、再寫數(shù)據(jù)庫3、休眠1秒,再次淘汰緩存16、項目搭建多級緩存的好處是什么?實現(xiàn)多級緩存的流程是什么?(加分項)好處:可以避免緩存雪崩(緩存失效,大量請求直達DB),提高系統(tǒng)的可用性流程:1、反向代理nginx將請求負載均衡到業(yè)務(wù)nginx集群2、接著業(yè)務(wù)Nginx讀取本地緩存(本地緩存可以使用Lua),如果本地緩存命中則直接返回,使用應(yīng)用Nginx本地緩存可以提升整體的吞吐量,降低后端的壓力,尤其應(yīng)對熱點問題非常有效3、如果Nginx本地緩存沒有命中,則會讀取相應(yīng)的分布式緩存(如Redis緩存,另外可以考慮使用主從架構(gòu)來提升性能和吞吐量),如果分布式緩存命中則直接返回相應(yīng)的數(shù)據(jù)(并會寫到Nginx本地緩存)4、如果分布式緩存也沒有命中,則會回源到Tomcat集群,在回源到Tomcat集群時也可以使用輪詢和一致性哈希作為負載均衡算法5、在Tomcat中,首先讀取本地堆緩存,如果有則直接返回(并會寫到Redis集群)6、如果所有的緩存都沒有命中只能查詢DB或相關(guān)服務(wù)獲取相關(guān)數(shù)據(jù)并返回7、返回的數(shù)據(jù)異步寫到Redis17、Redis的hash槽一共有多少個?數(shù)據(jù)是如何進行入槽的?如果實現(xiàn)動態(tài)擴容?個數(shù):16384數(shù)據(jù)進行入槽方式:對Key的有效部分進行運算產(chǎn)生hash值,再拿hash對16384進行取余,余數(shù)是多少,所屬的槽就是哪個實現(xiàn)動態(tài)擴容方式:1、重新分配哈希槽2、輸入要分配多少個哈希槽(數(shù)量)3、輸入指定要分配哈希槽的節(jié)點ID4、選擇需要分配的哈希槽來源,分配哈希槽有兩種方式:1、將所有節(jié)點用作哈希槽的源節(jié)點2、在指定的節(jié)點拿出指定數(shù)量的哈希槽分配到目標(biāo)節(jié)點
七、Rabbitmq
1、Rabbitmq消息模式有哪些?你們用的哪種?(5種)
1、簡單模式:
單發(fā)送單消費
2、工作模式:
單發(fā)送多接收
3、發(fā)布、訂閱模式:
生產(chǎn)者端發(fā)送消息,多個消費者同時接收所有的消息
4、路由模式:
生產(chǎn)者按 routing key 發(fā)送消息,不同的消費者端按不同的 routing key 接收消息
5、Topic:
生產(chǎn)者端不只按固定的 routing key 發(fā)送消息,而是按字符串“匹配”發(fā)送,消費者端同樣如此
2、Rabbitmq如何保證mq消息可靠性?(3大方面)
1、保證消息投遞到MQ不丟:
開啟生產(chǎn)者消息確認機制
1)、開啟 ConfirmCallBack 回調(diào):消息投遞至交換機的回調(diào)(成功、失敗、異常)
2)、開啟 ReturnCallBack 回調(diào):消息從交換機路由到隊列的回調(diào)
2、保證消息到達MQ之后不丟(MQ宕機了也不影響):
消息持久化(三者默認就是持久化的)
1)、交換機的持久化
2)、隊列的持久化
3)、消息的持久化
3、保證消費者不丟(必須至少消費一次):
開啟消費者消息確認機制
1)、none:沒有確認機制,如果出現(xiàn)異常也會直接丟棄
2)、manual:手動確認
1、可以自己靈活的控制消息的確認和拒收
2、注意:開啟這個機制后一定要記得手動回執(zhí),否則將造成消息大量堆積問題
3)、auto:自動確認
優(yōu)點:
出現(xiàn)異常返回nack,正常執(zhí)行返回ack,無需編寫業(yè)務(wù)代碼、無侵入(原理:AOP)
缺點:
當(dāng)消費消息出現(xiàn)異常返回nack時會一直反復(fù)投遞,解決:開啟消費者重試機制(有一個最大重試次數(shù))
消費者重試機制:
消息消費失敗,消費者會自己發(fā)起重試,重試間隔和最大重試次數(shù)可靈活配置
當(dāng)超過最大重試次數(shù)時,消費者對于消息會有幾種執(zhí)行策略:
1、直接丟棄:該消息從MQ刪除
2、放回隊列:將消息放回至隊列,然后投遞給消費者,消費者進行重試,如此循環(huán)往復(fù)
3、投遞至指定的交換機(常用):將消息投遞至專用的交換機,綁定隊列后進行精準(zhǔn)消費
3、Rabbitmq如何實現(xiàn)延時消息?(2種)1、利用死信交換機實現(xiàn)延時投遞原理:消息超時未被消費會被投遞至死信隊列設(shè)置超時:1、針對消息設(shè)置延時時間2、針對隊列設(shè)置延時時間2、利用延時交換機插件實現(xiàn)延時投遞原理:交換機延時路由,到達指定時間會被路由至隊列4、什么是死信隊列?什么樣的消息會進入死信隊列?死信隊列:當(dāng)消息在一個隊列中變成一個死信之后,如果配置了死信隊列,它將被重新publish到死信交換機,死信交換機將死信投遞到一個隊列上,這個隊列就是死信隊列什么樣的消息會進入死信隊列1、超時過期的消息2、被拒絕或者nack的消息3、隊列放不下的消息
5、Rabbitmq如何解決消息堆積問題?(3種思路)1、針對同一隊列增加多個消費者進行消息消費2、針對同一消費者開啟多個線程進行消息消費3、加大隊列的存儲容量:惰性隊列1)、原理:直接將消息寫到磁盤2)、優(yōu)點:存儲容量大,減少從內(nèi)存刷消息數(shù)據(jù)至磁盤的次數(shù),性能更穩(wěn)定3)、缺點:性能取決于磁盤IO6、如何保證消息的冪等性?(從業(yè)務(wù)層面進行判斷)1、數(shù)據(jù)要寫mysql,先根據(jù)主鍵查一下,如果這數(shù)據(jù)都有了,就別插入了,update一下2、如果是寫redis,那沒問題了,反正每次都是set,天然冪等性3、讓生產(chǎn)者發(fā)送每條數(shù)據(jù)的時候,里面加一個全局唯一的id,然后你這里消費到了之后,先根據(jù)這個id去數(shù)據(jù)庫查一下,之前消費過嗎?如果沒有消費過,就處理,然后這個id寫到數(shù)據(jù)庫。如果消費過了,那你就別處理了,保證別重復(fù)處理相同的消息即可
八、微服務(wù)
1、概念問題
1)、什么是微服務(wù)?解決微服務(wù)各種問題都用了哪些組件?
微服務(wù):
一種良好的分布式架構(gòu)方案
1、優(yōu)點:拆分粒度更小、服務(wù)更獨立、耦合度更低
2、缺點:架構(gòu)非常復(fù)雜,運維、監(jiān)控、部署難度提高
組件:
1、Nacos:
服務(wù)注冊中心和配置中心
2、Ribbon:
服務(wù)間發(fā)起請求的時候,基于Ribbon做負載均衡,從一個服務(wù)的多臺機器中選擇一臺
3、Feign:
基于Feign的動態(tài)代理機制,根據(jù)注解和選擇的機器,拼接請求URL地址,發(fā)起請求
4、Hystrix:
發(fā)起請求是通過Hystrix的線程池來走的,不同的服務(wù)走不同的線程池,實現(xiàn)了不同服務(wù)調(diào)用的隔離,避免了服務(wù)雪崩的問題
5、Gateway:
如果前端、移動端要調(diào)用后端系統(tǒng),統(tǒng)一從Zuul網(wǎng)關(guān)進入,由Zuul網(wǎng)關(guān)轉(zhuǎn)發(fā)請求給對應(yīng)的服務(wù)
2)、什么是單體架構(gòu)、什么是分布式架構(gòu)、什么是微服務(wù)架構(gòu)?單體架構(gòu):將業(yè)務(wù)的所有功能集中在一個項目中開發(fā),打成一個包部署優(yōu)點:架構(gòu)簡單部署成本低缺點:耦合度高(維護困難、升級困難)分布式架構(gòu):根據(jù)業(yè)務(wù)功能對系統(tǒng)做拆分,每個業(yè)務(wù)功能模塊作為獨立項目開發(fā),稱為一個服務(wù)優(yōu)點:降低服務(wù)耦合有利于服務(wù)升級和拓展缺點:服務(wù)調(diào)用關(guān)系錯綜復(fù)雜微服務(wù)的架構(gòu):給分布式架構(gòu)制定一個標(biāo)準(zhǔn),進一步降低服務(wù)之間的耦合度,提供服務(wù)的獨立性和靈活性。做到高內(nèi)聚,低耦合。因此,可以認為微服務(wù)是一種經(jīng)過良好架構(gòu)設(shè)計的分布式架構(gòu)方案3)、微服務(wù)有哪些特點?單一職責(zé):微服務(wù)拆分粒度更小,每一個服務(wù)都對應(yīng)唯一的業(yè)務(wù)能力,做到單一職責(zé)自治:團隊獨立、技術(shù)獨立、數(shù)據(jù)獨立,獨立部署和交付面向服務(wù):服務(wù)提供統(tǒng)一標(biāo)準(zhǔn)的接口,與語言和技術(shù)無關(guān)隔離性強:服務(wù)調(diào)用做好隔離、容錯、降級,避免出現(xiàn)級聯(lián)問題2、遠程調(diào)用1)、什么是Feign,用來做什么的?Feign底層調(diào)用是怎么實現(xiàn)的?底層協(xié)議是什么?優(yōu)勢是什么?Feign:Feign是一個聲明式WebService客戶端。使用Feign能讓編寫Web Service客戶端更加簡單,它的使用方法就是定義一個接口,然后在上面添加注解,同時也支持JAX-RS標(biāo)準(zhǔn)作用:使編寫 java http 客戶端變得容易,封裝了Http調(diào)用流程,更適合面向接口化的編程習(xí)慣底層調(diào)用實現(xiàn)流程;1、基于面向接口的動態(tài)代理方式生成實現(xiàn)類2、根據(jù)Contract協(xié)議規(guī)則,解析接口類的注解信息,解析成內(nèi)部表現(xiàn)3、基于RequestBean,動態(tài)生成Request4、使用Encoder將Bean轉(zhuǎn)換成Http報文正文(消息解析和轉(zhuǎn)碼邏輯)5、攔截器負責(zé)對請求和返回進行裝飾處理6、日志記錄7、基于重試器發(fā)送HTTP請求8、發(fā)送Http請求底層協(xié)議:Https協(xié)議優(yōu)勢: 1.feign 采用的是基于接口的注解2.feign 整合了 ribbon,具有負載均衡的能力3.整合了 Hystrix,具有熔斷的能力2)、服務(wù)間調(diào)用,其中一個服務(wù)宕機了,這個時候怎么做呢?1、超時處理2、艙壁模式(隔離)3、熔斷,降級3)、Ribbon是什么?負載均衡策略有哪些?底層原理是什么?默認是哪種?Ribbon:主要功能是提供客戶端的軟件負載均衡算法負載均衡策略:1、隨機策略:隨機選擇server2、輪詢策略:按照順序選擇server(ribbon默認策略)3、重試策略:在一個配置時間段內(nèi),當(dāng)選擇server不成功,則一直嘗試選擇一個可用的server4、最低并發(fā)策略:逐個考察server,如果server斷路器打開,則忽略,再選擇其中并發(fā)鏈接最低的server5、可用過濾策略:過濾掉一直失敗并被標(biāo)記為 circuit tripped 的 server,過濾掉那些高并發(fā)鏈接的 server(active connections超過配置的閾值)6、響應(yīng)時間加權(quán)重策略:根據(jù)server的響應(yīng)時間分配權(quán)重,響應(yīng)時間越長,權(quán)重越低,被選擇到的概率也就越低7、區(qū)域權(quán)重策略:綜合判斷server所在區(qū)域的性能,和server的可用性,輪詢選擇server并且判斷一個AWS Zone的運行性能是否可用,剔除不可用的Zone中的所有server4)、Ribbon是如何實現(xiàn)輪詢的?如果讓你自己實現(xiàn)輪詢,如何實現(xiàn)? 原理:rest 接口的第幾次請求數(shù) % 服務(wù)器集群總數(shù)量 = 實際調(diào)用服務(wù)器的下標(biāo),每次服務(wù)重啟,rest接口計數(shù)從1開始5)、Feign和Ribbon的關(guān)系是什么?Feign 是在 Ribbon的基礎(chǔ)上進行了一次改進,是一個使用起來更加方便的 HTTP 客戶端6)、你們項目中如何使用Feign的(Feign的最佳實踐)將Feign的Client抽取為獨立模塊,并且把接口有關(guān)的POJO、默認的Feign配置都放到這個模塊中,提供給所有消費者使用7)、Feign遠程調(diào)用時的日志級別有哪些?1、NONE,無記錄(DEFAULT)
2、BASIC,只記錄請求方法和URL以及響應(yīng)狀態(tài)代碼和執(zhí)行時間
3、HEADERS,記錄基本信息以及請求和響應(yīng)標(biāo)頭
4、FULL,記錄請求和響應(yīng)的頭文件,正文和元數(shù)據(jù)
8)、如何優(yōu)化Feign的調(diào)用性能?1、配置連接池2、設(shè)置合理的日志級別(basic級別就ok了,強烈不建議使用full)7)、Feign的默認超時時間是多久?重試次數(shù)是幾次?默認超時時間:1秒重試次數(shù):1次8)、Dubbo服務(wù)注冊與發(fā)現(xiàn)的原理?(官方原理圖)1、服務(wù)器容器負責(zé)啟動、加載、運行服務(wù)提供者2、服務(wù)提供者在啟動時,向注冊中心注冊自己提供的服務(wù)3、服務(wù)消費者在啟動時,向注冊中心訂閱自己需要的服務(wù)4、注冊中心返回服務(wù)提供者地址列表給消費者,如果有變更,注冊中心將基于長連接推送變更數(shù)據(jù)給消費者5、服務(wù)消費者從提供者地址列表中基于負載均衡算法,選一臺提供者進行調(diào)用,如果調(diào)用失敗,再選另一臺調(diào)用6、服務(wù)消費者和提供者,在內(nèi)存中累計調(diào)用次數(shù)和調(diào)用時間,定時每分鐘發(fā)送一次統(tǒng)計數(shù)據(jù)到監(jiān)控中心9)、Dubbo負載均衡策略有哪些?默認是哪種?1、Random LoadBalance(默認):隨機,按權(quán)重設(shè)置隨機概率2、RoundRobin LoadBalance: 輪詢,按公約后的權(quán)重設(shè)置輪詢比例3、LeastActive LoadBalance:最少活躍調(diào)用數(shù),相同活躍數(shù)的隨機4、ConstantHash LoadBalance:一致性 Hash,相同參數(shù)的請求總是發(fā)到同意提供者10)、Dubbo支持哪些通信協(xié)議?默認是哪種?一般用哪種協(xié)議?有什么好處?Dubbo支持9種通信協(xié)議:1、dubbo 協(xié)議2、rmi 協(xié)議3、hessian 協(xié)議4、http 協(xié)議5、webservice 協(xié)議6、thrift 協(xié)議7、memcached 協(xié)議8、redis 協(xié)議9、rest默認是哪種:dubbo 協(xié)議 (默認)一般用哪種協(xié)議:dubbo 協(xié)議好處:底層是TCP,效率快11)、注冊中心掛了影響服務(wù)調(diào)用嗎?為什么?不會因為啟動dubbo時,消費者會從注冊中心拉取注冊的生產(chǎn)者的地址接口等數(shù)據(jù),緩存在本地。每次調(diào)用時,按照本地存儲的地址進行調(diào)用12)、Dubbo啟動檢查如何設(shè)置?多版本支持如何設(shè)置?啟動檢查:可以通過配置信息 check="false" 關(guān)閉檢查多版本支持:@DubboService(version = “2.0.0”)@DubboReference(version = "2.0.0")13)、Dubbo的默認超時時間是多久?重試次數(shù)是幾次?默認超時時間:1秒默認重試次數(shù):2次14)、Dubbo進行服務(wù)注冊和發(fā)現(xiàn)的核心注解是哪個?@DubboService@DubboReference15)、Dubbo服務(wù)如何進行監(jiān)控和管理?dubbo-admin 監(jiān)控中心2、注冊中心1)、Eureka1、eureka是屬于什么體系的技術(shù)(Spring Cloud)Spring Cloud2、eureka技術(shù)體系有哪些角色?(服務(wù)端用作注冊中心,客戶端用作微服務(wù))服務(wù)端用作注冊中心,客戶端用作微服務(wù)3、eureka的自我保護機制是什么?什么時候開啟?為什么開啟?開啟了會發(fā)生什么?自我保護機制:某時刻某個微服務(wù)不能用了,eureka不會立刻清理,而是對該微服務(wù)進行保存開啟時間:當(dāng)EurekaServer節(jié)點在短時間內(nèi)丟失過多客戶端時候(可能發(fā)生了網(wǎng)絡(luò)分區(qū)故障)為什么開啟:默認情況下,如果EurekaServer在一定時間內(nèi)沒有收到某個微服務(wù)實例的心跳,EurekaServer將會注銷該實例(默認90s)。但是當(dāng)網(wǎng)絡(luò)分區(qū)故障發(fā)生(延時、卡頓、擁擠)時候,微服務(wù)與EurekaServer之間無法正常通信,以上行為可能變得非常危險了,因為微服務(wù)本身其實是健康的。此時本不應(yīng)該注銷這個微服務(wù)的開啟了會發(fā)生什么:一旦進入保護模式,Eureka Server將會嘗試保護其服務(wù)注冊表中的信息,不再刪除服務(wù)注冊表中的數(shù)據(jù)。也就是不會注銷任何微服務(wù)4、eureka作為注冊中心的原理是什么?心跳檢測某個服務(wù)是否健康的原理詳細說下?原理:1、服務(wù)提供者啟動后將注冊到注冊中心,提供IP, 名字,什么服務(wù)等信息,2、服務(wù)消費者作為客戶端注冊到注冊中心后,拉取注冊中心的服務(wù)列表,在通過負載均衡調(diào)用對應(yīng)的服務(wù)提供者。3、注冊中心可以建立集群,生成多臺eureka,注冊中心為了監(jiān)測各個服務(wù)的心跳,將在每 30S 向所注冊的服務(wù)發(fā)起請求判斷4、服務(wù)是否掛掉,如果掛掉90S后將會將服務(wù)從注冊中心剔除。一個服務(wù)可以監(jiān)測多臺服務(wù)實例,從而可實現(xiàn)均衡負載。心跳檢測:在應(yīng)用啟動后,節(jié)點們將會向Eureka Server發(fā)送心跳,默認周期為30秒,如果Eureka Server在多個心跳周期內(nèi)沒有接收到某個節(jié)點的心跳,Eureka Server將會從服務(wù)注冊表中把這個服務(wù)節(jié)點移除(默認90秒)。5、eureka集群是屬于AP還是CP?(AP)AP2)、Nacos1、nacos是屬于什么體系的技術(shù)(Spring Cloud Alibaba)Spring Cloud Alibaba2、nacos作為注冊中心的原理是什么?服務(wù)注冊時在服務(wù)端本地會通過輪詢注冊中心集群節(jié)點地址進行服務(wù)注冊,在注冊中心上,即Nacos Server上采用了Map保存實例信息,當(dāng)然配置了持久化的服務(wù)會被保存到數(shù)據(jù)庫中,在服務(wù)的調(diào)用方,為了保證本地服務(wù)實例列表的動態(tài)感知,Nacos與其他注冊中心不同的是,采用了 Pull/Push同時運作的方式3、nacos如何確定唯一的一個服務(wù)?(通過namespace、group、service、集群唯一確定一個服務(wù))通過namespace、group、service、集群唯一確定一個服務(wù)4、nacos中namespace、group分別的作用是什么?namespace:用于進行租戶粒度的配置隔離。不同的命名空間下,可以存在相同的 Group 或 Data ID 的配置group:Nacos中的一組配置集,是組織配置的維度之一。通過一個有意義的字符串對配置集進行分組,從而區(qū)分 Data ID 相同的配置集5、nacos和eureka的異同有哪些?相同點:1、都支持服務(wù)注冊和服務(wù)拉取2、都支持服務(wù)提供者心跳的方式做健康檢測不同點:1、nacos支持服務(wù)端主動檢測提供者狀態(tài):臨時實例采用心跳模式,非臨時實例采用主動檢測模式(一般情況下都使用臨時實例,主動檢測消費的服務(wù)器資源較大,服務(wù)器壓力大)2、臨時實例心跳不正常會被剔除,非臨時實例則不會被剔除3、nacos支持服務(wù)列表變更的消息推送模式,服務(wù)列表更新及時4、nacos集群默認采用AP方式,當(dāng)集群中存在非臨時實例時,采用CP模式;eureka采用AP方式6、nacos的臨時節(jié)點和非臨時節(jié)點有什么區(qū)別?非臨時實例掛掉后不會被nacos剔除,而是等待他重連7、nacos集群是屬于AP還是CP?(AP或CP)nacos集群默認采用AP方式,當(dāng)集群中存在非臨時實例時,采用CP模式3)、Zookeeper1、Zookeeper的內(nèi)部結(jié)構(gòu)是什么?ZooKeeper維護和操作一個小型的數(shù)據(jù)節(jié)點,這些節(jié)點被稱之為znode,采用類似于文件系統(tǒng)的層級樹狀結(jié)構(gòu)進行管理2、使用Zookeeper作為分布式事務(wù)鎖的原理是什么?鎖分為兩種:共享鎖(讀鎖)和排他鎖(寫鎖)讀鎖:當(dāng)有一個線程獲取讀鎖后,其他線程也可以獲取讀鎖,但是在讀鎖沒有完全被釋放之前,其他線程不能獲取寫鎖。寫鎖:當(dāng)有一個線程獲取寫鎖后,其他線程就無法獲取讀鎖和寫鎖了。zookeeper 有一種節(jié)點類型叫做臨時序號節(jié)點,它會按序號自增地創(chuàng)建臨時節(jié)點,這正好可以作為分布式鎖的實現(xiàn)工具。3、Zookeeper集群屬于AP還是CP?(CP)CP3、配置中心1)、實現(xiàn)配置中心都可以使用哪些技術(shù)?1、Spring Cloud Config2、Apollo3、Nacos2)、使用nacos作為配置中心,如何實現(xiàn)熱更新?1、在 @Value 注入的變量所在的類上添加注解 @RefreshScope2、使用 @ConfigurationProperties(prefix = "pattern") 注解3)、nacos作為配置中心,為什么需要用到bootstrap文件?得知nacos地址、配置文件id4)、遠程配置文件和本地配置文件屬性加載優(yōu)先級是什么樣的?遠程 > 本地高優(yōu)先級的會覆蓋低優(yōu)先級的重復(fù)的配置內(nèi)容5)、使用配置中心的好處是什么?能解決什么問題?好處:將配置文件集中管理解決的問題:可以在配置變更時,及時通知微服務(wù),實現(xiàn)配置的熱更新4、服務(wù)保護1)、Hystrix1、hystrix是屬于什么體系的技術(shù)?(SpringCloud)SpringCloud2、hystrix可以用來干嘛?(服務(wù)熔斷降級)服務(wù)熔斷降級3、hystrix默認的觸發(fā)熔斷策略是什么?(5分鐘之內(nèi)服務(wù)調(diào)用異常比例達到一半或者失敗次數(shù)超過20次)5分鐘之內(nèi)服務(wù)調(diào)用異常比例達到一半或者失敗次數(shù)超過20次4、hystrix的隔離是基于什么?(線程池隔離【低扇出】)線程池隔離(低扇出)2)、Sentinel1、sentinel可以用來干嘛?(限流、隔離、熔斷、降級)限流、隔離、熔斷、降級2、什么是微服務(wù)雪崩現(xiàn)象?如何解決微服務(wù)雪崩問題?微服務(wù)雪崩:微服務(wù)之間相互調(diào)用,因為調(diào)用鏈中的一個服務(wù)故障,引起整個鏈路都無法訪問的情況解決方案:1、超時處理2、船壁模式(隔離)3、熔斷,降級3、sentinel的限流模式有哪些?分別的運用場景是什么?1、直接:對當(dāng)前資源限流2、關(guān)聯(lián): 比如用戶支付時需要修改訂單狀態(tài),同時用戶要查詢訂單。查詢和修改操作會爭搶數(shù)據(jù)庫鎖,產(chǎn)生競爭。業(yè)務(wù)需求是優(yōu)先支付和更新訂單的業(yè)務(wù),因此當(dāng)修改訂單業(yè)務(wù)觸發(fā)閾值時,需要對查詢訂單業(yè)務(wù)限流。3、鏈路:閾值統(tǒng)計時,只統(tǒng)計從指定資源進入當(dāng)前資源的請求,是對請求來源的限流4、sentinel的限流效果有哪些?分別的運用場景是什么?1、快速失敗:QPS超過閾值時,拒絕新的請求2、warm up:QPS超過閾值時,拒絕新的請求;QPS閾值是逐漸提升的,可以避免冷啟動時高并發(fā)導(dǎo)致服務(wù)宕機3、排隊等待:請求會進入隊列,按照閾值允許的時間間隔依次執(zhí)行請求;如果請求預(yù)期等待時長大于超時時間,直接拒絕4、熱點參數(shù):分別統(tǒng)計參數(shù)值相同的請求,判斷是否超過QPS閾值5、sentinel支持對熱點參數(shù)進行限流嗎?支持6、實現(xiàn)微服務(wù)調(diào)用隔離有兩種方式(信號量隔離和線程池隔離),區(qū)別是什么?sentinel是使用的哪種?區(qū)別:1、信號量隔離:不創(chuàng)建線程池,而是計數(shù)器模式,記錄業(yè)務(wù)使用的線程數(shù)量,達到信號量上限時,禁止新的請求。特點:基于計數(shù)器模式,簡單,開銷小;高扇出2、線程池隔離給每個服務(wù)調(diào)用業(yè)務(wù)分配一個線程池,利用線程池本身實現(xiàn)隔離效果特點:基于線程池模式,有額外開銷,但隔離控制更強;低扇出sentinel是使用的哪種:信號量隔離7、什么是熔斷?熔斷的原理是什么?什么時候會觸發(fā)sentinel的熔斷?斷路器的三種狀態(tài)是哪些?是怎樣進行切換的?概念:熔斷降級會在調(diào)用鏈路中某個資源出現(xiàn)不穩(wěn)定狀態(tài)時(例如調(diào)用超時或異常比例升高),對這個資源的調(diào)用進行限制,讓請求快速失敗,避免影響到其它的資源而導(dǎo)致級聯(lián)錯誤熔斷的原理:斷路器什么時候會觸發(fā)sentinel的熔斷:1、慢調(diào)用2、異常比例或者異常數(shù)斷路器的三種狀態(tài)是哪些,是怎樣進行切換的:1、關(guān)閉:默認就是關(guān)閉的2、半開:開啟后到達指定(可配置)的時間,開啟半開狀態(tài),嘗試接收請求如果成功:狀態(tài)置為關(guān)閉如果失敗:狀態(tài)置為開啟3、開啟:當(dāng)觸發(fā)配置的閾值,會開啟8、什么是降級?如何實現(xiàn)降級?概念:當(dāng)微服務(wù)調(diào)用失敗,客戶端走降級邏輯如何實現(xiàn)降級:1、FallBackClass2、FallBackFactoryClass(優(yōu)勢:可以獲取服務(wù)端拋出的異常)9、sentinel授權(quán)規(guī)則是用來干什么的?授權(quán)規(guī)則可以對調(diào)用方的來源做控制,有白名單和黑名單兩種方式:1、白名單:來源(origin)在白名單內(nèi)的調(diào)用者允許訪問2、黑名單:來源(origin)在黑名單內(nèi)的調(diào)用者不允許訪問10、sentinel的規(guī)則持久化方式有哪些?一般使用哪種?sentinel的規(guī)則持久化方式:1、原始模式:Sentinel的默認模式,將規(guī)則保存在內(nèi)存,重啟服務(wù)會丟失。2、pull模式3、push模式一般使用哪種:push模式5、網(wǎng)關(guān)1)、網(wǎng)關(guān)有什么作用?在你們項目中用網(wǎng)關(guān)來干嘛了?1、權(quán)限控制:網(wǎng)關(guān)作為微服務(wù)入口,需要校驗用戶是是否有請求資格,如果沒有則進行攔截。2、路由和負載均衡:一切請求都必須先經(jīng)過gateway,但網(wǎng)關(guān)不處理業(yè)務(wù),而是根據(jù)某種規(guī)則,把請求轉(zhuǎn)發(fā)到某個微服務(wù),這個過程叫做路由。當(dāng)然路由的目標(biāo)服務(wù)有多個時,還需要做負載均衡。3、限流:當(dāng)請求流量過高時,在網(wǎng)關(guān)中按照下流的微服務(wù)能夠接受的速度來放行請求,避免服務(wù)壓力過大。2)、網(wǎng)關(guān)的核心技術(shù)點有哪些?1、斷言工廠2、過濾器工廠3、全局過濾器4、解決跨域3)、網(wǎng)關(guān)的路由是用來干嘛的?分為哪幾種?路由的作用:一切請求都必須先經(jīng)過gateway,但網(wǎng)關(guān)不處理業(yè)務(wù),而是根據(jù)某種規(guī)則,把請求轉(zhuǎn)發(fā)到某個微服務(wù)分為哪幾種:靜態(tài)路由、動態(tài)路由4)、網(wǎng)關(guān)的過濾器是用來干嘛的?分為哪幾種?網(wǎng)關(guān)的過濾器作用:可以對進入網(wǎng)關(guān)的請求和微服務(wù)返回的響應(yīng)做處理分為哪幾種:1、路由過濾器2、請求頭過濾器3、默認過濾器5)、網(wǎng)關(guān)局部過濾器和全局過濾器的區(qū)別有哪些?局部過濾器:攔截經(jīng)過網(wǎng)關(guān)的特定服務(wù)的請求全局過濾器:無差別攔截所有經(jīng)過網(wǎng)關(guān) 的請求6)、網(wǎng)關(guān)中局部過濾器、默認過濾器、全局過濾器的執(zhí)行順序是什么?默認過濾器 > 局部過濾器 > 全局過濾器7)、加入網(wǎng)關(guān)后,訪問一個鏈接,你們項目的執(zhí)行流程是什么?1、客戶端發(fā)送請求2、進行權(quán)限校驗,如果是登錄或者注冊操作則直接放行3、校驗通過生成該用戶的token,校驗失敗攔截4、路由匹配到某個微服務(wù)8)、定義全局過濾器需要實現(xiàn)哪幾個接口?GlobalFilter6、分布式事務(wù)1)、什么是本地事務(wù)?什么是分布式事務(wù)?本地事務(wù):無需跨越多個服務(wù)或者數(shù)據(jù)源的單體事務(wù),一般由spring控制即可(聲明式事務(wù)處理:AOP)分布式事務(wù):指一個業(yè)務(wù)跨越多個服務(wù)或者數(shù)據(jù)源,每個事務(wù)叫做分支事務(wù),要保證所有分支事務(wù)要么成功,要么失敗2)、什么是CAP定理?為什么必須保證P?為什么在保證P的前提下只能保證C或者A其中一個?CAP定理:
‘’ Consistency(一致性)、Availability(可用性)、Partition tolerance (分區(qū)容錯性),這三個指標(biāo)不可能同時做到為什么必須保證P: 在分布式系統(tǒng)中,系統(tǒng)間的網(wǎng)絡(luò)不能100%保證健康,一定會有故障的時候,而服務(wù)有必須對外保證服務(wù)。因此Partition Tolerance不可避免為什么在保證P的前提下只能保證C或者A其中一個:如果此時要保證一致性,就必須等待網(wǎng)絡(luò)恢復(fù),完成數(shù)據(jù)同步后,整個集群才對外提供服務(wù),服務(wù)處于阻塞狀態(tài),不可用。如果此時要保證可用性,就不能等待網(wǎng)絡(luò)恢復(fù),那 node01、node02、node03 之間就會出現(xiàn)數(shù)據(jù)不一致。3)、什么是BASE理論?BASE理論是對CAP的一種解決思路,包含三個思想:1、Basically Available(基本可用):分布式系統(tǒng)在出現(xiàn)故障時,允許損失部分可用性,即保證核心可用2、Soft State(軟狀態(tài)):在一定時間內(nèi),允許出現(xiàn)中間狀態(tài),比如臨時的不一致狀態(tài)3、Eventually Consistent(最終一致性):雖然無法保證強一致性,但是在軟狀態(tài)結(jié)束后,最終達到數(shù)據(jù)一致4)、seata解決分布式事務(wù)的三個角色以及分別的作用什么?1、TC (Transaction Coordinator) - 事務(wù)協(xié)調(diào)者:維護全局和分支事務(wù)的狀態(tài),協(xié)調(diào)全局事務(wù)提交或回滾2、TM (Transaction Manager) - 事務(wù)管理器:定義全局事務(wù)的范圍、開始全局事務(wù)、提交或回滾全局事務(wù)3、RM (Resource Manager) - 資源管理器:管理分支事務(wù)處理的資源,與TC交談以注冊分支事務(wù)和報告分支事務(wù)的狀態(tài),并驅(qū)動分支事務(wù)提交或回滾5)、seata解決分布式事務(wù)的四種模式1、XA2、AT3、TCC4、SAGA6)、XA模式特點、原理以及應(yīng)用場景?優(yōu)缺點有哪些?特點:強一致性分階段事務(wù)模式,犧牲了一定的可用性,無業(yè)務(wù)侵入 (CP)原理:1)、第一階段:1、TM:1、開啟全局事務(wù)2、調(diào)用分支事務(wù)2、TC: 接收開啟全局事務(wù)的請求3、RM: 1、將分支事務(wù)注冊到TC服務(wù)2、執(zhí)行本地sql,但是,重點:不提交事務(wù)!!!!3、將本地事務(wù)狀態(tài)報告至TC服務(wù) 2)、第二階段:1、TM:等第一階段所有分支事務(wù)執(zhí)行完,發(fā)起提交/回滾全局事務(wù)的命令2、TC:接收全局事務(wù)提交/回滾請求,核查所有分支事務(wù)的狀態(tài),對RM發(fā)起提交/回滾的命令3、RM:提交或者回滾當(dāng)前的分支事務(wù)(依賴于數(shù)據(jù)庫)優(yōu)點:強一致性、無代碼侵入、實現(xiàn)簡單缺點:強依賴于關(guān)系型數(shù)據(jù)庫實現(xiàn)回滾、性能比較差7)、AT模式特點、原理以及應(yīng)用場景?優(yōu)缺點有哪些?有可能會出現(xiàn)什么問題?如何解決?特點:同樣是分階段提交的事務(wù)模型,不過缺彌補了XA模型中資源鎖定周期過長的缺陷,屬于最終一致(AP)原理:1)、第一階段:1、TM:1、開啟全局事務(wù)2、調(diào)用分支事務(wù)2、TC:接收開啟全局事務(wù)的請求3、RM:1、將分支事務(wù)注冊到TC服務(wù)2、執(zhí)行本地sql,重點:提交事務(wù)!!!!3、執(zhí)行sql前后,生成快照:undo_log4、將本地事務(wù)狀態(tài)報告至TC服務(wù)2)、第二階段:1、TM:等第一階段所有分支事務(wù)執(zhí)行完,發(fā)起提交/回滾全局事務(wù)的命令2、TC:接收全局事務(wù)提交/回滾請求,核查所有分支事務(wù)的狀態(tài),對RM發(fā)起提交/回滾的命令3、RM:提交或者回滾當(dāng)前的分支事務(wù)(依賴于undo_log快照數(shù)據(jù))提交:刪除快照數(shù)據(jù)回滾:根據(jù)快照進行數(shù)據(jù)恢復(fù)優(yōu)點:1、一階段完成直接提交事務(wù),釋放數(shù)據(jù)庫資源,性能比較好2、利用全局鎖實現(xiàn)讀寫隔離3、沒有代碼侵入,框架自動完成回滾和提交缺點:1、兩階段之間屬于軟狀態(tài),屬于最終一致2、框架的快照功能會影響性能,但比XA模式要好很多可能出現(xiàn)的問題:臟寫:當(dāng)全局事務(wù)1提交修改的數(shù)據(jù)后,此時全局事務(wù)2又過來修改了這條數(shù)據(jù)后續(xù)階段二全局事務(wù)1需要利用快照進行回滾,將全局事務(wù)2的所有修改進行了覆蓋解決方案:seata內(nèi)部提供了全局鎖的概念(需要在seata server新增一張全局鎖的表)但是全局鎖有可能導(dǎo)致死鎖(內(nèi)部通過限制獲取全局鎖的次數(shù)來解決:30次/10ms)8)、重點:TCC模式特點、原理以及應(yīng)用場景?優(yōu)缺點有哪些?有可能會出現(xiàn)什么問題?什么是空回滾和業(yè)務(wù)懸掛,如何解決?特點:與AT模式非常相似,每階段都是獨立事務(wù),不同的是TCC通過人工編碼來實現(xiàn)數(shù)據(jù)恢復(fù)。屬于最終一致(AP)原理:1、T: Try,進行資源的檢測和預(yù)留2、C:Confirm,對資源進行確認操作(業(yè)務(wù)執(zhí)行和提交)3、C:Cancle,對資源進行回滾操作(預(yù)留資源的釋放)優(yōu)點:1、一階段完成直接提交事務(wù),釋放數(shù)據(jù)庫資源,性能好2、相比AT模型,無需生成快照,無需使用全局鎖,性能最強3、不依賴數(shù)據(jù)庫事務(wù),而是依賴補償操作,可以用于非事務(wù)型數(shù)據(jù)庫缺點:1、有代碼侵入,需要人為編寫try、Confirm和Cancel接口,太麻煩2、軟狀態(tài),事務(wù)是最終一致3、需要考慮Confirm和Cancel的失敗情況,做好冪等處理可能出現(xiàn)的問題:1、空回滾問題描述:當(dāng)某分支事務(wù)的try階段阻塞時,可能導(dǎo)致全局事務(wù)超時而觸發(fā)二階段的cancel操作。在未執(zhí)行try操作時先執(zhí)行了cancel操作,這時cancel不能做回滾,則就是空回滾。解決辦法:執(zhí)行cancel操作時,應(yīng)當(dāng)判斷try是否已經(jīng)執(zhí)行,如果尚未執(zhí)行,則應(yīng)該空回滾。2、業(yè)務(wù)懸掛問題描述:對于已經(jīng)空回滾的業(yè)務(wù),之前被阻塞的try操作恢復(fù),繼續(xù)執(zhí)行try,就永遠不可能confirm或cancel ,事務(wù)一直處于中間狀態(tài),這就是業(yè)務(wù)懸掛。解決辦法:執(zhí)行try操作時,應(yīng)當(dāng)判斷cancel是否已經(jīng)執(zhí)行過了,如果已經(jīng)執(zhí)行,應(yīng)當(dāng)阻止空回滾后的try操作,避免懸掛 9)、SAGA模式特點、原理以及應(yīng)用場景?優(yōu)缺點有哪些?概念:Saga 模式是 Seata 即將開源的長事務(wù)解決方案,將由螞蟻金服主要貢獻。原理:在 Saga 模式下,分布式事務(wù)內(nèi)有多個參與者,每一個參與者都是一個沖正補償服務(wù),需要用戶根據(jù)業(yè)務(wù)場景實現(xiàn)其正向操作和逆向回滾操作。分布式事務(wù)執(zhí)行過程中,依次執(zhí)行各參與者的正向操作,如果所有正向操作均執(zhí)行成功,那么分布式事務(wù)提交。如果任何一個正向操作執(zhí)行失敗,那么分布式事務(wù)會去退回去執(zhí)行前面各參與者的逆向回滾操作,回滾已提交的參與者,使分布式事務(wù)回到初始狀態(tài)。優(yōu)點:1、事務(wù)參與者可以基于事件驅(qū)動實現(xiàn)異步調(diào)用,吞吐高2、一階段直接提交事務(wù),無鎖,性能好3、不用編寫 TCC中的三個階段,實現(xiàn)簡單缺點:1、軟狀態(tài)持續(xù)時間不確定,時效性差2、沒有鎖,沒有事務(wù)隔離,會有臟寫
九、Docker
1、什么是Docker?優(yōu)點是什么?有哪些核心概念?
概念:
Docker是一個快速交付應(yīng)用、運行應(yīng)用的技術(shù)
優(yōu)點:
1、可以將程序及其依賴、運行環(huán)境一起打包為一個鏡像,可以遷移到任意Linux操作系統(tǒng)
2、運行時利用沙箱機制形成隔離容器,各個應(yīng)用互不干擾
3、啟動、移除都可以通過一行命令完成,方便快捷
核心概念:
解決大型項目依賴關(guān)系復(fù)雜,不同組件依賴的兼容性問題:
1、Docker允許開發(fā)中將應(yīng)用、依賴、函數(shù)庫、配置一起打包,形成可移植鏡像
2、Docker應(yīng)用運行在容器中,使用沙箱機制,相互隔離
解決開發(fā)、測試、生產(chǎn)環(huán)境有差異的問題:
Docker鏡像中包含完整運行環(huán)境,包括系統(tǒng)函數(shù)庫,僅依賴系統(tǒng)的Linux內(nèi)核,因此可以在任意Linux操作系統(tǒng)上運行
2、鏡像操作命令有哪些?拉取、推送、查看、查看所有、刪除、刪除所有、制作鏡像、導(dǎo)出鏡像、加載鏡像3、容器操作命令有哪些?查看所有、查看正在運行的容器、刪除、強制刪除、創(chuàng)建容器、創(chuàng)建并運行、啟動容器、停止容器、重啟容器、暫停容器、恢復(fù)容器、進入容器4、數(shù)據(jù)卷操作命令有哪些?創(chuàng)建數(shù)據(jù)卷、查看單個數(shù)據(jù)卷詳情、查看數(shù)據(jù)卷列表、刪除數(shù)據(jù)卷、刪除未使用的數(shù)據(jù)卷、創(chuàng)建容器時掛載數(shù)據(jù)卷5、docker如何自定義鏡像?docker file的語法是什么樣的?自定義鏡像:1、準(zhǔn)備基礎(chǔ)鏡像和tar包2、創(chuàng)建Dockerfile3、使用Dockerfile創(chuàng)建鏡像docker file的語法:保留字指令要大寫,后邊有空格,后邊必須有內(nèi)容。 比如:FROM scratch 指令從上往下依次執(zhí)行6、docker compose是干嘛的?語法是什么樣的?作用:調(diào)用docker服務(wù)的API負責(zé)實現(xiàn)對docker容器集群的快速編排,即通過一個單獨的yaml文件,來定義一組相關(guān)的容器來為一個項目服務(wù)語法:一份標(biāo)準(zhǔn)配置文件應(yīng)該包含 version、services、networks 三大部分,其中最關(guān)鍵的就是 services 和 networks 兩個部分
十、ElasticSearch
1、什么是ES?由什么語言編寫?和Lunce的關(guān)系?什么是ELK?
概念:
1)、是一款分布式、高性能、高擴展,支持海量數(shù)據(jù)分析、搜索、計算的搜索引擎
2)、基于Java語言編寫,發(fā)起的請求時基于Json風(fēng)格的符合RestFull風(fēng)格的DSL語句
3)、前身Lucene誕生于1999年,2004年變?yōu)榱薱ompass,2010年重構(gòu)成了現(xiàn)在的ES
4)、ELK:是一個圍繞ElasticSearch的技術(shù)棧,包含:ElasticSearch、Logstatch、Kibana,最新版本7.16.3
5)、Solr:是ES的一款競品,2016被ES反超,主流成為ES
由什么語言編寫:
Java
和Lunce的關(guān)系:
前身Lucene誕生于1999年,2004年變?yōu)榱薱ompass,2010年重構(gòu)成了現(xiàn)在的ES
什么是ELK:
是一個圍繞ElasticSearch的技術(shù)棧,包含:ElasticSearch、Logstatch、Kibana,最新版本7.16.3
2、ES的核心概念有哪些?什么是索引?什么是文檔?文檔格式是什么?什么是映射?什么是DSL?核心概念:1)、倒排索引對文檔進行合理化的分詞,形成一個不重復(fù)的詞條列表,每一個詞條對應(yīng)一個文檔id集合,將來根據(jù)文檔分成詞條找id,再根據(jù)id找到相應(yīng)的文檔(涉及到兩次的Btree查詢)2)、索引 -- index同一類型文檔的集合,相當(dāng)于mysql的表3)、映射 -- mapping對索引結(jié)構(gòu)的約束,相當(dāng)于mysql的schema(約束)(表結(jié)構(gòu))4)、文檔 -- documentJson格式的數(shù)據(jù),相當(dāng)于mysql的row(行)5)、字段 -- field一個個的字段,相當(dāng)于mysql的列6)、DSL語句Json風(fēng)格的符合restful風(fēng)格的請求語句 3、什么是倒排索引?倒排索引建立過程?倒排索引:對文檔進行合理化的分詞,形成一個不重復(fù)的詞條列表,每一個詞條對應(yīng)一個文檔id集合,將來根據(jù)文檔分成詞條找id,再根據(jù)id找到相應(yīng)的文檔(涉及到兩次的Btree查詢)倒排索引建立過程:1、將每一個文檔的數(shù)據(jù)利用算法分詞,得到一個個詞條2、創(chuàng)建表,每行數(shù)據(jù)包括詞條、詞條所在文檔id、位置等信息3、因為詞條唯一性,可以給詞條創(chuàng)建索引,例如hash表結(jié)構(gòu)索引4、ES有哪些數(shù)據(jù)類型?keyword和text有什么區(qū)別?數(shù)據(jù)類型:1、字符串:text(可分詞的文本)、keyword(精確值,例如:品牌、國家、ip地址)2、數(shù)值:long、integer、short、byte、double、float、3、布爾:boolean4、日期:date5、對象:objectkeyword和text有什么區(qū)別:text可分詞,keyword不可分詞5、重要:說說用戶輸入框輸入查詢條件 進行ES搜索的底層原理過程1、如果用戶輸入條件“華為手機”進行搜索。2、對用戶輸入內(nèi)容分詞,得到詞條:“華為”、“手機”。3、拿著詞條在倒排索引中查找,可以得到包含詞條的文檔id:1、2、3。4、拿著文檔id到正向索引中查找具體文檔。6、ES分詞器適合在什么字段上使用?分詞器在ES中的使用場景有哪些?(建立倒排索引時對文檔分詞和用戶搜索時對搜索條件分詞)建立倒排索引時對文檔分詞和用戶搜索時對搜索條件分詞7、你們分詞器用的哪種?為什么要自定義拼音分詞器?為什么搜索時不能用拼音分詞器?用的哪種:IK分詞器為什么要自定義拼音分詞器:要實現(xiàn)根據(jù)字母做補全,就必須對文檔按照拼音分詞。默認的拼音分詞器會將每個漢字單獨分為拼音,而我們希望的是每個詞條形成一組拼音,需要對拼音分詞器做個性化定制,形成自定義分詞器為什么搜索時不能用拼音分詞器:為了避免搜索到同音字,搜索時不要使用拼音分詞器8、ES有哪些查詢類型,分別用在什么場景?如何實現(xiàn)復(fù)合查詢?要給指定的數(shù)據(jù)進行加分如何實現(xiàn)?查詢類型:1、查詢所有:查詢出所有數(shù)據(jù),一般測試用。例如:match_all2、全文檢索(full text)查詢:利用分詞器對用戶輸入內(nèi)容分詞,然后去倒排索引庫中匹配。例如:match_querymulti_match_query3、精確查詢:根據(jù)精確詞條值查找數(shù)據(jù),一般是查找keyword、數(shù)值、日期、boolean等類型字段。例如:idsrangeterm4、地理(geo)查詢:根據(jù)經(jīng)緯度查詢。例如:geo_distanceeo_bounding_box5、復(fù)合(compound)查詢:復(fù)合查詢可以將上述各種查詢條件組合起來,合并查詢條件。例如:boolfunction_score如何實現(xiàn)復(fù)合查詢:1、根據(jù)原始條件查詢搜索文檔,并且計算相關(guān)性算分,稱為原始算分(query score)2、根據(jù)過濾條件,過濾文檔3、符合過濾條件的文檔,基于算分函數(shù)運算,得到函數(shù)算分(function score)4、將原始算分(query score)和函數(shù)算分(function score)基于運算模式做運算,得到最終結(jié)果,作為相關(guān)性算分。給指定的數(shù)據(jù)進行加分如何實現(xiàn):算分函數(shù):可以簡單粗暴,直接給固定的算分結(jié)果,weight9、給指定的數(shù)據(jù)進行加分如何實現(xiàn)?如何實現(xiàn)高亮?給指定的數(shù)據(jù)進行加分如何實現(xiàn):1、排序2、分頁3、高亮如何實現(xiàn)高亮:1、給文檔中的所有關(guān)鍵字都添加一個標(biāo)簽,例如<em>標(biāo)簽2、頁面給<em>標(biāo)簽編寫CSS樣式10、ES有哪些聚合查詢?1、桶(Bucket)聚合:用來對文檔做分組2、度量(Metric)聚合:用以計算一些值,比如:最大值、最小值、平均值等3、管道(pipeline)聚合:其它聚合的結(jié)果為基礎(chǔ)做聚合11、ES如何實現(xiàn)自動補全查詢1、修改索引庫結(jié)構(gòu),設(shè)置自定義拼音分詞器2、修改索引庫的需要補全的屬性,使用自定義分詞器3、索引庫添加一個新字段suggestion,類型為completion類型,使用自定義的分詞器4、給實體類doc添加suggestion字段5、重新導(dǎo)入數(shù)據(jù)到索引庫12、如何自定義分詞器?1、創(chuàng)建索引庫時,在settings中配置,可以包含三部分2、character filter:在tokenizer之前對文本進行處理。例如刪除字符、替換字符3、tokenizer:將文本按照一定的規(guī)則切割成詞條(term)。例如keyword,就是不分詞;還有ik_smart4、filter:將tokenizer輸出的詞條做進一步處理。例如大小寫轉(zhuǎn)換、同義詞處理、拼音處理等13、如何實現(xiàn)es與mysql的數(shù)據(jù)同步?1、同步調(diào)用:1、ES微服務(wù)對外提供接口,用來修改elasticsearch中的數(shù)據(jù)2、操作數(shù)據(jù)庫微服務(wù)在完成數(shù)據(jù)庫操作后,直接調(diào)用微服務(wù)提供的接口,2、異步通知:1、操作數(shù)據(jù)庫微服務(wù)對mysql數(shù)據(jù)庫數(shù)據(jù)完成增、刪、改后,發(fā)送MQ消息2、ES微服務(wù)監(jiān)聽MQ,接收到消息后完成elasticsearch數(shù)據(jù)修改3、監(jiān)聽binlog1、給mysql開啟binlog功能2、mysql完成增、刪、改操作都會記錄在binlog中3、ES微服務(wù)基于canal監(jiān)聽binlog變化,實時更新elasticsearch中的內(nèi)容14、es集群節(jié)點有哪些類型?分別的職責(zé)是什么?1、備選主節(jié)點(master eligible):主節(jié)點可以管理和記錄集群狀態(tài)、決定分片在哪個節(jié)點、處理創(chuàng)建和刪除索引庫的請求2、數(shù)據(jù)節(jié)點(data):存儲數(shù)據(jù)、搜查、聚合、CRUD3、ingest:數(shù)據(jù)存儲之前的預(yù)處理4、coordinating:路由請求到其他節(jié)點,合并其他節(jié)點處理的結(jié)果,返回給用戶15、什么是es腦裂問題?1、一個集群中,主節(jié)點與其它節(jié)點失聯(lián)2、此時,node2和node3認為node1宕機,就會重新選主3、當(dāng)node3當(dāng)選后,集群繼續(xù)對外提供服務(wù),node2和node3自成集群,node1自成集群,兩個集群數(shù)據(jù)不同步,出現(xiàn)數(shù)據(jù)差異4、當(dāng)網(wǎng)絡(luò)恢復(fù)后,因為集群中有兩個master節(jié)點,集群狀態(tài)的不一致,出現(xiàn)腦裂的情況
十一、壓測、高并發(fā)性能優(yōu)化
1、jemiter壓測工具使用
2、多級緩存(nginx共享字典、redis緩存、tomcat進程緩存)
3、數(shù)據(jù)庫主從讀寫分離(mycat)
4、發(fā)布:
開發(fā)環(huán)境、測試環(huán)境用的shell腳本自動發(fā)布(包括從git上拉取代碼、打包編譯、啟動)
預(yù)上線、線上環(huán)境用的jenkins持續(xù)集成
5、提交代碼之前需要做什么?
總結(jié)
以上是生活随笔為你收集整理的Java基础知识详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CF 1529E. Trees of T
- 下一篇: Coding Contest HDU -