1. 程式人生 > 其它 >沙漏喲:2021年Java面試真題

沙漏喲:2021年Java面試真題

2021.03.01 餓了麼一面

1.1 使用dubbo遇到過的問題

1)dubbo序列化的問題

(1)序列化和反序列化

任何一個物件從一個JVM傳輸到另一個JVM,都要經過序列化為二進位制資料(或者字串等其他格式,比如JSON),然後在反序列化為Java物件,這最後都是通過二進位制的資料在不同的JVM之間傳輸(一般是通過Socket和二進位制的資料傳輸),本文定義一個比較符合工作中。

dubbo是採用Hessian(比jdk自帶反序列化高效)進行反序列化的,該反序列化建立物件時,會取引數最少的構造方法來建立物件,構造方法引數設定預設值,基本型別設定為相應基本型別的預設值,不是基本型別設定為null(就是這點,才導致我上面的構造方法出現空指標,進而導致該物件無法例項化)

dubbo在進行反序列化時,如果找不到物件,會被反序列化成HashMap,給出類找不到的warn,具體的實現可研究com.alibaba.com.caucho.hessian.io.SerializerFactory類。

(2)無法獲取到父類名稱相同的屬性

最近工作中遇見了一個小問題,在此記錄一下,大致是這樣的,有一父類,有一個屬性traceId,主要是記錄日誌號,這樣可以把所有日誌串起來,利於排查問題,所有的pojo物件繼承於此,但是其中一同事在子類pojo中也增加了這一個屬性,在消費者端給traceId設定了值,但經過序列化解析後,提供者端這個traceId時,值為空,解決問題很簡單啊,把子類中的traceId屬性去掉搞定。

這個類的構造方法裡呼叫了這樣的方法getFieldMap,把裡面本類和父類的所有方法放到一個fieldMap裡,因為是HashMap,為了保證方法名不覆蓋,這個方法裡做了一個操作就是fieldMap.get(field.getName()) != null,有的話就繼續迴圈下去不覆蓋,這樣的話如果有同名的方法,那只有子類的方法在裡面。還有這個類Hessian2Input要說下,其中的方法readObjectInstance,它會取到本類和父類的所有方法放到一個數組fieldNames下,這些說完了說到這裡面反序列化的方法JavaSerializer的readObject,是按fieldNames陣列迴圈取值,在流裡面挨個取出來,一直賦給本類的set方法,先是有值的,到父類時,取到的為空,就把本類的值覆蓋了。到這裡原因就清楚了。

(3)泛型的

對於泛型的ComplexModel,Hessian是可以正確的序列化和反序列化的,這讓我納悶了,既然泛型是編譯時的行為,為什麼序列化和反序列化能夠成功?

我的理解:對於JVM而言,執行時沒有泛型資訊,也就是說不管是否使用泛型,它的位元組碼是完全一樣的,當把一個沒有泛型資訊的物件序列化為二進位制資料,然後再把它反序列回來,它的資料就是反序列化前的樣子。

因此ComplexModel的List如果是Point型別的元素,那麼反序列化後也是Point型別,這屬於位元組碼級別的序列化和反序列化。

反序化時為什麼能夠知道List元素的型別呢?原因是在序列化時,List中的每個元素的型別都會作為序列化的資料的一部分,這部分型別資訊就是反序列化到正確型別的依據

2)傳輸報文最大限制

1. dubbo介面限制, 針對的是單個引數, 還是整體引數的大小呢?

  • 1. 經過測試,大小限制針對整體引數大小.

2. 如何解決?

  • 1. dubbo預設引數大小限制為8388608(8M).
  • 2. 可以通過配置修改
  • 3. 配置payload屬性:dubbo.protocol.dubbo.payload=10485760

3. 另外一種方式:繞過dubbo的限制

  • 大檔案,都統一用第三方檔案系統儲存,dubbo介面呼叫中,只傳遞url地址.

3)重試次數,2次

4)其他引數

背景:如果不設定dubbo解救超時時間,預設是1s,重試次數是2次,在呼叫dubbo介面時,會存在超過1s的介面響應時間,這時,就會重新發送請求,而在dubbo提供方邏輯還沒有走完,就會由於介面響應時間問題而造成bug,在這次事故中是對資料庫的操作幾乎同時操作造成了SqlMapClient operation; SQL []這個錯誤。
dubbo預設值:

