阿里11面+EMC+網易+美團面經


作者:水啊水來源:牛客網

從7月初到8月底一直在面阿里,從提前批投螞蟻中間件與阿里中間件,最後阿里中間件面完了hr,但是很遺憾最後沒能進,被調到了盒馬。不過最終還是拿到了盒馬的offer。期間還面了EMC、網易、攜程(水到不行)、美團、拼多多,目前出了美團跟拼多多沒有出結果,其他幾家公司也都順利拿到意向,在此回饋一波牛客網。

面經一部分出自阿里,其他幾家公司有少部分補充,內容是個人整理,如有不對,還請糾正,謝謝!

小編溫馨提示:本文超長,且乾貨超多,可以準備好小本本把你需要的記下來!

1.網絡編程

ISO模型與協議:

◆應用層:爲操作系統或網絡應用程序提供訪問網絡服務的接口。協議Telnet、FTP、HTTP、SNMP、DNS:

●http1.0:需要使用keep-alive參數來告知服務器端要建立一個長連接

●http1.1:默認長連接。支持只發送header信息,可以用作權限請求。支持Host域。

●http2.0:多路複用的技術,做到同一個連接併發處理多個請求。HTTP2.0使用HPACK算法對header的數據進行壓縮。支持HTTP2.0的web server請求數據的時候,服務器會順便把一些客戶端需要的資源一起推送到客戶端,免得客戶端再次創建連接發送請求到服務器端獲取。這種方式非常合適加載靜態資源。

◆表示層:對上層數據進行變換(加密、解密、壓縮、格式轉換等),確保兩臺主機的應用層程序能過理解。協議ASCII、ASN.1、JPEG、MPEG

◆會話層:負責管理主機之間的會話進程,負責建立、管理、終止進程之間的會話。

◆傳輸層:將上層數據分段並提供端到端的、可靠的或不可靠的傳輸,還要處理端到端的差錯控制和流量控制問題。協議TCP、UDP、SPX

◆網絡層:對子網間的數據包進行路由選擇。此外,網絡層還可以實現擁塞控制、網際互連等功能。協議IP、IPX、RIP、OSPF

◆數據鏈路層:在不可靠的物理介質上提供可靠的傳輸。該層的作用包括:物理地址尋址、數據的成幀、流量控制、數據的檢錯、重發等。協議SDLC、HDLC、PPP、STP、幀中繼

◆物理層:爲上層協議提供了一個傳輸數據的物理媒體。

◆TCP\IP模型與協議:

●應用層:單位是數據段,協議有FTP、TELNET、HTTP、SMTP、SNMP、TFTP、NTP、DNS

●運輸層:單位是數據包,協議有TCP、UDP

●網絡層:單位是數據幀,協議有IP

●網絡接口層:單位是比特,ARP、RARP

阿里11面+EMC+網易+美團面經

◆三次握手與四次揮手

◆tcp拆包粘包:

●由於一批發送的數據太多或緩衝區太小,將一批數據分成多個segment來發送,叫拆包。

●將多批小數據寫入一個緩衝區,或讀取不及時,一個緩衝區存在多批數據,叫粘包。

●解決方式:根據消息頭中的長度與偏移量來重組數據。設置定長消息,使得一個緩衝區中的segment總是一批數據的。設置消息邊界。

◆BIO NIO AIO:

●BIO:同步阻塞IO,每個請求都要一個線程來處理。

●NIO:同步非阻塞IO,一個線程可以處理多個請求,適用於短連接、小數據。

●AIO:異步非阻塞IO,一個線程處理多個請求,使用回調函數實現,適用於長連接、大數據。

◆DDOS攻擊原理與防禦方式:

●SYN flood:僞造ip地址發送請求,佔滿半連接隊列,導致正常鏈接被服務器拋棄。攻擊方需要很高的帶寬資源。

●ACK flood:大量ACK連接請求服務器,服務器需要花費CPU資源去查詢連接隊列並回應。只有當流量很高時纔會對服務器造成影響。

●Connection Flood:利用真實IP,在服務器上建立大量連接,從而佔滿服務器連接隊列,導致正常連接被丟棄。

●HTTP Get Flood:發送大量會產生sql查詢的連接,使得數據庫負載很高。

◆CSRF跨站請求僞造原理:

●攻擊者盜用了你的身份,以你的名義發送惡意請求。

●例子:假如你去銀行網站上通過請求http://www.mybank.com/Transfer.php?toBankId=11&money=1000來消費1000元。然後登陸某個惡意網站,上面有這麼一段代碼 。由於你沒有登出銀行網站,因此會再消費1000.

●CSRF攻擊是源於WEB的隱式身份驗證機制!WEB的身份驗證機制雖然可以保證一個請求是來自於某個用戶的瀏覽器,但卻無法保證該請求是用戶批准發送的!

●防禦方式:1.驗證碼;2. 後臺生成token,讓前端請求攜帶。3.使用對稱加密,後端隨機給前端一個密鑰,前端進行加密,後端解密。

◆會話劫持

●通過暴力破解、 預測、竊取(通過XSS攻擊)等方式獲取到用戶session

