2021-4-13 河貍家面試
面試過程
1.先自我介紹先聊項目
????談談你項目里負責的模塊
2.開始追著項目模塊細問
????談到多線程更新緩存數(shù)據(jù)時,被問到會不會有并發(fā)的問題,怎么解決(主要是redis更新操作不是原子性的,可能存在并發(fā)操作)
加synchronized在方法上,或者如果只是覆蓋的話setnx命令保證原子性
3.開始問簡歷上的東西
設計模式
????觀察者模式
????自己講了監(jiān)聽者模式,也沒講明白(可以講代理模式)
Linux
????怎么查日志 tail -f -n 數(shù)量 查詢最近行數(shù)的日志
????查關鍵字 加 | grep
????查詢關鍵字時忽略大小寫(不會) grep -i ?文件名
????查詢日志行數(shù)(不會)nl 文件名
????有沒有查過系統(tǒng)參數(shù)(不會)
????df -h 查看磁盤占用的空間
cloud
????說下你對注冊中心的理解(服務的注冊流程,發(fā)現(xiàn)流程,自我保護機制)
sql優(yōu)化的經(jīng)歷
????說了下 explain 的使用 type keys 字段的解釋,
????說了下 工作中發(fā)現(xiàn)函數(shù)使查詢速度減慢,索引的添加,最左匹配原則和關聯(lián)字段加索引
4.談談自己是怎么學習的
????腦子抽風說了自己最近在看jvm的書,這不是挖坑嗎,然后把類加載機制的那五個步驟說了一邊,其中說到驗證時,被問到只有class文件格式被驗證嗎?
5.又被問工作的時候怎么學習的,學到了什么 ?
????就把自己學gitlab版的ci ,docker 編寫dockerfile 說了下,但是面試官沒有繼續(xù)問下去
6.面試官說有什么想問的嗎?
總結:
總的來說面試很失敗,被面試官稍微再問下,就不會了,看來學習的深度不夠,還是要加強學習。
知識補充
linux命令補充
查詢系統(tǒng)命令
- sql優(yōu)化補充
????explain
如果是mysql的話,我們可以了解下 使用 如何查看執(zhí)行計劃
?explain select * from emp where name = 'Jefabc';
?
?-- expain出來的信息有10列,分別是id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra
一、 id
SELECT識別符。這是SELECT的查詢序列號
我的理解是SQL執(zhí)行的順序的標識,SQL從大到小的執(zhí)行
id相同時,執(zhí)行順序由上至下
如果是子查詢,id的序號會遞增,id值越大優(yōu)先級越高,越先被執(zhí)行
id如果相同,可以認為是一組,從上往下順序執(zhí)行;在所有組中,id值越大,優(yōu)先級越高,越先執(zhí)行
二、select_type
? 查詢中每個select子句的類型
(1) SIMPLE(簡單SELECT,不使用UNION或子查詢等)
(2) PRIMARY(子查詢中最外層查詢,查詢中若包含任何復雜的子部分,最外層的select被標記為PRIMARY)
(3) UNION(UNION中的第二個或后面的SELECT語句)
(4) DEPENDENT UNION(UNION中的第二個或后面的SELECT語句,取決于外面的查詢)
(5) UNION RESULT(UNION的結果,union語句中第二個select開始后面所有select)
(6) SUBQUERY(子查詢中的第一個SELECT,結果不依賴于外部查詢)
(7) DEPENDENT SUBQUERY(子查詢中的第一個SELECT,依賴于外部查詢)
(8) DERIVED(派生表的SELECT, FROM子句的子查詢)
(9) UNCACHEABLE SUBQUERY(一個子查詢的結果不能被緩存,必須重新評估外鏈接的第一行)
三、table
顯示這一步所訪問數(shù)據(jù)庫中表名稱(顯示這一行的數(shù)據(jù)是關于哪張表的),有時不是真實的表名字,可能是簡稱,例如上面的e,d,也可能是第幾步執(zhí)行的結果的簡稱
四、type
對表訪問方式,表示MySQL在表中找到所需行的方式,又稱“訪問類型”。
常用的類型有:ALL、index、range、 ref、eq_ref、const、system、NULL(從左到右,性能從差到好)
ALL:Full Table Scan, MySQL將遍歷全表以找到匹配的行
index: Full Index Scan,index與ALL區(qū)別為index類型只遍歷索引樹
range:只檢索給定范圍的行,使用一個索引來選擇行
ref: 表示上述表的連接匹配條件,即哪些列或常量被用于查找索引列上的值
eq_ref: 類似ref,區(qū)別就在使用的索引是唯一索引,對于每個索引鍵值,表中只有一條記錄匹配,簡單來說,就是多表連接中使用primary key或者 unique key作為關聯(lián)條件
const、system: 當MySQL對查詢某部分進行優(yōu)化,并轉換為一個常量時,使用這些類型訪問。如將主鍵置于where列表中,MySQL就能將該查詢轉換為一個常量,system是const類型的特例,當查詢的表只有一行的情況下,使用system
NULL: MySQL在優(yōu)化過程中分解語句,執(zhí)行時甚至不用訪問表或索引,例如從一個索引列里選取最小值可以通過單獨索引查找完成。
五、possible_keys
指出MySQL能使用哪個索引在表中找到記錄,查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢使用(該查詢可以利用的索引,如果沒有任何索引顯示 null)
該列完全獨立于EXPLAIN輸出所示的表的次序。這意味著在possible_keys中的某些鍵實際上不能按生成的表次序使用。如果該列是NULL,則沒有相關的索引。在這種情況下,可以通過檢查WHERE子句看是否它引用某些列或適合索引的列來提高你的查詢性能。如果是這樣,創(chuàng)造一個適當?shù)乃饕⑶以俅斡肊XPLAIN檢查查詢
六、Key
key列顯示MySQL實際決定使用的鍵(索引),必然包含在possible_keys中
如果沒有選擇索引,鍵是NULL。要想強制MySQL使用或忽視possible_keys列中的索引,在查詢中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。
七、key_len
表示索引中使用的字節(jié)數(shù),可通過該列計算查詢中使用的索引的長度(key_len顯示的值為索引字段的最大可能長度,并非實際使用長度,即key_len是根據(jù)表定義計算而得,不是通過表內檢索出的)
不損失精確性的情況下,長度越短越好
八、ref
列與索引的比較,表示上述表的連接匹配條件,即哪些列或常量被用于查找索引列上的值
九、rows
估算出結果集行數(shù),表示MySQL根據(jù)表統(tǒng)計信息及索引選用情況,估算的找到所需的記錄所需要讀取的行數(shù)
十、Extra
該列包含MySQL解決查詢的詳細信息,有以下幾種情況:
Using where:不用讀取表中所有信息,僅通過索引就可以獲取所需數(shù)據(jù),這發(fā)生在對表的全部的請求列都是同一個索引的部分的時候,表示mysql服務器將在存儲引擎檢索行后再進行過濾
Using temporary:表示MySQL需要使用臨時表來存儲結果集,常見于排序和分組查詢,常見 group by ; order by
Using filesort:當Query中包含 order by 操作,而且無法利用索引完成的排序操作稱為“文件排序”
sing join buffer:改值強調了在獲取連接條件時沒有使用索引,并且需要連接緩沖區(qū)來存儲中間結果。如果出現(xiàn)了這個值,那應該注意,根據(jù)查詢的具體情況可能需要添加索引來改進能。
Impossible where:這個值強調了where語句會導致沒有符合條件的行(通過收集統(tǒng)計信息不可能存在結果)。
Select tables optimized away:這個值意味著僅通過使用索引,優(yōu)化器可能僅從聚合函數(shù)結果中返回一行
No tables used:Query語句中使用from dual 或不含任何from子句
sql優(yōu)化
① SQL優(yōu)化
?小表驅動大表,即小的數(shù)據(jù)集驅動大的數(shù)據(jù)集:
?當B表的數(shù)據(jù)集比A表小時,用in優(yōu)化 exist兩表執(zhí)行順序是先查B表再查A表查詢語句:SELECT * FROM tb_dept WHERE id in (SELECT id FROM tb_dept) ;
?當A表的數(shù)據(jù)集比B表小時,用exist優(yōu)化in ,兩表執(zhí)行順序是先查A表,再查B表,查詢語句:SELECT * FROM A WHERE EXISTS (SELECT id FROM B WHERE A.id = B.ID) ;
?盡量使用連接代替子查詢,因為使用 join 時,MySQL 不會在內存中創(chuàng)建臨時表。
② 優(yōu)化索引的使用
?不做列運算,把計算都放入各個業(yè)務系統(tǒng)實現(xiàn)
?查詢語句盡可能簡單,大語句拆小語句,減少鎖時間
?or 查詢改寫成 union?查詢
?不用函數(shù)和觸發(fā)器
?避免 %xx 查詢,可以使用:select * from t where reverse(f) like reverse('%abc');
?少用 join 查詢
?使用同類型比較,比如 '123' 和 '123'、123 和 123
?盡量避免在 where 子句中使用 != 或者 <> 操作符,查詢引用會放棄索引而進行全表掃描
?列表數(shù)據(jù)使用分頁查詢,每頁數(shù)據(jù)量不要太大
?避免在索引列上使用 is null 和 is not null
③ 表結構設計優(yōu)化
?盡量使用 tinyint、smallint、mediumint 作為整數(shù)類型而非 int。
?盡可能使用 not null 定義字段,因為 null 占用 4 字節(jié)空間。數(shù)字可以默認 0 ,字符串默認 “”
?盡量少用 text 類型,非用不可時最好獨立出一張表。
?盡量使用 timestamp,而非 datetime。
?單表不要有太多字段,建議在 20 個字段以內。
類加載機制補充
類加載時機
1.遇到new、getstatic、putstatic或invokestatic這四條字節(jié)碼指令時,如果類型沒有進行過初始
化,則需要先觸發(fā)其初始化階段。
2.使用java.lang.reflect包的方法對類型進行反射調用的時候,如果類型沒有進行過初始化,則需
要先觸發(fā)其初始化
3.當初始化類的時候,如果發(fā)現(xiàn)其父類還沒有進行過初始化,則需要先觸發(fā)其父類的初始化。
4.當虛擬機啟動時,用戶需要指定一個要執(zhí)行的主類(包含main()方法的那個類),虛擬機會先
初始化這個主類。
5.當使用JDK 7新加入的動態(tài)語言支持時,如果一個java.lang.invoke.MethodHandle實例最后的解
析結果為REF_getStatic、REF_putStatic、REF_invokeStatic、REF_newInvokeSpecial四種類型的方法句
柄,并且這個方法句柄對應的類沒有進行過初始化,則需要先觸發(fā)其初始化。
6.當一個接口中定義了JDK 8新加入的默認方法(被default關鍵字修飾的接口方法)時,如果有
這個接口的實現(xiàn)類發(fā)生了初始化,那該接口要在其之前被初始化。
對于這六種會觸發(fā)類型進行初始化的場景,《Java虛擬機規(guī)范》中使用了一個非常強烈的限定語
——“有且只有”,這六種場景中的行為稱為對一個類型進行主動引用。除此之外,所有引用類型的方
式都不會觸發(fā)初始化,稱為被動引用
類加載機制主要五個階段
加載
“加載”(Loading)階段是整個“類加載”(Class Loading)過程中的一個階段,希望讀者沒有混淆
這兩個看起來很相似的名詞。在加載階段,Java虛擬機需要完成以下三件事情:
1)通過一個類的全限定名來獲取定義此類的二進制字節(jié)流。
2)將這個字節(jié)流所代表的靜態(tài)存儲結構轉化為方法區(qū)的運行時數(shù)據(jù)結構。
3)在內存中生成一個代表這個類的java.lang.Class對象,作為方法區(qū)這個類的各種數(shù)據(jù)的訪問入口。
總的來說,虛擬機拿到class文件(或者是其他形式)轉化為類對象存放在方法區(qū)中。
驗證
文件格式驗證
元數(shù)據(jù)驗證
字節(jié)碼驗證
符號引用驗證
準備
準備階段是正式為類中定義的變量(即靜態(tài)變量,被static修飾的變量)分配內存并設置類變量初始值的階段。
解析
解析階段是Java虛擬機將常量池內的符號引用替換為直接引用的過程。
符號引用(Symbolic References):符號引用以一組符號來描述所引用的目標,符號可以是任何
形式的字面量,只要使用時能無歧義地定位到目標即可。符號引用與虛擬機實現(xiàn)的內存布局無關,引
用的目標并不一定是已經(jīng)加載到虛擬機內存當中的內容。各種虛擬機實現(xiàn)的內存布局可以各不相同,
但是它們能接受的符號引用必須都是一致的,因為符號引用的字面量形式明確定義在《Java虛擬機規(guī)
范》的Class文件格式中。
直接引用(Direct References):直接引用是可以直接指向目標的指針、相對偏移量或者是一個能
間接定位到目標的句柄。直接引用是和虛擬機實現(xiàn)的內存布局直接相關的,同一個符號引用在不同虛
擬機實例上翻譯出來的直接引用一般不會相同。如果有了直接引用,那引用的目標必定已經(jīng)在虛擬機
的內存中存在。
初始化
初始化階段就是執(zhí)行類構造器<clinit>()方法的過程
·<clinit>()方法是由編譯器自動收集類中的所有類變量的賦值動作和靜態(tài)語句塊(static{}塊)中的
語句合并產生的,編譯器收集的順序是由語句在源文件中出現(xiàn)的順序決定的,靜態(tài)語句塊中只能訪問
到定義在靜態(tài)語句塊之前的變量,定義在它之后的變量,在前面的靜態(tài)語句塊可以賦值,但是不能訪
問