變數名 描述 預設值 用途
DEFAULT_IO_THREADS 預設IO執行緒 Math.min(Runtime.getRuntime().availableProcessors() + 1, 32) 建立NettyServer和MinaServer時
DEFAULT_PROXY 預設代理, javassist 通過生成位元組碼代替反射
DEFAULT_PAYLOAD 預設最大資料大小 8 * 1024 * 1024/8M 在從通道獲取資料進行編碼時判斷大小
DEFAULT_CLUSTER 預設叢集容錯方案 failover
DEFAULT_DIRECTORY 預設叢集目錄服務 dubbo
DEFAULT_LOADBALANCE 預設負載均衡方案 random(隨機)
DEFAULT_PROTOCOL 預設協議 dubbo
DEFAULT_EXCHANGER 預設資訊交換方式 header
DEFAULT_TRANSPORTER 預設傳輸方式 netty(netty3)
DEFAULT_REMOTING_SERVER 預設遠端客戶端 netty(netty3)
DEFAULT_REMOTING_CODEC 預設協議編碼 dubbo
DEFAULT_REMOTING_SERIALIZATION 預設遠端呼叫序列化方案 hessian2
DEFAULT_HTTP_CLIENT protocol為hession時的預設客戶端型別 jdk
DEFAULT_HTTP_SERIALIZATION http型別預設序列化方案 json
DEFAULT_CHARSET 預設字符集 UTF-8
DEFAULT_WEIGHT 服務預設權重 1000
DEFAULT_FORKS 預設並行請求數 2
DEFAULT_THREAD_NAME 預設執行緒名 Dubbo
DEFAULT_CORE_THREADS 預設核心執行緒數 0
DEFAULT_THREADS 執行緒池預設執行緒數 200
DEFAULT_QUEUES 預設佇列數 0
DEFAULT_IDLE_TIMEOUT 預設空閒時間 600 * 1000(10分鐘)
DEFAULT_ALIVE 連線預設存活時間 60 * 1000(1分鐘)
DEFAULT_CONNECTIONS 預設連線 0
DEFAULT_ACCEPTS 預設接收 0
DEFAULT_HEARTBEAT 預設心跳時間 60 * 1000(1分鐘)
DEFAULT_TIMEOUT 請求執行預設超時時間 1s
DEFAULT_CONNECT_TIMEOUT 連線預設超時時間 3s
DEFAULT_RETRIES 預設重試次數 2
DEFAULT_BUFFER_SIZE 預設緩衝區大小 8 * 1024(8K)

1.2 redis 分散式鎖

A執行緒拿到分散式鎖,但是處理時間過長,然後B執行緒又來拿到分散式鎖,怎麼處理這種情況

1.3 mysql的聯合索引,a,b,c

我用a,c查詢條件,可以走到a,b,c的索引嗎

1.4 classloader隔離

比如rocketmq引用了slf4j,其他包也引用了slf4j,但是版本不一致怎麼處理
兩個不同的classloader載入相同的類,互相之間怎麼通訊?

不同分支載入同一個class檔案會被認為是不同的class,不可直接互相訪問
比方說class A 分別被兩個分支上的classLoader 載入,分別生成a1,a2兩個例項,
如果兩個例項都持有對方的引用, 在a1 中調 a2.f();或在a2中調a1.f();都會提示class not found

但是通過介面訪問沒問題,比方說A implements IA ,不同classloader 載入的類可以通過IA的引用互訪

其原理是,classloader載入順序為從父類到子類順著繼承關係一級一級的載入,如果在載入的過程中沒有找到改class 則到父類裡面尋找,平行的 classloader是不能夠互訪的。

所以,實現方法是要先用一個公共介面的jar包。這個jar包放到父類裡面。也就是osgi框架級別載入。

使用自定義ClassLoader解決反序列化serialVesionUID不一致問題

利用類載入器解決不相容的Jar包共存的問題

就是rocketmq引用了一個jar包2.0版本的,呼叫了裡面某個類,假設是com.xxx.classA裡面的hello2方法,但是redis裡面引用的是一個1.0版本的jar,裡面的com.xxx.classA中沒有hello2方法,那如果類載入過程中,先由redis的classloader載入com.xxx.classA,那麼rocketmq呼叫hello2的時候就找不到這個方法

1.5 分散式事務的原理

XA、2PC、3PC、TCC、SAGA

Seata

1.6 rocketmq訊息佇列堆積問題

1.7 rocketmq的分片機制

2021.03.02 小鵝拼拼一面

對著簡歷的專案經驗問,我說專案經驗裡用到了SpringBoot + Dubbo + Redis + MySQL,然後就一個個地開始問了。

1)SpringBoot

(1)SpringMVC和SpringBoot使用起來有什麼區別