●防禦方式

●更改Session名稱

●關閉透明化Session ID。透明化Session ID指當瀏覽器中的Http請求沒有使用Cookie來存放Session ID時,Session ID則使用URL來傳遞。

●設置HttpOnly。通過設置Cookie的HttpOnly爲true,可以防止客戶端腳本訪問這個Cookie,從而有效的防止XSS攻擊。

◆XSS攻擊

●XSS攻擊是Web攻擊中最常見的攻擊方法之一,它是通過對網頁注入可執行代碼且成功地被瀏覽器執行,達到攻擊的目的,形成了一次有效XSS攻擊,一旦攻擊成功,它可以獲取用戶的聯繫人列表,然後向聯繫人發送虛假詐騙信息,可以刪除用戶的日誌等等,有時候還和其他攻擊方式同時實施比如SQL注入攻擊服務器和數據庫、Click劫持、相對鏈接劫持等實施釣魚,它帶來的危害是巨大的,是web安全的頭號大敵。

●XSS反射型攻擊,惡意代碼並沒有保存在目標網站,通過引誘用戶點擊一個鏈接到目標網站的惡意鏈接來實施攻擊的。

●XSS存儲型攻擊,惡意代碼被保存到目標網站的服務器中,這種攻擊具有較強的穩定性和持久性,比較常見場景是在博客,論壇等社交網站上,但OA系統,和CRM系統上也能看到它身影,比如:某CRM系統的客戶投訴功能上存在XSS存儲型漏洞,黑客提交了惡意攻擊代碼,當系統管理員查看投訴信息時惡意代碼執行,竊取了客戶的資料,然而管理員毫不知情,這就是典型的XSS存儲型攻擊。

+解決方法:

●在表單提交或者url參數傳遞前,對需要的參數進行過濾

●過濾用戶輸入。檢查用戶輸入的內容中是否有非法內容。如<>(尖括號)、”(引號)、 ‘(單引號)、%(百分比符號)、;(分號)、()(括號)、&(& 符號)、+(加號)等

●RPC與HTTP服務的區別

2.數據庫原理

◆MYISAM與innodb搜索引擎原理:

●MyISAM引擎使用B+Tree作爲索引結構,葉節點的data域存放的是數據記錄的地址。其採用索引文件與數據文件,索引文件只存放索引,葉子節點存放數據的物理地址。數據文件存放數據。其索引方式是非聚集的。

●InnoDB也使用B+Tree作爲索引結構。但是它的主索引與數據都放在一個文件中。這種索引叫做聚集索引,因爲InnoDB的數據文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識數據記錄的列作爲主鍵,如果不存在這種列,則MySQL自動爲InnoDB表生成一個隱含字段作爲主鍵,這個字段長度爲6個字節,類型爲長整形。

●區別一:InnoDB的主索引與數據都放在一個文件中。而MYISAM是分開存放的。

●區別二:InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。

●區別三:InnoDB的主鍵索引是聚集索引,而MYISAM不是聚集索引。

◆索引,聚簇索引和二級索引的加鎖區別:

●聚集(clustered)索引,也叫聚簇索引。數據行的物理順序與列值(一般是主鍵的那一列)的邏輯順序相同,一個表中只能擁有一個聚集索引。

●非聚集(unclustered)索引。該索引中索引的邏輯順序與磁盤上行的物理存儲順序不同,一個表中可以擁有多個非聚集索引。會發生二次查詢。

●稠密索引:稠密索引文件中的索引塊保持鍵的順序與文件中的排序順序一致。

●稀疏索引:稀疏索引沒有爲每個數據都創建一個索引,它比稠密索引節省了更多的存儲空間,但查找給定值的記錄需更多的時間。只有當數據文件是按照某個查找鍵排序時,在該查找鍵上建立的稀疏索引才能被使用,而稠密索引則可以應用在任何的查找鍵。

●聯合索引:將一張表中多個列組成聯合索引(col1,col2,col3),其生效方式滿足最左前綴原則。

●最左前綴:假如我們創建了聯合索引(col1,col2,col3),那麼相當於創建了(col1),(col1,col2),(col1,col2,col3)這3個索引,然後where條件會根據出現的列名挑選最嚴格的索引。例如where col1=? and col2=? and col3=?,那麼就會使用(col1,col2,col3);如果where col1=? and col3 =?,那麼就會使用(col1);如果where col2=? and col3=?,那麼一個都不會使用。因此在創建多列索引時,要根據業務需求,where子句中使用最頻繁的一列放在最左邊。

●選擇性:不重複數佔所有記錄的比例,假如有10w條記錄,unique之後有9w條,那麼選擇性位90%。主要有兩個作用:1. 查看某一列是否有必要建立索引;2. 對於String、hash值、日期等字段,應該取多少位來建立索引(即使用前綴索引),因爲主鍵越短,整個索引表越小。

●覆蓋索引:對於二級索引而言,在innodb中一般是需要先根據二級索引查詢到主鍵,然後在根據一級索引查詢到數據。但是如果select的列都在索引中,就避免進行一級查詢。

