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