(高頻問題)161-180 計(jì)算機(jī) Java后端 實(shí)習(xí) and 秋招 面試高頻問題匯總
161. Kafka分區(qū)機(jī)制與多實(shí)例環(huán)境下的消息順序性
Kafka通過分區(qū)(Partition)機(jī)制來提高吞吐量和實(shí)現(xiàn)負(fù)載均衡。在單個(gè)分區(qū)內(nèi)部,Kafka能夠保證消息的嚴(yán)格順序性,即消息按照生產(chǎn)者發(fā)送的順序被存儲(chǔ)和消費(fèi)。如果生產(chǎn)者將一系列消息指定發(fā)送到同一個(gè)分區(qū),并且這些消息都成功寫入,那么消費(fèi)者在拉取該分區(qū)的消息時(shí),將嚴(yán)格按照發(fā)送順序接收到它們。
然而,在多實(shí)例部署的生產(chǎn)者環(huán)境中,即使指定了分區(qū),也可能出現(xiàn)消費(fèi)者感知到的消息順序與預(yù)期不符的情況。這主要源于以下幾個(gè)因素:
首先,多個(gè)生產(chǎn)者實(shí)例并發(fā)地向同一分區(qū)發(fā)送消息時(shí),網(wǎng)絡(luò)延遲、客戶端處理速度差異以及Broker端的處理時(shí)序可能導(dǎo)致消息實(shí)際落盤的順序與任何單個(gè)生產(chǎn)者的發(fā)送順序不一致,形成局部的亂序。
其次,生產(chǎn)者的消息重試機(jī)制可能導(dǎo)致亂序。當(dāng)一條消息發(fā)送失敗(如網(wǎng)絡(luò)抖動(dòng)或Broker短暫不可用)后,生產(chǎn)者會(huì)進(jìn)行重試。如果在重試成功之前,后續(xù)的消息已經(jīng)先一步發(fā)送成功,那么最終存儲(chǔ)在分區(qū)中的順序就會(huì)與原始發(fā)送順序不同。
再次,異步發(fā)送模式下,消息發(fā)送請(qǐng)求的完成順序并不一定與調(diào)用發(fā)送API的順序一致,這也可能影響消息抵達(dá)Broker并被存儲(chǔ)的順序。
最后,雖然不常見,但若在生產(chǎn)過程中分區(qū)策略發(fā)生改變(例如,通過某種動(dòng)態(tài)邏輯決定分區(qū))或分區(qū)數(shù)量本身進(jìn)行了調(diào)整,也可能間接影響依賴特定分區(qū)順序的消費(fèi)邏輯。
為了在多實(shí)例環(huán)境下最大程度保證業(yè)務(wù)所需的順序性,可以考慮采用單一生產(chǎn)者實(shí)例負(fù)責(zé)關(guān)鍵順序消息的發(fā)送,或者在多個(gè)生產(chǎn)者之間實(shí)現(xiàn)嚴(yán)格的協(xié)調(diào)機(jī)制(如分布式鎖或序號(hào)生成器)來控制發(fā)送順序。同時(shí),消費(fèi)者端也可以設(shè)計(jì)具備排序能力的邏輯,例如根據(jù)消息體中包含的時(shí)間戳或業(yè)務(wù)序列號(hào)進(jìn)行重排序,以應(yīng)對(duì)潛在的順序問題。
162. Redis鍵刪除后的內(nèi)存回收機(jī)制與碎片化處理
Redis在接收到客戶端執(zhí)行的 DEL 命令刪除一個(gè)鍵時(shí),會(huì)觸發(fā)其內(nèi)部的內(nèi)存回收流程。Redis自身管理內(nèi)存,通常使用如jemalloc這樣的高效內(nèi)存分配器,而非直接依賴操作系統(tǒng)的標(biāo)準(zhǔn)內(nèi)存管理。
內(nèi)存回收主要依賴引用計(jì)數(shù)(Reference Counting)機(jī)制。Redis中的數(shù)據(jù)對(duì)象(如字符串、哈希、列表等)都關(guān)聯(lián)有引用計(jì)數(shù)。當(dāng)執(zhí)行DEL命令時(shí),Redis會(huì)找到該鍵所關(guān)聯(lián)的值對(duì)象,并減少其引用計(jì)數(shù)。一旦對(duì)象的引用計(jì)數(shù)降為0,表明不再有任何內(nèi)部結(jié)構(gòu)或鍵指向該對(duì)象,該對(duì)象占用的內(nèi)存就可以被回收了。
內(nèi)存的實(shí)際釋放由Redis集成的**內(nèi)存分配器(如jemalloc)**負(fù)責(zé)。標(biāo)記為可回收的內(nèi)存會(huì)被內(nèi)存分配器收回,這部分內(nèi)存隨后可以被用于存儲(chǔ)新的數(shù)據(jù)。對(duì)于較大的內(nèi)存塊,分配器可能會(huì)將其歸還給操作系統(tǒng);對(duì)于較小的內(nèi)存塊,則通常保留在分配器的內(nèi)部池中,以便快速復(fù)用,減少向操作系統(tǒng)申請(qǐng)內(nèi)存的開銷。
需要注意的是,頻繁的鍵創(chuàng)建和刪除操作,尤其是在對(duì)象大小不一的情況下,可能導(dǎo)致內(nèi)存碎片化。即物理內(nèi)存中存在許多小的、不連續(xù)的空閑塊,雖然總空閑內(nèi)存可能很多,但無法分配給需要較大連續(xù)內(nèi)存的新對(duì)象。
為緩解此問題,較新版本的Redis提供了在線內(nèi)存碎片整理(Active Defragmentation)功能。通過配置開啟后,Redis可以在運(yùn)行時(shí)嘗試移動(dòng)內(nèi)存中的數(shù)據(jù),合并空閑塊,以降低碎片率,但這會(huì)消耗一定的CPU資源。在某些嚴(yán)重碎片化的情況下,通過主從切換進(jìn)行實(shí)例重啟也是一種徹底清理內(nèi)存碎片的方法。
163. HashMap數(shù)據(jù)傾斜問題分析與應(yīng)對(duì)策略
HashMap的數(shù)據(jù)傾斜指的是大量的鍵(Key)經(jīng)過哈希計(jì)算后,被映射到了少數(shù)幾個(gè)桶(Bucket)或槽位(Slot)上,而大部分桶卻很少被使用或完全空閑。理想情況下,HashMap的鍵應(yīng)均勻分布在所有桶中,以確保增、刪、查操作的時(shí)間復(fù)雜度接近O(1)。數(shù)據(jù)傾斜會(huì)導(dǎo)致這些操作在傾斜的桶上退化為鏈表(或紅黑樹)的遍歷,最壞情況下時(shí)間復(fù)雜度可能接近O(n),嚴(yán)重影響性能。
應(yīng)對(duì)HashMap數(shù)據(jù)傾斜可以采取以下策略:
優(yōu)化哈希函數(shù) (Hash Function Optimization):核心在于確保哈希函數(shù)能夠產(chǎn)生分布均勻的哈希碼。如果鍵的 hashCode() 方法實(shí)現(xiàn)不佳,導(dǎo)致大量不同鍵產(chǎn)生相同或相近的哈希碼,或者哈希碼集中在某個(gè)范圍內(nèi),就會(huì)引發(fā)傾斜??梢钥紤]重寫鍵對(duì)象的 hashCode() 方法,使其能更好地結(jié)合鍵自身的內(nèi)容特征,生成更分散的哈希值。
采用一致性哈希 (Consistent Hashing):雖然主要應(yīng)用于分布式系統(tǒng)(如分布式緩存),但其設(shè)計(jì)思想有助于理解和解決數(shù)據(jù)分布問題。一致性哈希通過將哈??臻g組織成一個(gè)哈希環(huán),并將節(jié)點(diǎn)(或在這里可類比為桶)和數(shù)據(jù)的哈希值映射到環(huán)上,數(shù)據(jù)歸屬于其在環(huán)上順時(shí)針遇到的第一個(gè)節(jié)點(diǎn)。虛擬節(jié)點(diǎn)技術(shù)的引入,通過為一個(gè)物理節(jié)點(diǎn)創(chuàng)建多個(gè)虛擬映射點(diǎn),可以進(jìn)一步增強(qiáng)節(jié)點(diǎn)在環(huán)上的均勻度,從而使得數(shù)據(jù)分布更為均衡。此外,其動(dòng)態(tài)調(diào)整特性,即增刪節(jié)點(diǎn)時(shí)僅影響局部數(shù)據(jù),也體現(xiàn)了其對(duì)分布變化的適應(yīng)性。
結(jié)構(gòu)優(yōu)化 (Structural Optimization):Java 8及以后版本的HashMap實(shí)現(xiàn)引入了重要的優(yōu)化。當(dāng)某個(gè)桶中的鏈表長度超過特定閾值(默認(rèn)為8),并且HashMap的總?cè)萘看笥诘扔?4時(shí),該鏈表會(huì)轉(zhuǎn)換為紅黑樹進(jìn)行存儲(chǔ)。紅黑樹的查找、插入、刪除操作的時(shí)間復(fù)雜度為O(log n),這顯著改善了在嚴(yán)重哈希沖突(即數(shù)據(jù)傾斜)情況下的查詢性能,雖然不能完全消除傾斜的影響,但能有效緩解其帶來的性能退化。
164. JVM新生代對(duì)象晉升老年代的機(jī)制
Java虛擬機(jī)(JVM)的堆內(nèi)存通常采用分代收集策略,劃分為新生代(Young Generation)和老年代(Old Generation)。新生代又細(xì)分為Eden區(qū)和兩個(gè)Survivor區(qū)(通常稱為S0和S1)。對(duì)象晉升老年代主要發(fā)生在新生代的垃圾收集(Minor GC)過程中。
新創(chuàng)建的對(duì)象通常首先被分配在Eden區(qū)。當(dāng)Eden區(qū)空間不足時(shí),會(huì)觸發(fā)一次Minor GC。Minor GC采用**復(fù)制算法(Copying Algorithm)**進(jìn)行垃圾回收。其過程大致為:將Eden區(qū)和當(dāng)前使用的那個(gè)Survivor區(qū)(稱為from區(qū),例如S0)中仍然存活的對(duì)象,復(fù)制到另一個(gè)空的Survivor區(qū)(稱為to區(qū),例如S1)。在復(fù)制過程中,每個(gè)存活對(duì)象的年齡(Age)會(huì)增加1。對(duì)象的初始年齡為0。
對(duì)象晉升到老年代(Old Generation)主要基于對(duì)象年齡閾值。JVM會(huì)設(shè)定一個(gè)晉升閾值(Promotion Age Threshold),可以通過參數(shù) -XX:MaxTenuringThreshold 指定(默認(rèn)通常是15)。當(dāng)一個(gè)對(duì)象在Survivor區(qū)中經(jīng)歷多次Minor GC后,其年齡達(dá)到了這個(gè)閾值,它就會(huì)在下一次Minor GC時(shí)被移動(dòng)到老年代,而不是復(fù)制到另一個(gè)Survivor區(qū)。
此外,還存在一些特殊情況可能導(dǎo)致對(duì)象提前晉升或直接在老年代分配:
- 動(dòng)態(tài)年齡判斷:如果在一次Minor GC后,to Survivor區(qū)中相同年齡所有對(duì)象大小的總和大于Survivor空間的一半,那么年齡大于或等于該年齡的對(duì)象也會(huì)被直接晉升到老年代,無需等到MaxTenuringThreshold。
- 大對(duì)象直接進(jìn)入老年代:如果創(chuàng)建了一個(gè)非常大的對(duì)象,新生代無法容納(特別是Eden區(qū)和from Survivor區(qū)都放不下),JVM可能會(huì)嘗試將其直接分配在老年代。這可以通過參數(shù) -XX:PretenureSizeThreshold 控制。
165. MySQL可重復(fù)讀隔離級(jí)別與MVCC機(jī)制的協(xié)同工作
MySQL InnoDB存儲(chǔ)引擎默認(rèn)的事務(wù)隔離級(jí)別是可重復(fù)讀(Repeatable Read, RR)。該級(jí)別的核心目標(biāo)是確保在同一個(gè)事務(wù)內(nèi)部,多次讀取同一行數(shù)據(jù)的結(jié)果始終保持一致,不會(huì)看到其他并發(fā)事務(wù)在此期間對(duì)該行數(shù)據(jù)所做的修改(已提交的修改也不可見),從而避免了“不可重復(fù)讀”問題。在InnoDB中,RR級(jí)別還能在一定程度上防止“幻讀”。
多版本并發(fā)控制(Multi-Version Concurrency Control, MVCC)是InnoDB存儲(chǔ)引擎用來實(shí)現(xiàn)高并發(fā)事務(wù)處理的一種關(guān)鍵技術(shù),它并非與可重復(fù)讀隔離級(jí)別相悖,反而是實(shí)現(xiàn)該隔離級(jí)別的底層機(jī)制。MVCC的核心思想是為數(shù)據(jù)庫中的每一行數(shù)據(jù)維護(hù)多個(gè)版本。
MVCC與可重復(fù)讀協(xié)同工作的原理如下:當(dāng)一個(gè)事務(wù)開始時(shí)(在RR級(jí)別下,通常是執(zhí)行第一條查詢語句時(shí)),InnoDB會(huì)為該事務(wù)創(chuàng)建一個(gè)一致性視圖(Read View),也稱為快照(Snapshot)。該事務(wù)后續(xù)的所有一致性讀(Consistent Read)操作(即普通的SELECT語句)都會(huì)基于這個(gè)快照來進(jìn)行。這意味著事務(wù)只能看到在創(chuàng)建快照那一刻之前已經(jīng)提交的數(shù)據(jù)版本,而對(duì)于在快照創(chuàng)建之后其他事務(wù)所做的修改(即使已提交),該事務(wù)是“看不見”的。
寫操作(如INSERT, UPDATE, DELETE)并不會(huì)直接覆蓋舊數(shù)據(jù),而是會(huì)創(chuàng)建數(shù)據(jù)的新版本,并記錄下執(zhí)行該操作的事務(wù)ID。舊版本的數(shù)據(jù)會(huì)保留下來,直到不再被任何活躍事務(wù)的快照所需要時(shí),才會(huì)被后臺(tái)的Purge線程清理。
因此,MVCC通過讓讀操作訪問數(shù)據(jù)的歷史版本(快照),實(shí)現(xiàn)了讀寫操作的非阻塞,極大地提高了數(shù)據(jù)庫的并發(fā)性能。同時(shí),正是由于事務(wù)讀取的是其啟動(dòng)時(shí)刻的數(shù)據(jù)快照,確保了在整個(gè)事務(wù)期間讀取到的數(shù)據(jù)是一致的,完美地支撐了可重復(fù)讀隔離級(jí)別的要求。所以,MVCC不僅不違背可重復(fù)讀,反而是InnoDB實(shí)現(xiàn)高并發(fā)下可重復(fù)讀隔離級(jí)別的基石。
166. 經(jīng)典取石子博弈(每次取1-3個(gè))的必勝策略分析
這是一個(gè)經(jīng)典的博弈論問題,屬于取物游戲(如Nim游戲)的一種變體。規(guī)則為:兩名玩家輪流從一堆石子中取出石子,每次最少取1個(gè),最多取3個(gè),取走最后一個(gè)石子的玩家獲勝。此游戲存在明確的必勝策略,其核心在于控制剩余石子的數(shù)量。
該策略基于一個(gè)關(guān)鍵數(shù):4(即可取數(shù)量的最大值3加1)。如果一個(gè)玩家在自己操作結(jié)束后,能確保留給對(duì)手的石子數(shù)量是4的倍數(shù),那么該玩家就掌握了主動(dòng)權(quán)。因?yàn)闊o論對(duì)手接下來取走1、2或3個(gè)石子,剩余石子的數(shù)量將不再是4的倍數(shù)。此時(shí),輪到的玩家總可以通過取走相應(yīng)數(shù)量(3、2或1個(gè))的石子,使得剩余石子數(shù)量再次變?yōu)?的倍數(shù)。
因此,必勝策略的實(shí)施取決于游戲開始時(shí)石子的總數(shù)N:
- 如果 N 是 4 的倍數(shù),那么先手玩家(第一個(gè)取石子的玩家)天然處于劣勢。只要后手玩家每次都采取與先手玩家互補(bǔ)的策略(即如果先手取k個(gè),后手就取4-k個(gè)),就能確保每次留給先手玩家的都是4的倍數(shù),最終后手玩家將取走最后一顆石子獲勝。
- 如果 N 不是 4 的倍數(shù),那么先手玩家可以通過第一次操作,取走 N % 4 個(gè)石子(即N除以4的余數(shù)個(gè)石子,這個(gè)數(shù)量必然在1-3之間),使得剩余石子數(shù)量變?yōu)?的倍數(shù)。此后,無論對(duì)手如何取,先手玩家始終可以采取上述互補(bǔ)策略,確保每次都留給對(duì)手4的倍數(shù)的石子,從而確保自己最終獲勝。
關(guān)鍵在于,有策略的一方需要始終致力于在自己的回合結(jié)束后,讓石子堆的數(shù)量成為4的倍數(shù)。
167. HashSet 內(nèi)部實(shí)現(xiàn):值(Value)的角色與 HashMap 的關(guān)聯(lián)
Java中的 HashSet 在其內(nèi)部實(shí)現(xiàn)上,是基于 HashMap 來構(gòu)建的。HashSet 的核心目標(biāo)是存儲(chǔ)一組唯一的元素,它不關(guān)心元素對(duì)應(yīng)的值,只關(guān)注元素(鍵)本身是否存在。
為了利用 HashMap 高效的鍵查找和唯一性保證機(jī)制,HashSet 將其存儲(chǔ)的元素作為 HashMap 的鍵(Key)。然而,HashMap 要求每個(gè)鍵都必須關(guān)聯(lián)一個(gè)值(Value)。由于 HashSet 的語義中值是無意義的,為了節(jié)省內(nèi)存空間并簡化實(shí)現(xiàn),HashSet 采用了一個(gè)巧妙的方法:它為內(nèi)部 HashMap 中的所有鍵都關(guān)聯(lián)同一個(gè)、預(yù)定義的靜態(tài)對(duì)象作為值。
這個(gè)充當(dāng)“啞值”(Dummy Value)的對(duì)象通常是一個(gè)內(nèi)部定義的、私有的靜態(tài)常量,例如:
// 在 HashSet 源碼內(nèi)部類似定義 private static final Object PRESENT = new Object();
當(dāng)你調(diào)用 HashSet 的 add(E element) 方法時(shí),內(nèi)部實(shí)際上執(zhí)行的是 map.put(element, PRESENT)。如果 put 操作返回 null(表示 element 是新添加的鍵),則 add 方法返回 true;否則返回 false。由于 PRESENT 是一個(gè)靜態(tài)常量對(duì)象,所有 HashSet 中的條目都共享對(duì)這同一個(gè)對(duì)象的引用,因此并不會(huì)因?yàn)榇鎯?chǔ)這個(gè)“值”而帶來顯著的額外的內(nèi)存開銷。
168. Redis 緩存與數(shù)據(jù)庫一致性策略:延時(shí)雙刪詳解
延時(shí)雙刪(Delayed Double Delete)是解決緩存與數(shù)據(jù)庫數(shù)據(jù)一致性問題的一種常用策略,尤其適用于讀多寫少的業(yè)務(wù)場景。其目的是在更新數(shù)據(jù)庫數(shù)據(jù)時(shí),盡可能地降低緩存中出現(xiàn)臟數(shù)據(jù)的風(fēng)險(xiǎn)。
該策略的操作步驟如下:
- 第一次刪除緩存:在執(zhí)行數(shù)據(jù)庫寫操作(更新或刪除)之前,首先嘗試刪除緩存中對(duì)應(yīng)的條目。這一步旨在防止并發(fā)的讀請(qǐng)求在數(shù)據(jù)庫更新期間讀到舊的緩存數(shù)據(jù)。
- 更新數(shù)據(jù)庫:執(zhí)行實(shí)際的數(shù)據(jù)庫更新或刪除操作。這是數(shù)據(jù)變更的核心步驟。
- 延時(shí)等待:在數(shù)據(jù)庫操作成功后,不立即操作緩存,而是等待一段預(yù)設(shè)的時(shí)間(例如幾百毫秒或根據(jù)業(yè)務(wù)并發(fā)情況估算的時(shí)間)。設(shè)置延時(shí)的核心目的是,允許那些在步驟1(刪除緩存)之后、步驟2(更新數(shù)據(jù)庫)完成之前就已經(jīng)發(fā)起的讀請(qǐng)求有機(jī)會(huì)完成。這些讀請(qǐng)求可能會(huì)因?yàn)榫彺嫖疵卸ゲ樵償?shù)據(jù)庫(此時(shí)可能讀到舊數(shù)據(jù)),并將舊數(shù)據(jù)重新寫入緩存。
- 第二次刪除緩存:延時(shí)結(jié)束后,再次執(zhí)行刪除緩存的操作。這一步是為了清除在延時(shí)期間可能被并發(fā)讀請(qǐng)求重新寫入的臟數(shù)據(jù)(舊數(shù)據(jù)),確保最終緩存被清空,后續(xù)的讀請(qǐng)求將直接從數(shù)據(jù)庫加載最新數(shù)據(jù)。
通過這兩次刪除和中間的延時(shí),延時(shí)雙刪策略提高了數(shù)據(jù)最終一致性的保障程度,但需要注意的是,它并不能完全保證強(qiáng)一致性,且延時(shí)時(shí)間的設(shè)定需要權(quán)衡。
169. Spring Boot 注解失效的常見場景分析(含 @Transactional 特例)
Spring Boot 及 Spring 框架大量使用注解來簡化配置和開發(fā)。然而,在某些情況下注解可能不會(huì)按預(yù)期生效。以下是一些常見的導(dǎo)致注解失效的場景:
首先,注解僅對(duì)由 Spring IoC 容器管理的 Bean 生效。如果你嘗試在通過 new 關(guān)鍵字手動(dòng)創(chuàng)建的對(duì)象實(shí)例上使用 Spring 注解(如 @Autowired, @Component, @Service, @Transactional 等),這些注解將不會(huì)被處理。同時(shí),確保相關(guān)的 Bean 被 Spring 正確掃描并加載到上下文中(例如,組件掃描路徑配置正確,配置類本身被 @Configuration 標(biāo)記并被掃描)。
其次,涉及 AOP(面向切面編程) 的注解(如 @Transactional, @Async, @Cacheable 等)依賴于 Spring 的代理機(jī)制。這引入了幾個(gè)失效點(diǎn):
- 方法可見性:許多 AOP 注解默認(rèn)只對(duì) public 方法生效。將注解用在 protected, private 或包可見方法上可能導(dǎo)致其失效。
- 靜態(tài)方法:Spring AOP 無法代理靜態(tài)方法,因此在靜態(tài)方法上使用這類注解無效。
- 代理模式:Spring AOP 默認(rèn)使用 JDK 動(dòng)態(tài)代理(基于接口)。如果注解應(yīng)用在沒有實(shí)現(xiàn)接口的類上,需要啟用 CGLIB 代理(通過配置 spring.aop.proxy-target-class=true),否則注解可能不生效。注解通常建議標(biāo)注在實(shí)現(xiàn)類而非接口上,以避免代理模式帶來的問題。
此外,循環(huán)依賴問題可能干擾 Bean 的正常初始化過程,間接導(dǎo)致其上的注解無法正常工作。使用 @Conditional 系列注解時(shí),如果其指定的條件未滿足,對(duì)應(yīng)的 Bean 不會(huì)被創(chuàng)建,其上的注解自然也就無從談起。
@Transactional 注解失效的特例:
除了上述通用原因,@Transactional 還有一些特定的失效場景:
- 自調(diào)用問題:在一個(gè) Bean 的內(nèi)部方法調(diào)用另一個(gè)帶有 @Transactional 注解的本類方法時(shí),事務(wù)不會(huì)生效。這是因?yàn)閮?nèi)部調(diào)用沒有經(jīng)過 Spring 生成的代理對(duì)象,而是直接通過 this 引用調(diào)用,繞過了事務(wù)增強(qiáng)邏輯。
- 異常類型與回滾策略:@Transactional 默認(rèn)只在遇到 RuntimeException 或 Error 時(shí)才回滾事務(wù)。如果方法拋出的是受檢查異常(Checked Exception),并且沒有通過 @Transactional(rollbackFor = Exception.class) 等方式顯式指定需要回滾,事務(wù)將不會(huì)回滾。
- 數(shù)據(jù)庫引擎不支持事務(wù):如果底層數(shù)據(jù)庫使用的存儲(chǔ)引擎(如 MySQL 的 MyISAM 引擎)本身不支持事務(wù),那么 @Transactional 注解自然無法產(chǎn)生效果。
170. HTTPS 通信流程詳解:從握手到加密傳輸
HTTPS(Hyper Text Transfer Protocol Secure)是在 HTTP 協(xié)議基礎(chǔ)上加入了 SSL/TLS 加密層的安全網(wǎng)絡(luò)傳輸協(xié)議,旨在保障數(shù)據(jù)在客戶端與服務(wù)器間傳輸?shù)?strong>機(jī)密性、完整性和身份認(rèn)證。其詳細(xì)通信流程主要包括握手階段和加密傳輸階段:
SSL/TLS 握手階段:
剩余60%內(nèi)容,訂閱專欄后可繼續(xù)查看/也可單篇購買
曾獲多國內(nèi)大廠的 ssp 秋招 offer,且是Java5年的沉淀老兵(不是)。專注后端高頻面試與八股知識(shí)點(diǎn),內(nèi)容系統(tǒng)詳實(shí),覆蓋約 30 萬字面試真題解析、近 400 個(gè)熱點(diǎn)問題(包含大量場景題),60 萬字后端核心知識(shí)(含計(jì)網(wǎng)、操作系統(tǒng)、數(shù)據(jù)庫、性能調(diào)優(yōu)等)。同時(shí)提供簡歷優(yōu)化、HR 問題應(yīng)對(duì)、自我介紹等通用能力??紤]到歷史格式混亂、質(zhì)量較低、也在本地積累了大量資料,故準(zhǔn)備從頭重構(gòu)專欄全部內(nèi)容