●主鍵選擇:在使用InnoDB存儲引擎時,如果沒有特別的需要,請永遠使用一個與業務無關的自增字段作爲主鍵。

●where 1 = 1:能夠方便我們拼sql,但是使用了之後就無法使用索引優化策略,因此會進行全表掃描,影響效率。

◆分表分庫:

●水平拆分:依據表中的數據的邏輯關係,將同一個表中的數據依照某種條件拆分到多臺數據庫(主機)上面。按照1個或多個字段以及相應的規則,將一張表重的數據分到多張表中去。比如按照id%5的規則,將一張大表拆分成5張小表。適合具有超大表的系統。

●垂直拆分:依照不同的表(或者Schema)來切分到不同的數據庫(主機)之上。一般按照模塊來分庫。適合各業務之間耦合度非常低的系統。

◆validationQuery:用來驗證數據庫連接的查詢語句,這個查詢語句必須是至少返回一條數據的SELECT語句。

◆select鎖定記錄:

●select * from table where ?;不加鎖

●將查詢放到事物中

●select * from table where ? lock in share mode;加共享鎖

●select * from table where ? for update;加排它鎖

●insert, update, delete;加排它鎖

◆隔離級別:

●read uncommit:讀不加鎖,寫加共享鎖。會產生髒讀、幻讀。

●read commit:讀加共享鎖,寫加排它鎖,但不加間隙鎖。間隙鎖的主要作用是防止不可重複讀,但會加大鎖的範圍。

●repeatable read(innodb默認):讀加共享鎖,寫加間隙排它鎖。注意,Innodb對這個級別進行了特殊處理,使得這個級別能夠避免幻讀,但不是所有引擎都能夠防止幻讀!(網易面試官問)

●serialization:會給整張表加鎖,強一致,但是效率低。

◆innodb中的鎖:

●MVCC(multi-Version Concurrency Control):讀不加鎖,讀寫不衝突。適合寫少讀多的場景。讀操作分爲:快照讀(返回記錄的可見版本,不加鎖)、當前讀(記錄的最新版本,加鎖,保證其它記錄不修改)。

●LBCC(Lock-Based Concurrency Control):

◆join原理:

●Simple Nested-Loop Join:效率最低,按照join的次序,在join的屬性上一個個掃描,併合並結果。

●Index Nested-Loop Join:效率最高,join的屬性上面有索引,根據索引來匹配。

●Block Nested-Loop Join:用於沒有索引的列。它會採用join buffer,將外表的值緩存到join buffer中,然後與內表進行批量比較,這樣可以降低對外表的訪問頻率

◆galera:

●多主架構:真正的多點讀寫的集羣,在任何時候讀寫數據,都是最新的。

●同步複製,各節點間無延遲且節點宕機不會導致數據丟失。

●緊密耦合,所有節點均保持相同狀態,節點間無不同數據。

●無需主從切換操作。

●無需進行讀寫分離。

●併發複製:從節點在APPLY數據時,支持並行執行,有更好的性能表現。

●故障切換:在出現數據庫故障時,因爲支持多點寫入,切的非常容易。

●熱插拔:在服務期間,如果數據庫掛了,只要監控程序發現的夠快,不可服務時間就會非常少。在節點故障期間,節點本身對集羣的影響非常小。

●自動節點克隆:在新增節點,或者停機維護時,增量數據或者基礎數據不需要人工手動備份提供,Galera Cluster會自動拉取在線節點數據,最終集羣會變爲一致。

●對應用透明:集羣的維護,對應用程序是透明的,幾乎感覺不到。

●以下是缺點:

a.目前的複製僅僅支持InnoDB存儲引擎

b.DELETE操作不支持沒有主鍵的表

c.在多主環境下LOCK/UNLOCK TABLES不支持以及鎖函數GET_LOCK(), RELEASE_LOCK()

d.由於集羣是樂觀的併發控制,事務commit可能在該階段中止。

e.整個集羣的寫入吞吐量是由最弱的節點限制,如果有一個節點變得緩慢,那麼整個集羣將是緩慢的。爲了穩定的高性能要求,所有的節點應使用統一的硬件。

◆LSM Tree,主要應用於nessDB、leveldb、hbase:

●核心思想的核心就是放棄部分讀能力,換取寫入的最大化能力。它假設假定內存足夠大,因此不需要每次有數據更新就必須將數據寫入到磁盤中,而可以先將最新的數據駐留在內存中,等到積累到最後多之後,再使用歸併排序的方式將內存內的數據合併追加到磁盤隊尾。(使用歸併排序是要因爲帶排序樹都是有序樹)

●LSM具有批量特性,存儲延遲。B樹在insert的時候可能會造成分裂,可能會造成隨機讀寫。而LSM將多次單頁隨機寫,變成一次多頁隨機寫,複用了磁盤尋道時間,極大提升效率。

●LSM Tree放棄磁盤讀性能來換取寫的順序性。

●一般會使用Bloom Filter來優化LSM。當將內存中的數據與磁盤數據合併的時候,先要判斷數據是否有重複,如果不用Bloom Filter就需要在磁盤上一層層地找,而使用了之後就會降低搜索代價。

