百度二面,有點小激動!附面試題
前幾天剛面完百度,這不,沒兩天就收到二面邀請了,還有點小激動呢!來看看這次都問了哪些面試題吧,附答案僅供參考。
ConsurrentHashMap如何計算下標?
ConsurrentHashMap 計算下標和 HashMap 類似,它的主要執(zhí)行流程有以下兩步:
計算 key 哈希值:
- JDK 1.7:key.hashCode()。
- **JDK 1.8+**:((h=key.hashCode()) ^ (h>>>16)) -> 算法更均勻,哈希沖突越少。
計算下標:hash & (table.length-1)。
說說MVCC機制?
MVCC(Multi-Version Concurrency Control)是一種并發(fā)控制機制,用于解決數(shù)據(jù)庫并發(fā)訪問中,數(shù)據(jù)一致性問題。它通過在讀寫操作期間保存多個數(shù)據(jù)版本,以提供并發(fā)事務(wù)間的隔離性,從而避免了傳統(tǒng)的鎖機制所帶來的資源爭用和阻塞問題。
在 MVCC 機制中,每個事務(wù)的讀操作都能看到事務(wù)開始之前的一致性數(shù)據(jù)快照,而不受其他并發(fā)事務(wù)的修改的影響。核心思想是通過創(chuàng)建多個數(shù)據(jù)版本,保持事務(wù)的一致性和隔離性。
MVCC 主要是依靠以下兩部分實現(xiàn)的:
- Undo Log 鏈
- Read View(讀視圖或者叫一致性視圖)
Undo Log 鏈
我們知道 Undo Log 主要是用于數(shù)據(jù)庫中事務(wù)回滾的,但在 MVCC 機制中也發(fā)揮著重要的作用,那什么是 Undo Log 鏈呢?
Undo Log 鏈是指在每個數(shù)據(jù)對象上維護的 Undo Log 記錄鏈表。每張表都會有與之相對應(yīng)的 Undo Log 鏈,用于記錄修改前的數(shù)據(jù)信息(以方便數(shù)據(jù)進行回滾)。
Read View
Read View(讀視圖)用于管理事務(wù)之間數(shù)據(jù)可見性的一種機制。Read View 在特定時刻為事務(wù)創(chuàng)建的一個快照,該快照包含了在該時刻所有未提交事務(wù)的事務(wù)標識符,以及其他一些輔助信息。
在 Read View 中包含了以下 4 個主要的字段:
- m_ids:當前活躍的事務(wù)編號集合。
- min_trx_id:最小活躍事務(wù)編號。
- max_trx_id:預(yù)分配事務(wù)編號,當前最大事務(wù)編號+1。
- creator_trx_id:ReadView 創(chuàng)建者的事務(wù)編號。
RC 級別中,每次快照讀都會生成一個全新的 Read View,而 RR 級別中同一個事務(wù)會復(fù)用一個 Read View。
有了 Read View 和 Undo Log 鏈之后,并發(fā)事務(wù)在查詢時就知道要讀取那些數(shù)據(jù)了。
判斷方法
判斷方法是根據(jù) Read View 中的 4 個重要字段,先去 Undo Log 中最新的數(shù)據(jù)行進行比對,如果滿足下面 Read View 的判斷條件,則返回當前行的數(shù)據(jù),如果不滿足則繼續(xù)查找 Undo Log 的下一行數(shù)據(jù),直到找到滿足的條件的數(shù)據(jù)為止,如果查詢完沒有滿足條件的數(shù)據(jù),則返回 NULL。
判斷規(guī)則
- trx_id==creator_trx_id:先將 Undo Log 最新數(shù)據(jù)行中的 trx_id 和 ReadView 中的 creator_trx_id 進行對比,如果他們兩個值相同,則說明是在同一個事務(wù)中執(zhí)行,那么直接返回當前 Undo Log 的數(shù)據(jù)行即可,如果不相等,則繼續(xù)下面流程。
- trx_id<min_trx_id:如果 trx_id 小于 min_trx_id,則說明在執(zhí)行查詢時,其他事務(wù)已經(jīng)提交此行數(shù)據(jù)了,那么直接返回此行數(shù)據(jù)即可,如果大于等于,則繼續(xù)下面流程。
- trx_id>max_trx_id:如果 trx_id 如果大于等于 max_trx_id,則說明該行數(shù)據(jù)比當前操作執(zhí)行的晚,當前行數(shù)據(jù)不可見,繼續(xù)執(zhí)行后續(xù)流程。
- min_trx_id<=trx_id<max_trx_id:trx_id 在 min_trx_id 和 max_trx_id 之間還分為以下兩種情況:
- trx_id 在 m_ids 中:說明事務(wù)尚未執(zhí)行完,該行數(shù)據(jù)不可被訪問。
- trx_id 未在 m_ids 中:說明事務(wù)已經(jīng)執(zhí)行完,可以返回該行數(shù)據(jù)。
以上判斷規(guī)則從 Undo Log 最新的行數(shù)據(jù),逐行對比,直到找到匹配的數(shù)據(jù),否則查詢完未匹配上,則返回 NULL。
說說讀已提交和可重復(fù)讀各自創(chuàng)建ReadView的時機?
創(chuàng)建 ReadView 時機如下:
- 讀已提交(Read Committed):在讀已提交隔離級別下,MySQL 為每一個讀取操作創(chuàng)建一個新的 ReadView。這意味著每次執(zhí)行 SELECT 查詢時,都會根據(jù)當前活躍事務(wù)的狀態(tài)重新計算可見性視圖。這樣做的結(jié)果是,同一個事務(wù)內(nèi)的連續(xù)兩次查詢可能會看到不同的數(shù)據(jù),因為第二次查詢可能會看到第一次查詢后其他事務(wù)提交的新數(shù)據(jù)。因此,在這個隔離級別下,事務(wù)能看到其他事務(wù)已經(jīng)提交的修改。
- 可重復(fù)讀(Repeatable Read):在可重復(fù)讀隔離級別下,MySQ為整個事務(wù)而不是單個查詢創(chuàng)建一個 ReadView。也就是說,當一個事務(wù)開始時,MySQL 會為該事務(wù)創(chuàng)建一個快照(Snapshot),這個快照包含了數(shù)據(jù)庫在事務(wù)開始時刻的所有數(shù)據(jù)的一個一致性視圖。在整個事務(wù)的生命周期內(nèi),不論執(zhí)行多少次查詢操作,都是基于這個初始創(chuàng)建的 ReadView 來決定數(shù)據(jù)的可見性,確保事務(wù)內(nèi)多次相同的查詢結(jié)果是一致的,即“可重復(fù)讀”。因此,在這個隔離級別下,事務(wù)開始后,不會看到其他事務(wù)后續(xù)提交的修改。
你知道哪些常用的Linux命令?
Linux 常用的命令有以下這些:
- ls:用于列出目錄中的文件和子目錄。
- pwd:顯示當前工作目錄的路徑。
- cd:切換到指定工作目錄。
- mkdir:創(chuàng)建一個新的目錄。
- rmdir:刪除一個空目錄。
- rm:刪除文件或目錄。
- cp:復(fù)制文件或目錄。
- mv:移動或重命名文件或目錄。
- touch:創(chuàng)建空文件或更新文件的時間戳。
- less:分頁顯示文件內(nèi)容。
- tail:顯示文件的開頭或結(jié)尾部分的內(nèi)容(可查看動態(tài)日志)。
- cat:查看文件內(nèi)容或?qū)⒍鄠€文件內(nèi)容合并輸出。
- grep:在文件中搜索指定的文本模式。
- ps:顯示系統(tǒng)中的進程信息。
- kill:終止指定進程。
- ifconfig/ip:查看和配置網(wǎng)絡(luò)接口信息。
- ping:測試網(wǎng)絡(luò)連接。
- wget/curl:從網(wǎng)絡(luò)下載文件。
- chmod:改變文件或目錄的權(quán)限。
如何排查CPU占用比較高的問題?
以 Linux 系統(tǒng)為例,排查 CPU 飆升問題的實現(xiàn)步驟如下:
- 使用 top 命令,查詢占用 CPU 最高的進程 ID。
- 查詢該進程 ID 中,哪個線程占用的 CPU 資源最多。
- 將占用 CPU 資源最多的線程 ID 轉(zhuǎn)換成 16 進制。
- 使用 Java 自帶的工具 jstack 查詢該線程的詳細信息,定位到問題代碼,分析代碼和解決 CPU 飆升的問題。
說說Top命令各個指標的具體含義?
使用 top 命令查詢 cpu 占用最高的進程 ID(PID),如下圖所示:
可以使用 shift+P 快捷鍵進行 CPU 占用率排序(從高到低)。
指標含義:包括進程ID (PID)、用戶 (USER)、優(yōu)先級 (PR)、nice 值 (NI)、虛擬內(nèi)存使用量 (VIRT)、物理內(nèi)存使用量 (RES)、共享內(nèi)存大小 (SHR)、進程狀態(tài) (S)、CPU 使用率 (%CPU)、內(nèi)存使用率 (%MEM)、進程累計 CPU 時間 (TIME+) 和命令名 (COMMAND)。
其中:
- 優(yōu)先級 (PR):優(yōu)先級是進程在內(nèi)核中的實際調(diào)度優(yōu)先級,也稱為動態(tài)優(yōu)先級。它反映了進程被調(diào)度占用 CPU 的實際順序。在 top 命令中,PR 列顯示的是進程的調(diào)度優(yōu)先級,對于實時進程,使用“RT”標記;對于非實時進程(普通用戶進程),其取值范圍是 0 至 39,值越小優(yōu)先級越高。
- nice值 (NI):nice 值是進程的用戶態(tài)優(yōu)先級,也稱為靜態(tài)優(yōu)先級。它是一個從 -20 到 19 的數(shù)值,其中負數(shù)表示較高的優(yōu)先級,正數(shù)表示較低的優(yōu)先級。默認情況下,大多數(shù)進程的 nice 值為0。通過 nice 和 renice 命令,用戶可以調(diào)整進程的 nice 值,從而影響其優(yōu)先級。
Redis為什么快?
Redis 運行比較快的原因主要有以下幾點:
- 純內(nèi)存操作:Redis 將所有數(shù)據(jù)存儲在內(nèi)存中,這意味著對數(shù)據(jù)的讀寫操作直接在內(nèi)存中進行,而內(nèi)存的訪問速度遠遠高于磁盤。這種設(shè)計使得 Redis 能夠以接近硬件極限的速度處理數(shù)據(jù)讀寫。
- 單線程模型:Redis 使用單線程模型來處理客戶端請求。這可能聽起來似乎效率不高,但實際上,這種設(shè)計避免了多線程頻繁切換和過度競爭所帶來的性能開銷。Redis 每個請求的執(zhí)行時間都很短,因此在單線程下,也能夠處理大量的并發(fā)請求。
- I/O多路復(fù)用:Redis 使用了 I/O 多路復(fù)用技術(shù),可以在單個線程中同時監(jiān)聽多個客戶端連接,只有當有網(wǎng)絡(luò)事件發(fā)生時才會進行實際的 I/O 操作。這樣有效地利用了 CPU 資源,減少了無謂的等待和上下文切換。
- 高效數(shù)據(jù)結(jié)構(gòu):Redis 提供了多種高效的數(shù)據(jù)結(jié)構(gòu),如哈希表、有序集合等。這些數(shù)據(jù)結(jié)構(gòu)的實現(xiàn)都經(jīng)過了優(yōu)化,使得 Redis 在處理這些數(shù)據(jù)結(jié)構(gòu)的操作時非常高效。
Redis有哪些持久化方式?
Redis 4.0 之后支持以下 3 種持久化方案:
- RDB(Redis DataBase)持久化:快照方式持久化,將某一個時刻的內(nèi)存數(shù)據(jù),以二進制的方式寫入磁盤。占用空間小,恢復(fù)快,可能存在數(shù)據(jù)丟失。
- AOF(Append Only File)持久化:文件追加持久化,記錄所有非查詢操作命令,并以文本的形式追加到文件中。數(shù)據(jù)通常不易丟失,但占用空間大。
- 混合持久化:RDB + AOF 混合方式的持久化,Redis 4.0 之后新增的方式,混合持久化是結(jié)合了 RDB 和 AOF 的優(yōu)點,在寫入的時候,先把當前的數(shù)據(jù)以 RDB 的形式寫入文件的開頭,再將后續(xù)的操作命令以 AOF 的格式存入文件,這樣既能保證 Redis 重啟時的速度,又能減低數(shù)據(jù)丟失的風(fēng)險。
說說AOF中的寫時復(fù)制技術(shù)?
① AOF 重寫背景
隨著 Redis 運行,AOF 文件會不斷增長,因為每次寫操作都被追加到文件中。為了減小文件體積、提高恢復(fù)速度,Redis 提供了 AOF 重寫功能,它可以創(chuàng)建一個新的、更緊湊的 AOF 文件,僅包含重建當前數(shù)據(jù)集所需的最小命令序列。
② 寫時復(fù)制在 AOF 中的應(yīng)用
- 子進程寫時復(fù)制:Redis 在執(zhí)行 AOF 重寫(bgrewriteaof)時,會 fork 出一個子進程(bgsave 子進程)來負責(zé) AOF 文件的重寫,主進程依然執(zhí)行 Redis 的業(yè)務(wù)命令。
- AOP 重寫遇到寫操作:在 bgsave 子進程運行期間,如果主進程有寫操作(如修改 key-value),主進程會采用寫時復(fù)制機制。具體來說,主進程會把這個新寫或修改的數(shù)據(jù)寫入到一個新的物理地址中,并修改自己的頁表映射。這樣,虛擬頁和物理頁的關(guān)系在子進程中保持不變,而主進程中的數(shù)據(jù)已經(jīng)被更新。
- AOF 重寫緩沖區(qū):為了解決主進程在 AOF 重寫過程中修改數(shù)據(jù)導(dǎo)致的數(shù)據(jù)不一致問題,Redis 設(shè)置了一個 AOF 重寫緩沖區(qū)。在重寫 AOF 期間,當 Redis 執(zhí)行完一個寫命令之后,它會同時將這個寫命令寫入到 AOF 緩沖區(qū)和 AOF 重寫緩沖區(qū)。當 AOF 重寫完成后,Redis 會將 AOF 重寫緩沖區(qū)中的命令追加到新的 AOF 文件中,以確保數(shù)據(jù)的一致性。
手撕算法:三數(shù)之和?
- 題目:https://leetcode.cn/problems/3sum/description/。
- 解題思路:雙指針+數(shù)組變量。
- 解題思路推薦:https://leetcode.cn/problems/3sum/solutions/12307/hua-jie-suan-fa-15-san-shu-zhi-he-by-guanpengchn/。