回答一個是少了很多配置,一個是SpringBoot把Tomcat容器整合進去了

(2)看過SpringBoot的原始碼嗎?他和Dubbo的類載入區別是什麼?

(3)SpringBoot是怎樣提前讀取配置給到Tomcat的?tomcat有配置過超時時間、請求協議之類的嗎?

(4)自己寫過SpringBoot starter嗎?

寫一個AutoApplication註解

(5)你說用過Apollo,那Apollo是怎麼實現熱更新的?怎麼熱更新Tomcat的配置?

(4)Bean的生命週期

2)Dubbo

(1)Dubbo有哪些負載均衡策略?

(2)給我講一講Dubbo的完整呼叫鏈。

(3)Dubbo的SPI是怎麼實現的?

3)Redis

(1)Redis主要用來做什麼?分散式快取和分散式鎖。

(2)分散式快取是先操作資料庫還是先操作快取?分別有什麼樣的問題,怎麼解決?

(3)假設先操作快取,然後服務宕機了,這個時候鎖就拿不到了怎麼解決?

(4)用了哪些資料型別?String、list、set、zset主要用在什麼場景?

我說zset用來做排行榜。那1億的使用者資料怎麼用zset做排行榜?

(5)zset底層的實現原理是什麼?

字典表+跳錶。字典表用來做什麼?插入一個數據,插在跳錶的第幾層?

4)MySQL

事務隔離級別知道吧?

MySQL的MVCC在RC和RR上分別有什麼樣的表現?你說下兩種隔離級別下的事務ID檢視?(後來問了說是活躍數和快照表)

MVCC讀取的快照資料在哪裡?

undo log和redo log分別什麼情形下寫入?bin log呢?

5)網路瞭解過嗎?

說下TCP的四次揮手。

HTTP響應碼主要有哪些? 200,404,500

forward和redirect的響應碼是什麼?302?

你用看過HTTP請求的時候當前連線狀態嗎?用什麼看的。我說用過netstat,主要用來看埠是否被佔用了。他說他想問的不是這個。

HTTPS的連線過程是怎樣的?證書是誰頒發的?怎麼驗證證書的?

6)我們來寫一道演算法題吧

剛開始是大數的一個題,我沒聽懂是什麼。

他就說寫個簡單的兩個大數相加吧。

2021.03.05 永輝超市一面

1)Object裡有哪些方法

2)Dubbo的一次完整呼叫鏈

3)有一張門店表、一張門店商品表,一張門店商品關聯表,門店商品關聯表的資料量特別大,怎麼提高這張表的查詢速度?

4)HashMap 1.7和1.8的區別,什麼時候連結串列轉紅黑樹,資料後來又刪除了,紅黑樹會變成連結串列嗎?

2021.03.06 微盟一面

1)專案經歷,這次主要講了信貸的專案分庫分表,引入到了這個專案

我說拆分成4庫16表,你為什麼這樣分?

2)Spring是怎麼解決迴圈依賴問題的(微盟必問,去年一面就是這個掛了)

3)資料庫的MVCC是怎麼實現的

4)你們是怎樣解決redis和資料庫的資料一致性問題的?

我說先更新資料庫,再刪除redis。

那麼如果這個時候併發量比較高,流量都打在redis上怎麼辦?

5)你們分散式鏈路跟蹤用的什麼?

6)我看你有帶團隊,你是怎樣保證團隊程式碼質量的?

2021.03.06 百布一面

1)物件的HashCode是什麼?兩個Person 年齡屬性值都是1,作為HashMap的key存入HashMap會儲存幾條記錄?

2)Java裡面是值傳遞還是引用傳遞?為什麼你傳一個Integer,然後改了外面的方法感知不到?

3)ArrayList按照1.5倍擴容,如果ArrayList容量是100萬再插入時,擴容時速度會變慢嗎?

4)System開頭的方法代表什麼?

5)MyBatis的Mapper介面沒有實現類,但是卻能自動注入,實現原理是什麼?

6)MinoGC和FullGC的關聯關係是什麼?

7)Histrix的熔斷策略是配置在客戶端還是服務端?

2021.03.08 Soul一面

1)Redis叢集情況下,主從同步失敗,導致分散式鎖失效怎麼處理?

redis的單點故障主從切換帶來的兩個客戶端同時執行(而不是叫同時獲取鎖的錯誤寫法)的問題

解決方案

(1)業務容忍

(2)RedLock

2)Redis的記憶體淘汰機制有哪幾種?

volatile lru ttl random lfu