3.多線程

◆synchronized、

◆CAS

◆Collections

◆支持高併發的數據結構,如ConcurrentHashMap

◆基於AQS實現的鎖、信號量、計數器原理

◆Runnable與Callable的區別

◆線程池:

●作用:a.減少在創建和銷燬線程上所花的時間以及系統資源的開銷 。

b.當前任務與主線程隔離,能實現和主線程的異步執行,特別是很多可以分開重複執行的任務。

◆阻塞隊列

◆threadlocal

4.框架

◆Spring

●IOC/DI

●Core、Beans、Context、Expression Language

●JDBC、ORM、OXM、JMS、Transaction

●AOP

●Web

●Test

●@Autowired原理:a.工廠模式 b.反射

●自動配置: a.@ConfigurationProperties(prefix = "hello"):讀取以hello爲開頭的配置,屬性類使用

b.@Configuration:指名當前類爲配置類

c.@EnableConfigurationProperties(Properties):指名配置屬性類

d.@ConditionalOnClass(Condition.class):條件類,只有Condition.class存在,當前配置類才生效

e.Spring Boot在spring.factories配置了很多全限定名的配置類。

◆Netty架構

◆Redis:

●核心原理

●常用數據類型:

a.String:二進制安全,可以存任何數據,比如序列化的圖片。最大長度位512M.

b.Hash:是KV對集合,本質是String類型的KV映射,適合存儲對象。

c.List:簡單字符串鏈表,可以在left、right兩邊插入,本質是雙向鏈表。緩衝區也是用這個實現。

d.Set:String類型的無序集合,內部實現是一個 value永遠爲null的HashMap,實際就是通過計算hash的方式來快速排重的,這也是set能提供判斷一個成員是否在集合內的原因。

e.zset:有序集合,每個元素會關聯一個double類型的score,然後根據score進行排序。注意:元素不能重複,但是score是可以重複的。使用HashMap和跳躍表(SkipList)來保證數據的存儲和有序,HashMap裏放的是成員到score的映射,而跳躍表裏存放的是所有的成員,排序依據是HashMap裏存的score.

f.pub/sub:在Redis中,你可以設定對某一個key值進行消息發佈及消息訂閱,當一個key值上進行了消息發佈後,所有訂閱它的客戶端都會收到相應的消息。

●持久化:

a.RDB:一種是手動執行持久化命令來持久化快照;另一種是在配置文件中配置策略,來自動持久化。持久化命令有save、bgsave兩種,bgsave會調用fork命令,產生子進程來進行持久化,而父進程繼續處理數據,但是持久化的快照是fork那一刻的快照,因此這種策略可能會丟失一部分數據。特點:每次都記錄所有數據,恢復快,子進程不影響父進程性能。

b.AOF:append only file,將每條操作命令都記錄到appendonly.aof文件中,但是不會立馬寫入硬盤,我們可以配置always(每有一個命令,都同b就夠了。aof數據損失要比RDB小。特點:有序記錄所有操作,數據丟失更少,會對操作做壓縮優化,bgrewriteaof也會fork子進程,不影響父進程性能

●事務:

a.Transactions:不是嚴格的ACID的事務,但是這個Transactions還是提供了基本的命令打包執行的功能(在服務器不出問題的情況下,可以保證一連串的命令是順序在一起執行的,中間有會有其它客戶端命令插進來執行)。

b.Redis還提供了一個Watch功能,你可以對一個key進行Watch,然後再執行Transactions,在這過程中,如果這個Watched的值進行了修改,那麼這個Transactions會發現並拒絕執行。

◆KafKA:

●topic

●broker

●partition

●consumer

●producer

●stream

●存儲機制

●網絡模型

●注意:partition之間是無序的

●消息隊列的生產者消費者中消費者沒有收到消息怎麼辦,消息有順序比如1.2.3但是收到的卻是1.3.2怎麼辦?消息發過來的過程中損壞或者出錯怎麼辦

◆Spring security:

●攔截器棧

●@PreAuthorize

●@PostAuthorize

●支持Expression Language

5.jvm原理

◆內存模型

◆垃圾收集器,CMS與G1是重點:

●垃圾收集算法: a.標記-清除(CMS)容易產生碎片,當碎片太多會提前觸發Full GC

b.複製(年輕代基本用這個算法)會浪費一半的可能感覺

c.標記-整理(serial Old、Parallel Old)

●Serial:採用單線程stop-the-world的方式進行收集。當內存不足時,串行GC設置停頓標識,待所有線程都進入安全點(Safepoint)時,應用線程暫停,串行GC開始工作,採用單線程方式回收空間並整理內存。串行收集器特別適合堆內存不高、單核甚至雙核CPU的場合。

●ParNew

●Parallel Scavenge

●CMS:a.初始標記(stop of world)

b.並行標記、預清理

c.重新標記(stop of world)

d.並行清理

e.重置

●G1:將堆分成很多region,可以同時堆年輕代與老年代進行收集:

a.初始標記(stop of world):初始標記(Initial Mark)負責標記所有能被直接

b.可達的根對象(原生棧對象、全局對象、JNI對象)

c.並行標記:

d.重新標記(stop of world):

e.清理(stop of world):

f.重置:

g.Pause Prediction Model(停頓預測模型):核心代碼MAX2(seq->davg() + sigma() * seq->dsd(),seq->davg() * confidence_factor(seq->num()));其中seq->davg()表示衰減均值,sigma()返回一個係數,表示信賴度,dsd表示衰減標準偏差,confidence_factor表示可信度相關係數。

●gc觸發條件:

a.從年輕代分區拷貝存活對象時,無法找到可用的空閒分區,會觸發Minor GC

b.從老年代分區轉移存活對象時,無法找到可用的空閒分區,會觸發Major GC

c.分配巨型對象時在老年代無法找到足夠的連續分區,會觸發Major GC

●可達性分析:通過檢查一塊內存空間能否被root達到,來判斷是否對其進行回收。

◆jdk不同版本新增的部分特性:

●1.7:a.switch語句中支持使用字符串了

b.try catch支持捕獲多個異常,豎線分割異常即可

c.try塊中使用的資源可以不用手動在finally中關閉

d.支持 List tempList = new ArrayList<>()的聲明方式,其實是泛型實例化類型自動推斷。

e.提供自定義關閉類的接口,實現AutoCloseable ,就可以在類銷燬的時候自動關閉一些資源。

●1.8:a.接口的默認方法

b.Lambda 表達式,@FunctionInterface註解

c.允許你使用 :: 關鍵字來傳遞方法或者構造函數引用

d.在包java.time下包含了一組全新的時間日期API。

◆jvm調優:

●VisualVM:JDK自帶JVM可視化工具,能過對內存、gc、cpu、thread、class、變量等等信息進行可視化。

◆類加載:

●類加載器: a.Bootstrap ClassLoader:由c語言實現,用來加載JVM自身工作需要的類。這個類不在雙親委派體系中。

b.ExtClassLoader:用於加載java\jre\lib\ext目錄下的jar

c.AppClassLoader:父類加載器爲ExtClassLoader,會加載classpath下所有的類。

●類加載方式: a.隱士加載:不通過代碼裏面調用ClassLoader來加載需要的類,而是通過JVM來自動加載需要的類到內存。

b.顯示加載:通過調用ClassLoader.loadClass或Class.forName(),或自己實現ClassLoader的findClass方法來加載類。

●自定義ClassLoader:父類加載器總是getSystemClassLoader()方法獲取到的ClassLoader。因爲不管調用哪個父類加載器,創建對象最終都會調用getSystemClassLoader作爲父加載器,在一般應用中getSystemClassLoader會獲取AppClassLoader,但在tomcat中getSystemClassLoader()會返回StandardClassLoader。

●流程:加載(調用findClass方法)->驗證(各種檢查)->準備(將靜態屬性用零值初始化)->解析(將符號引用替換成直接引用)->初始化(調用clinit方法)

●雙親委派:記載一個類的時候,會先遞歸檢查父類是否加載過,避免重加載。如果發生重加載,那原來的類與新加載的類 stanceof判斷是false。

◆熱部署:利用判斷兩個class是否是同一個,需要校驗類名與類加載器是否一樣的原理。熱部署的類都是用完釋放,每次使用都先new一個classLoader,然後用這個classLoader來加載這個類,這樣生成的類雖然與之前的名稱一樣,但是實際上不是同一個。

◆javac編譯器:

●讀取源碼

●詞法分析,從原文件的字符開始,按照java語法規範依次找出package、import、類定義、屬性、方法、關鍵詞等。

●語法分析,形成一顆符合java規範的抽象語法樹,它能將主要詞法用一個結構化的形式去表達。

●語義分析,將一些難懂的、複雜的語法轉化爲更加簡單的語法。比如添加解除語法糖、默認構造方法、檢查語句是否可達、檢查變量類型是否匹配、檢查checked exception 是否捕捉或拋出.

●通過字節碼生成器生成字節碼

◆interface可以多繼承;class只能單繼承,多實現

◆String:

●無法被繼承,因爲它是final class,其被設計成final主要出於以下考慮:

a.字符串常量池的需要。字符串常量池的誕生是爲了提升效率和減少內存分配。字符串重複的可能性很高,並且其不可變性能夠方便常量池優化。

b.安全性考慮。正因爲使用字符串的場景如此之多,所以設計成不可變可以有效的防止字符串被有意或者無意的篡改。(但是通過反射還是可以入侵的)

c.作爲HashMap、HashTable等hash型數據key的必要。因爲不可變的設計,jvm底層很容易在緩存String對象的時候緩存其hashcode,這樣在執行效率上會大大提升。

●String.equals()是的實現是逐字符比較兩個String對象的char,而==是比較引用。

●String.intern()會獲取在字符串常量池中的字符串對象,如果該字符串不在常量池中,那會將它假如常量池,然後再返回該對象。因此如果連個String的值一樣,那麼調用intern()方法返回的都是其再常量池中的對象,而常量池中一樣的字符串只有一個對象,因此使用==比較也是true。

◆int的範圍-2^32~2^32-1

◆序列化的底層實現

◆java深拷貝:

●實現Cloneable接口的clone方法

●通過序列化實現

6.設計模式

◆單例:

●雙重檢查

●靜態內部類

●枚舉(jdk1.8之後支持)

◆觀察者模式

◆裝飾者模式:jdk中輸入輸出流用到了該模式

◆適配器模式:jdk中Reader、writer用到了該模式

◆代理模式:

●靜態代理

●JDK動態代理

●Cglib到動態代理

◆生產者消費者模式

◆工廠模式

7.項目管理與運維工具

◆git+Jenkins

◆maven

◆K8S:

●pod:Pod是所有業務類型的基礎,所有的容器均在Pod中運行,它是一個或多個容器的組合。每一個Pod都會被指派一個唯一的Ip地址,在Pod中的每一個容器共享網絡命名空間,包括Ip地址和網絡端口。Pod能夠被指定共享存儲卷的集合,在Pod中所有的容器能夠訪問共享存儲卷,允許這些容器共享數據。

●kubelet:kubelet負責管理pods和它們上面的容器,images鏡像、volumes、etc。

●kube-proxy:爲Service提供cluster內部的服務發現和負載均衡;

●etcd:所有master的持續狀態都存在etcd的一個實例中。這可以很好地存儲配置數據。因爲有watch(觀察者)的支持,各部件協調中的改變可以很快被察覺。

●一旦一個Pod被創建,系統就會不停的監控Pod的健康情況以及Pod所在主機的健康情況,如果這個Pod因爲軟件原因掛掉了或者所在的機器掛掉了,replication controller 會自動在一個健康的機器上創建一個一摸一樣的Pod,來維持原來的Pod冗餘狀態不變,一個應用的多個Pod可以共享一個機器。

●ingress,用於負載均衡

◆docker:

●docker與虛擬機的區別

8.數據結構

◆平衡二叉樹AVL:

●高度log(n)

●插入時間複雜度log(n)

◆紅黑樹:

●插入時間複雜度log(n)

●查找時間複雜度log(n)

●在查找是,紅黑樹雖然複雜度也是log(n),但是從效率上比要略低於AVL。但是其優勢在於插入元素的時候,不會像AVL那樣頻繁地旋轉。

◆B+Tree:只有葉子節點存值,非葉子節點只存key和child,因此同樣大小的物理頁上能存放更多的節點。每一層的節點數量越多,意味着層次越少,也就意味着IO次數越少,因此非常適合數據庫以及文件系統。

◆大根堆:採用數組存儲樹,是一個完全樹。先插入到數組最後的位置上,然後採用上浮的思想,將該元素與比它小的父元素調換,直到parent>target,浮到root;然後將root與未排序的最後一個元素交換位置;重複以上步驟,直到所有元素都有序。插入如查找的複雜度都是log(n)。

◆優先隊列PriorityQueue,Java中使用小根堆實現,非線程安全。

◆優先阻塞隊列PriorityBlockQueue,線程安全。

9.算法

◆快排:

●時間複雜度O(nlog(n))

●空間複雜度O(log(n))

◆堆排序:

●時間複雜度O(nlog(n))

●空間複雜度O(1)

◆歸併排序:

●時間複雜度O(nlog(n))

●空間複雜度O(n)

◆跳錶:

●時間複雜度O(log(n))

●空間複雜度O(2n)

●高度O(log(n))

10.分佈式

◆cap理論:

●可用性

●一致性

●分區容忍性:對網絡斷開的容忍度,有點像魯棒性

◆拜占庭將軍問題:

●問題描述:拜占庭帝國即中世紀的土耳其,擁有巨大的財富,周圍10個鄰邦垂誕已久,但拜占庭高牆聳立,固若金湯,沒有一個單獨的鄰邦能夠成功入侵。任何單個鄰邦入侵的都會失敗,同時也有可能自身被其他9個鄰邦入侵。拜占庭帝國防禦能力如此之強,至少要有十個鄰邦中的一半以上同時進攻,纔有可能攻破。然而,如果其中的一個或者幾個鄰邦本身答應好一起進攻,但實際過程出現背叛,那麼入侵者可能都會被殲滅。於是每一方都小心行事,不敢輕易相信鄰國。這就是拜占庭將軍問題。這個問題的本質是要達成一致的共識。

●Raft 算法:a.有leader、follower、candidate

b.選主流程:

i.在最初,還沒有一個主節點的時候,所有節點的身份都是Follower。每一個節點都有自己的計時器,當計時達到了超時時間(Election Timeout),該節點會轉變爲Candidate。

ii.成爲Candidate的節點,會首先給自己投票,然後向集羣中其他所有的節點發起請求,要求大家都給自己投票。

iii.其他收到投票請求且還未投票的Follower節點會向發起者投票,發起者收到反饋通知後,票數增加。

iv.當得票數超過了集羣節點數量的一半,該節點晉升爲Leader節點。Leader節點會立刻向其他節點發出通知,告訴大家自己纔是老大。收到通知的節點全部變爲Follower,並且各自的計時器清零。

v.注意:每個節點的超時時間都是不一樣的。比如A節點的超時時間是3秒,B節點的超時時間是5秒,C節點的超時時間是4秒。這樣一來,A節點將會最先發起投票請求,而不是所有節點同時發起。如果所有節點同時發起投票,必然會導致大家的票數差不多,形成僵局,誰也當不成老大。一旦Leader節點掛掉,發不出通知,那麼計時達到了超時時間的Follower節點會轉變爲Candidate節點,發起選主投票,周而復始。

●同步流程: a.由客戶端提交數據到Leader節點。

b.由Leader節點把數據複製到集羣內所有的Follower節點。如果一次複製失敗,會不斷進行重試。

c.Follower節點們接收到複製的數據,會反饋給Leader節點。

d.如果Leader節點接收到超過半數的Follower反饋,表明複製成功。於是提交自己的數據,並通知客戶端數據提交成功。

e.由Leader節點通知集羣內所有的Follower節點提交數據,從而完成數據同步流程。

◆zookeeper,參考博客1,參考博客2:

●leader:複製進行投票的發起和決議,更新系統狀態。

●follower:接收client的請求並返回結果,在選主過程中進行投票。

●observer:接收client連接,並將請求轉發給leader節點。在不參加投票,只是同步leader狀態。

●client:請求發起方。

●Zab(Zookeeper Atomic Broadcast)協議,有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。

a.選主:有兩種算法:1. basic paxos;2. fast paxos(默認)

b.basic paxos流程: i.當前Server擔任選舉線程,其主要功能是對投票結果進行統計,並選出推薦的Server。

ii.選舉線程首先向所有Server發起一次詢問(包括自己);

iii.選舉線程收到回覆後,驗證是否是自己發起的詢問(驗證zxid是否一致),然後獲取對方的id(myid),並存儲到當前詢問對象列表中,最後獲取對方提議的leader相關信息(id,zxid),並將這些信息存儲到當次選舉的投票記錄表中;

iv.收到所有Server回覆以後,就計算出zxid最大的那個Server,並將這個Server相關信息設置成下一次要投票的Server;

v.線程將當前zxid最大的Server設置爲當前Server要推薦的Leader,如果此時獲勝的Server獲得n/2 + 1的Server票數, 設置當前推薦的leader爲獲勝的Server,將根據獲勝的Server相關信息設置自己的狀態,否則,繼續這個過程,直到leader被選舉出來。

●同步流程:

a.leader等待server連接;

b.Follower連接leader,將最大的zxid發送給leader;

c.Leader根據follower的zxid確定同步點;

d.完成同步後通知follower 已經成爲uptodate狀態;

f.Follower收到uptodate消息後,又可以重新接受client的請求進行服務了。

●事務順序一致性:採用了遞增的事務id號(zxid)來標識事務。所有的提議(proposal)都在被提出的時候加上了zxid。

●server的狀態:

a.LOOKING:當前Server不知道leader是誰,正在搜尋

b.LEADING:當前Server即爲選舉出來的leader

c.FOLLOWING:leader已經選舉出來,當前Server與之同步

●文件系統:zookeeper的通知機制、分佈式鎖、隊列管理、配置管理都是基於文件系統的。文件系統中有一下幾種節點:

a.PERSISTENT-持久化目錄節點,客戶端與zookeeper斷開連接後,該節點依舊存在 。

b.PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點,客戶端與zookeeper斷開連接後,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號。

c.EPHEMERAL-臨時目錄節點,客戶端與zookeeper斷開連接後,該節點被刪除。

d.EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點,客戶端與zookeeper斷開連接後,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號。

●通知機制:客戶端註冊監聽它關心的目錄節點,當目錄節點發生變化(數據改變、被刪除、子目錄節點增加刪除)時,zookeeper會通知客戶端。

●配置管理:把這些配置全部放到zookeeper上去,保存在 Zookeeper 的某個目錄節點中,然後所有相關應用程序對這個目錄節點進行監聽,一旦配置信息發生變化,每個應用程序就會收到 Zookeeper 的通知,然後從 Zookeeper 獲取新的配置信息應用到系統中。

●分佈式鎖:有了zookeeper的一致性文件系統,鎖的問題變得容易。鎖服務可以分爲兩類,一個是保持獨佔,另一個是控制時序。

a.獨佔鎖:將zookeeper上的一個znode看作是一把鎖,通過createznode的方式來實現。所有客戶端都去創建 /distribute_lock 節點,最終成功創建的那個客戶端也即擁有了這把鎖。用完刪除掉自己創建的distribute_lock 節點就釋放出鎖。

b.控制時序鎖:/distribute_lock 已經預先存在,所有客戶端在它下面創建臨時順序編號目錄節點,和選master一樣,編號最小的獲得鎖,用完刪除。

●隊列管理,分爲同步隊列、非同步隊列:

a.同步隊列,當一個隊列的成員都聚齊時,這個隊列纔可用,否則一直等待所有成員到達。 在約定目錄下創建臨時目錄節點,監聽節點數目是否是我們要求的數目。

b.隊列按照 FIFO 方式進行入隊和出隊操作。和分佈式鎖服務中的控制時序場景基本原理一致,入列有編號,出列按編號。

●數據複製的好處:a.容錯:一個節點出錯,不致於讓整個系統停止工作,別的節點可以接管它的工作;b.提高系統的擴展能力 :把負載分佈到多個節點上,或者增加節點來提高系統的負載能力;

提高性能:讓客戶端本地訪問就近的節點,提高用戶訪問速度。

●數據複製集羣系統分下面兩種:a.寫主(WriteMaster) :對數據的修改提交給指定的節點。讀無此限制,可以讀取任何一個節點。這種情況下客戶端需要對讀與寫進行區別,俗稱讀寫分離;b.寫任意(Write Any):對數據的修改可提交給任意的節點,跟讀一樣。這種情況下,客戶端對集羣節點的角色與變化透明。

◆Broker模式:主要有這6個類:Client,Server,Client_Proxy,Server_Proxy,Broker,Bridge。

●Server:就是我們根據業務寫的服務。

●Client:請求發起方,Client發送請求到Broker,並從Broker上接收響應或異常。Client和Server只是邏輯上相關而已,實際上Client並不知道Server的確切位置。

●Broker:成消息轉發器。Broker也負責一些控制和管理操作。它能夠定位服務端的位置,若發生異常,能夠將異常捕獲傳給Client。Broker需要提供註冊服務的接口給Server。

●Client_Proxy:連繫Client和Broker,這一層保證了通訊的透明性,使Client調用遠程服務就像調用本地的服務一樣。

●Server_Proxy:與Client_Proxy相對應的,它接受請求,解包消息,解析出參數並調用服務的實現接口。

●Bridge:Bridge用來連接各個Broker,一般這個組件是可選的。

◆一致性hash算法原理

◆微服務

●Spring cloud:

a.網關:zuul

b.分佈式\版本化配置 config

c.服務註冊和發現:Eureka,配置時需要注意多久刷新列表一次,多久監測心跳等。

d.service-to-service 調用

e.負載均衡:Ribbon;在生成RestTemplate的bean時,通過@LoadBalanced註解可以使得RestTemplate的調用

f.斷路器:Hystrix

g.監控:spring admin。在啓動類上加@EnableAdminServer註解。

11.java web

◆servlet工作原理:

●創建:如果load-on-startup>0,那就會在Context容器啓動的時候實例化。1、Wrapper.loadServlet獲取servletClass。2、傳給InstanceManager創建對象。

●初始化:即調用Servlet的init方法

◆tomcat工作原理,好文,強推

●service,一個server有多個service,一個service有一個container與多個connector

●connector,負責接受請求,並將請求封裝成request,同時創建repsonse對象傳給container。

●container: a.engine

b.host,一個端口一個,或tomcat上面一個服務一個

c.context,管理多個wrapper,是servlet的運行環境

d.wrapper,一個servlet一個

12.linux

◆系統結構,講得很好,強推

◆硬鏈接與軟連接:

●硬鏈接:數據節點通過引用計數的方式來對指向它的硬鏈接計數,當計數爲0就刪除。

●軟連接:我們可以把它看成是快捷方式,它只是記錄了某個文件的硬鏈接的路徑,如果我們把源文件刪除,再重新創建一個相同名字的文件,那麼軟連接指向的就是新創建的文件。

◆虛擬文件系統(VFS):文件系統是有很多實現的,比如ext2、ext3、FAT等等,而VFS則是存在於應用程序與文件系統中間,它封裝了open、close、read、write等等操作文件系統的接口,爲應用程序屏蔽掉不同文件系統之間的差異。

◆VFS數據結構

13.其它

◆bitmap,大文件交集

◆Elasticsearch索引原理

◆從內存到屏幕經歷了啥

◆高併發場景的限流,你怎麼來確定限流限多少,模擬場景和實際場景有區別怎麼解決,

14.EMC面試

◆說一下redis與kafka,redis持久化策略

◆git中rebase與merge區別

◆docker底層原理,依賴操作系統的什麼

◆ls -l | grep xxx的執行過程,儘可能的細,是多進程還是單進程?

◆兩個有序數組求中位數

◆算法 3Sum、中序遍歷非遞歸實現、循環打印矩陣

◆final、finally、finanize

◆jvm內存模型

◆垃圾回收器

◆Spring特點介紹下

◆Synchronize與ReentrantLock的區別、使用場景

◆CAS使用場景

◆聊了下git+jekins+K8S+docker實現自動化部署

◆innodb原理,使用場景,與MYISAM在場景上的區別

◆weakReference、softReference等

◆Hbase的原理,LSM Tree

◆Linux中,哪種進程可以使用管道

15.美團

◆權限模型

◆介紹下線程池,阻塞隊列的用法,無界隊列真的無界嗎?

◆說一下redis

◆kafka存儲模型與網絡模型

◆zookeeper與redis實現分佈式鎖

◆樂觀鎖與悲觀鎖

◆算法:有n個人,給你ai與aj的身高關係,如ai比aj高,進行身高排序,如果條件不滿足,則輸出“不滿足”

◆Spring boot的特性

相關文章