allkey lru lfu

3)MySQL是先操作undolog還是redolog?

4)MySQL寫磁碟前會先寫到Cache裡,這個原理叫什麼?

checkpoint規則:checkpoint觸發後,將buffer中髒資料頁和髒日誌頁都刷到磁碟。

髒資料刷盤:buffer-pool ====> redo log

髒日誌刷盤:redo log buffer ====> redo log file

redo log buffer -> os buffer -> fsync函式 -> redo log file

5)你們的分散式事務一致性是怎麼做的?用的什麼框架?

6)給你一個100億的資料,你要怎樣分庫分表?

7)ES有用過嗎?主要用來做什麼?

8)dubbo配置的連線池有哪幾種類型,區別是什麼?

9)崗位描述,C端業務研發

技術棧:Dubbo、zookeeper、mysql、HBase、Mongo

2021.03.10 喜馬拉雅一面

第一面

1)Redis瘋狂地面,所有知識點

(1)怎麼發現熱key?

Storm流式計算統計,判斷成熱點快取。

zookeeper同步,放到本地快取

(2)怎麼解決熱key?

(3)redis的過期刪除策略是什麼?我回答惰性+定時。

他問定期刪除是怎麼實現的?定期刪除的時候拿所有的key?

2)JVM

(1)JVM怎麼管理堆外記憶體

(2)強引用、軟引用、弱引用的實現原理是什麼?分別什麼時機回收?JVM是怎麼知道要去回收的?

(3)你看了軟引用類的原始碼裡的引數,有什麼啟發嗎?

(4)怎樣動態輸出GC的日誌?

3)RocketMQ

(1)RocketMQ的儲存實現原理是什麼?

(2)RocketMQ怎樣延時佇列的實現原理是什麼?

(3)RocketMQ的事務訊息實現原理是什麼?

第二面

1)Redis

(1)zset的底層資料結構是什麼?

HashMap + 跳錶。跳錶可以用紅黑樹代替嗎?

zset的range怎麼實現?查詢的路徑是什麼?

2)MySQL

(1)MVCC的實現原理是什麼?在RC和RR的事務隔離級別下分別有什麼?

(2)MySQL用B+樹,MongoDB用B樹,為什麼?

(3)給我畫一下B+樹升級層級的過程

3)講一下Dubbo的client呼叫過程

4)Zookeeper

(1)看過Zookeeper的原始碼嗎?

(2)Zookeeper的選舉過程是怎樣的?

(3)Zookeeper的ZAB演算法實現原理是什麼?看過ZAB的Paper嗎?

2021.03.10 叮咚一面

講了6個生產問題,問我可能的原因是什麼,怎麼解決?

1)A系統更新庫存,通過訊息通知B系統庫存更新完成了,B系統過來反查但是發現庫存沒變化,可能原因是什麼?

2)發完版本後,redis(騰訊雲上的單例項)頻寬佔滿了怎麼處理?

3)發現某個應用執行緒數佔用幾萬個,怎麼處理?

4)修改商品庫存,100個商品的庫存同時修改,在一個事務裡做for 迴圈偶爾會發生死鎖,可能是什麼原因?

解決方案,對商品ID排序後再操作。

5)說一下快取和資料庫的先操作哪個,分別會有什麼問題,怎麼解決。

6)樂觀鎖和悲觀鎖的區別是什麼,分別用在什麼場景?

7)A系統一個介面會呼叫B、C、D三個系統的查詢介面,怎麼提高A系統這個介面的查詢速度?

8)CQRS 更新和查詢分離,更新解決併發問題,查詢解決一致性問題

分散式系統就是解決併發和一致性問題

2021.03.11 比心一面

1. dubbo裡的執行緒池是用來做什麼的?什麼階段用?你說有200個執行緒,是200個連線嗎?具體是指什麼?業務執行緒和這200個執行緒是同一個執行緒嗎?如果不是,他們是怎麼通訊的呢?
2. 你剛剛說用了future,那future是怎麼拿到執行緒的返回的?可以具體講講嗎?
3. 執行緒池是怎麼管理執行緒的?怎麼回收的?可以具體講講嗎?
4. 你可以手寫一個阻塞佇列嗎?
5. 陣列123456右移2位變成561234,空間複雜度O(1)

用 Spring 的 @Transactional 註解控制事務有哪些不生效的場景?


作者:沙漏喲
出處:計算機的未來在於連線
本文版權歸作者和部落格園共有,歡迎轉載,請留下原文連結
微信隨緣擴列,聊創業聊產品,偶爾搞搞技術