1. 程式人生 > 其它 >騰訊面經彙總

騰訊面經彙總

序:很久沒寫部落格啦,各項事情塵埃落定,先輸出一波之前找工作時候記錄的一些東西

序:很久沒寫部落格啦,各項事情塵埃落定,先輸出一波之前找工作時候記錄的一些東西

阻塞、非阻塞、同步、非同步 的區別

  • 阻塞
    阻塞呼叫是指呼叫結果返回之前,當前執行緒會被掛起(執行緒進入非可執行狀態,在這個狀態下,cpu 不會給執行緒分配時間片,即執行緒暫停執行)。函式只有在得到結果之後才會返回。對於同步呼叫來說,很多時候當前執行緒還是啟用的,只是從邏輯上當前函式沒有返回而已。 就是呼叫我(函式),我(函式)沒有接收完資料或者沒有得到結果之前,我不會返回。
  • 非阻塞
    指在不能立刻得到結果之前,該函式不會阻塞當前執行緒,而會立刻返回。就是呼叫我(函式),我(函式)立即返回,通過 select 通知呼叫者
  • 同步 IO

同步 IO 進行 IO 操作時會阻塞程序。IO 操作分兩個階段(資料準備和拷貝資料),阻塞 IO 是這兩步都阻塞,非阻塞 IO 是資料準備階段,不會阻塞程序。資料準備完成後,程序主動在此呼叫 recvfrom 函式將資料從核心拷貝到使用者記憶體

  • 非同步IO

相當於使用者程序將 IO 操作整個交給核心去完成,核心會返回事件完成通知。在此階段,使用者程序不需要檢查 IO 操作狀態,也不需要主動拷貝資料,使用者程序完全沒有阻塞

資料庫 ACID 一致性和原子性的區別

ACID特性,原子性、一致性、隔離性、永續性

  • 原子性
    是指事務是一個不可再分割的工作單位,事務中的操作要麼都發生,要麼都不發生。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣
  • 一致性

一致性是指事務使得系統從一個一致的狀態轉換到另一個一致狀態。這是說資料庫事務不能破壞關係資料的完整性以及業務邏輯上的一致性

  • 隔離性

多個事務併發訪問時,事務之間是隔離的,一個事務不應該影響其它事務執行效果。這指的是在併發環境中,當不同的事務同時操縱相同的資料時,每個事務都有各自的完整資料空間。由併發事務所做的修改必須與任何其他併發事務所做的修改隔離

  • 永續性

永續性,意味著在事務完成以後,該事務所對資料庫所作的更改便持久的儲存在資料庫之中,並不會被回滾。即使出現了任何事故比如斷電等,事務一旦提交,則持久化儲存在資料庫中

Mysql如何保證事務的ACID特性

詳細1


詳細2

  • 原子性
    undolog記錄反向操作,用於回滾:
    對於每一個insert,undolog記錄一個delete
    對於每一個delete,undolog記錄一個insert
    對於每一個update,undolog記錄一個相反的update

  • 一致性
    redolog+undolog ,保證所有操作同時提交和回滾。
    通過加鎖保證同一行資料更新序列,避擴音交丟失。
    通過MVCC保證事務內讀一致性。
    加鎖參考

  • 隔離性
    通過隔離模式實現不同級別下的隔離性。
    通過鎖和MVCC實現隔離模式下的讀寫並行。
    [四種隔離模式]https://success.blog.csdn.net/article/details/105027900
    [加鎖原理]https://success.blog.csdn.net/article/details/103154299

  • 永續性
    通過redolog實現永續性。
    sync_binlog和innodb_flush_log_at_trx_commi設定為1,也就是大家常說的雙1策略,保證宕機資料不丟失。
    宕機重啟時通過對比redolog頁和資料頁的LSN(Log Sequence Number)進行恢復

常見排序演算法,說下快排過程,時間複雜度

有N個節點的滿二叉樹的高度

1+logN

單元點最短路的方法,時間複雜度

如何實現關鍵字輸入提示,使用字典樹,複雜度多少,有沒有其他方案,答雜湊,如果是中文呢,分詞後建立字典樹

紅黑樹的結構,查詢效能

死鎖是怎麼產生的

執行緒和程序的區別

程序的通訊方式

CPU的執行方式

程式碼中遇到程序阻塞,程序僵死,記憶體洩漏等情況怎麼排查。通過ps查詢狀態,分析dump檔案等方式排查

Linux瞭解麼,檢視程序狀態ps,檢視cpu狀態 top。檢視佔用埠的程序號netstat grep

10g檔案,只有2g記憶體,怎麼查詢檔案中指定的字串出現位置。MapReduce分割檔案處理,他說可以用cat | grep 管道處理

Linux的swap瞭解麼

MySQL的儲存引擎,有什麼區別

100w個數,怎麼找到前1000個最大的,堆排序,怎麼構造,怎麼調整,時間複雜度

一個矩陣,從左上角到右下角,每個位置有一個權值。可以上下左右走,到達右下角的路徑權值最小怎麼走

四輛小車,每輛車加滿油可以走一公里,問怎麼能讓一輛小車走最遠

MySQL的索引,B+樹性質

Linux的cpu 100怎麼排查,top jstack,日誌,gui工具

Linux大檔案怎麼查某一行的內容

十億個數的集合和10w個數的集合,如何求它們的交集 (集合的數字不重複)

十億和數找到前100個最大的,堆排序

TCP和UDP的區別,具體使用場景呢

TCP四次揮手講一下過程

對於socket程式設計,accept方法是幹什麼的,在三次握手中屬於第幾次

對於單例模式,有什麼使用場景了,講了全域性id生成器,他問我分散式id生成器怎麼實現

除了單例模式,知道介面卡模式怎麼實現麼,有什麼用

proc檔案系統

TCP和UDP的核心區別在哪,講了滑動視窗保證可靠有序傳輸,UDP不可靠。TCP需要連線而UDP不需要

TCP的四次揮手,time wait狀態有什麼意義

map 和 set 底層是用什麼資料結構實現?用 set 實現 map?(set<pair<key, value>>)

遞迴呼叫函式佔用了什麼空間

棧空間
實際上堆空間也有可能佔用

函式棧空間多大

函式傳參時int &會減少佔用的空間嗎,有好處嗎

基礎型別(不會)
感覺從記憶體上講沒好處,看需求把,是否需要改那個數。

引用佔不佔記憶體

1,引用實際是通過指標實現的。
2,引用是一個常量指標。
3,引用在記憶體中佔4個位元組。
4,在對引用定義時,需要對這個常量指標初始化。
5,因為在在表示式中,使用引用實際上就像使用變數本身一樣,所以直接用sizeof是得不到引用本身的大小的。

HTTP協議

簡單介紹,協議細節和包含了什麼

  • 請求報文
    請求行
    請求方法 URL 版本協議
    請求頭部
    請求資料

  • 響應報文

狀態行
版本協議 狀態碼 狀態碼描述
響應頭部
connection
響應正文

http常見狀態碼

http常見請求方法 (get,post, push)

STL常用的容器有哪些

講一講容器的內部實現,擴容縮容,儲存

vector記憶體結構,擴容縮容
string擴容縮容,連續的
string是連續的
優先順序佇列,以vector為儲存結構的堆

面向物件思想的特點

  • 封裝多型繼承

哪些語言特性體現面向物件

  • 多型

多型通過什麼實現的

多型和過載區別

  • 多型

通過虛擬函式表實現
一個介面,根據呼叫的物件不同產生不同的結果

  • 過載

通過引數列表的不同實現根據輸入引數型別不同選擇對應的函式

  • 重寫和過載的區別

過載是相同函式名,但函式的引數不能完全相同。重寫是指派生類改寫基類虛擬函式的函式體

虛擬函式繼承機制與內部實現

類的大小

int成員+普通函式+虛擬函式 類大小是多少 sizeof 為 8

位元組對齊的理解

為什麼要位元組對齊
怎麼位元組對齊
不對齊會怎麼樣
對齊與不對齊的訪問記憶體區別

位元組序

大端小端的區別

小端(先存小的) 數值高位 放在記憶體低位
網路序(預設大端序)
位元組序怎麼轉換
int的怎麼實現

string有位元組序的說法嗎

沒有,位元組序是指byte的排序,string裡面都是char,一個char就是1位元組
只要出現索引的地方,一定是索引越大地址越大

四次揮手

2msl
半連線狀態

記憶體碎片分為哪幾種

內碎片外碎片

有序陣列中找是否有兩個數和為N

Linux命令的使用,檢視程序、檢視資源佔用、檢視某一個程序的資源佔用

程序、執行緒及協程及使用場景

多執行緒哪些東西是共享的

靜態變數共享嗎
虛擬記憶體地址的組織

tcp擁塞控制

慢啟動和快重傳的觸發條件
怎麼區分是網路的原因(連發3次ack說明丟包)

udp改可靠udp怎麼做

對著tcp的可靠傳輸方法改
加ack
加序號
擁塞控制

stl標準庫六大容器

vector記憶體
map的實現方式

共享記憶體

程序重啟如何讀到之前的東西(比如本來有個map,重啟後繼續讀到)
共享記憶體可以實現的

設計一個演算法

紅包演算法,3個人搶5塊的紅包,每個人不能超過2塊

先每人分2塊,再加權取隨機數按比例加權扣一元

epoll兩種模式的區別

  • LT 模式
    當 epoll_wait 檢測到描述符事件發生並將此事件通知應用程式,應用程式可以不立即處理該事件。下次呼叫 epoll_wait 時,會再次響應應用程式並通知此事件。
    一個 socket 第一次有資料,LT 模式下檢測到 socket 處於活躍狀態,接下來再有資料過來,接著觸發。或者說可以根據需要收取部分資料,只要 socket 上資料不收取完,epoll_wait 會接著返回這個可讀 socket。程式設計上如果需要資料包一部分一部分的處理,可以使用 LT 模式
  • ET 模式
    當 epoll_wait 檢測到描述符事件發生並將此事件通知應用程式,應用程式必須立即處理該事件。如果不處理,下次呼叫 epoll_wait 時,不會再次響應應用程式並通知此事件。第一次有資料會觸發 socket,第二次再有資料不會觸發,必須等第一次的資料完全讀完或寫完。必須把當前 socket 資料全部收完,才能接受下一次的可讀 socket程式設計上 ET 模式必須是一個迴圈,收取資料到 recv 返回-1,errno=EAGAIN
  • epoll 的 ET 模式為什麼一定要使用非阻塞 IO
    ET 模式下每次 write 或 read 需要迴圈 write 或 read 直到返回 EAGAIN 錯誤。以讀操作為例,這是因為 ET 模式只在 socket 描述符狀態發生變化時才觸發事件,如果不一次把 socket 核心緩衝區的資料讀完,會導致 socket 核心緩衝區中即使還有一部分資料,該 socket 的可讀事件也不會被觸發。根據上面的討論,若 ET 模式下使用阻塞 IO,則程式一定會阻塞在最後一次 write 或 read 操作,因此說 ET 模式下一定要使用非阻塞 IO

google.com遮蔽的原理是什麼,隧道怎麼實現的

隧道上網原理

程序排程

程序排程:記錄系統中的所有程序的狀態、優先順序數和資源的需求情況確定排程演算法,決定將 CPU 分配給哪個程序多少時間分配處理機給程序,進行 CPU 現場的保護和移交

程序排程演算法:先來先服務排程演算法、短作業優先排程演算法、非搶佔式優先順序排程演算法、搶佔式優先順序排程演算法、高響應比優先排程演算法、時間片輪轉法排程演算法

頁面置換演算法

詳細

  • 先進先出頁面置換演算法(FIFO)及其改進

這種演算法的思想和佇列是一樣的,OS維護一個當前在記憶體中的所有頁面的連結串列,最新進入的頁面在尾部,最久的在頭部,每當發生缺頁中斷,就替換掉表頭的頁面並且把新調入的頁面加入到連結串列末尾。
一種合理的改進,稱為第二次機會演算法。即給每個頁面增加一個R位,每次先從連結串列頭開始查詢,如果R置位,清除R位並且把該頁面節點放到連結串列結尾;如果R是0,那麼就是又老又沒用到,替換掉

  • 最佳頁面置換演算法(OPT)

最理想的狀態下,我們給頁面做個標記,挑選一個最遠才會被再次用到的頁面。當然,這樣的演算法不可能實現,因為不確定一個頁面在何時會被用到。

  • 最近最久未使用(NRU)

系統為每一個頁面設定兩個標誌位:當頁面被訪問時設定R位,當頁面(修改)被寫入時設定M位。當發生缺頁中斷時,OS檢查所有的頁面,並根據它們當前的R和M位的值,分為四類:

(1)!R&!M(2)!R&M(3)R&!M(4)R&M

編號越小的類,越被優先換出。即在最近的一個時鐘滴答內,淘汰一個沒有被訪問但是已經被修改的頁面,比淘汰一個被頻繁使用但是“clean”的頁面要好。

  • 最近最少使用置換演算法(LRU)

最近最少使用,簡單來說就是將資料塊中,每次使用過的資料放在資料塊的最前端,然後將存在的時間最長的,也就是資料塊的末端的資料剔除掉這就是 LRU 演算法

作業系統的CPU如何排程

同進程排程

介紹下epoll,基本使用,lt/et,什麼時候檔案描述符活躍,活躍後核心如何處理。和select有什麼區別

介紹下tcp/ip四層協議

TCP/IP協議並不完全符合OSI 標準定製的七層參考模型,它採取了四層的層級結構

網路介面層:接收IP資料包並進行傳輸,從網路上接收物理幀,抽取IP 轉交給下一層,對實際網路的網路媒體的管理,定義如何使用物理網路 ,如乙太網。
網際層IP: 負責提供基本的資料封包傳送功能,讓每一塊資料包都能打到目的主機,但不檢查是否被正確接收,主要表現為IP協議
傳輸層:在此層中,它提供了節點的資料傳送,應用程式之間的通訊服務,主要是資料格式化,資料確認和丟失重傳等。主要協議包括TCP和UDP
應用層:應用程式間溝通單層,如全球資訊網(WWW)、簡單電子郵件傳輸(SMTP)、檔案傳輸協議(FTP)、網路遠端訪問協議(Telnet)等

ping通過什麼協議,在哪一層

Ping 是一個應用程式,是基於 ICMP 協議實現的。ICMP 協議是位於 IP 層的一個協議。它是 TCP/IP 協議族的一個子協議,用於在 IP 主機、路由器之間傳遞控制訊息。
Ping 命令的基本原理?答:ICMP,傳送主機發送 echo 請求,接受主機回覆 echo 報文
Ping 的如果是域名,還要先經過 DNS 解析

介紹三次握手四次揮手,伺服器能否不wait直接斷開

  • time_wait 狀態如何避免
    首先伺服器可以設定 SO_REUSEADDR 套接字選項來通知核心,如果埠忙,但 TCP 連線位於 TIME_WAIT 狀態時可以重用埠。在一個非常有用的場景就是,如果你的伺服器程式停止後想立即重啟,而新的套接字依舊希望使用同一埠,此時 SO_REUSEADDR 選項就可以避免TIME_WAIT 狀態

心跳包通過什麼實現的,如何調節引數

詳細

因為要考慮到一個伺服器通常會連線多個客戶端,因此由使用者在應用層自己實現心跳包,程式碼較多 且稍顯複雜,而利用TCP/IP協議層為內建的KeepAlive功能來實現心跳功能則簡單得多。 不論是服務端還是客戶端,一方開啟KeepAlive功能後,就會自動在規定時間內向對方傳送心跳包, 而另一方在收到心跳包後就會自動回覆,以告訴對方我仍然線上。 因為開啟KeepAlive功能需要消耗額外的寬頻和流量,所以TCP協議層預設並不開啟KeepAlive功 能,儘管這微不足道,但在按流量計費的環境下增加了費用,另一方面,KeepAlive設定不合理時可能會 因為短暫的網路波動而斷開健康的TCP連線。並且,預設的KeepAlive超時需要7,200,000 MilliSeconds, 即2小時,探測次數為5次。對於很多服務端應用程式來說,2小時的空閒時間太長。因此,我們需要手工開啟KeepAlive功能並設定合理的 KeepAlive引數

心跳包一般來說都是在邏輯層傳送空的echo包來實現的。下一個定時器,在一定時間間隔下發送一個空包給客戶端,然後客戶端反饋一個同樣的空包回來,伺服器如果在一定時間內收不到客戶端傳送過來的反饋包,那就只有認定說掉線了

malloc如何實現的,通過哪個系統呼叫開闢記憶體,如何對映到實體記憶體

  1. 當分配記憶體小於 128K 時,brk 是將資料段(.data)的最高地址指標_edata 往高地址推
  2. 當分配記憶體大於 128K 時,mmap 是在程序的虛擬地址空間中(堆和棧中間,稱為檔案對映區域的地方)找一塊空閒的虛擬記憶體

這兩種方式分配的都是虛擬記憶體,沒有分配實體記憶體。在第一次訪問已分配的虛擬地址空間的時候,發生缺頁中斷,作業系統負責分配實體記憶體,然後建立虛擬記憶體和實體記憶體之間的對映關係

mysql,acid,mvcc,版本號加在哪,跨表怎麼辦

介紹下B+樹,資料存在哪,資料具體存的哪些?

宕機了資料怎麼恢復?有幾種log形式?

詳細
永續性是指一個事務一旦被提交了,那麼對資料庫中的資料的改變就是永久性的,即便是在資料庫系統遇到故障的情況下也不會丟失提交事務的操作。
MySQL採用了一種叫WAL(Write Ahead Logging)提前寫日誌的技術。意思就是說,發生了資料修改操作先寫日誌記錄下來,等不忙的時候再持久化到磁碟。這裡提到的日誌就是redo log。
redo log稱為重做日誌,當有一條記錄需要修改的時候,InnoDB引擎會先把這條記錄寫到redo log裡面。redo log是物理格式日誌,它記錄的是對於每個頁的修改。
redo log是由兩部分組成的:一是記憶體中的重做日誌緩衝(redo log buffer);二是用來持久化的重做日誌檔案(redo log file)。為了消耗不必要的IO操作,事務再執行過程中產生的redo log首先會redo log buffer中,之後再統一存入redo log file刷盤進行持久化,這個動作稱為fsync
binlog記錄了mysql執行更改了所有操作,但不包含select和show這類本對資料本身沒有更改的操作。但是不是說對資料本身沒有修改就不會記錄binlog日誌。

  • binlog是mysql自帶的,他會記錄所有儲存引擎的日誌檔案。而redo log是InnoDB特有的,他只記錄該儲存引擎產生的日誌檔案
  • binlog是邏輯日誌,記錄這個語句具體操作了什麼內容。Redo log是物理日誌,記錄的是每個頁的更改情況
  • redo log是迴圈寫,只有那麼大的空間。binlog採用追加寫入,當一個binlog檔案寫到一定大小後會切換到下一個檔案

執行緒池如何實現的?

在應用程式啟動之後,就馬上建立一定數量的執行緒,放入空閒的佇列中。這些執行緒都是處於阻塞狀態,這些執行緒只佔一點記憶體,不佔用 CPU。當任務到來後,執行緒池將選擇一個空閒的執行緒,將任務傳入此執行緒中執行。當所有的執行緒都處在處理任務的時候,執行緒池將自動建立一定的數量的新執行緒,用於處理更多的任務。執行任務完成之後執行緒並不退出,而是繼續線上程池中等待下一次任務。當大部分執行緒處於阻塞狀態時,執行緒池將自動銷燬一部分的執行緒,回收系統資源。

epoll想改成多執行緒的該怎麼實現?

單獨單寫設計阻塞佇列,不用鎖怎麼實現?

使用一個全域性變數進行標誌

std:move介紹下,什麼是左值右值,傳遞個物件會什麼樣?連續執行兩次move會怎麼樣

取地址的、有名字的就是左值。左值的生存期長,可以作為賦值的物件。
右值指臨時物件,只在當前語句有效,右值又可以細分為純右值、將亡值。純右值指的是臨時變數和不跟物件關聯的字面量值;將亡值則是 C++11 新增的跟右值引用相關的表示式,這樣表示式通常是將要被移動的物件(移為他用)。如std::move 的返回值。將亡值可以理解為通過“盜取”其他變數記憶體空間的方式獲取到的值

std::move()將左值強制轉換為右值。

智慧指標介紹一下,unique如何防止多次釋放

shared_ptr、unique_ptr、weak_ptr。shared_ptr多個指標指向相同的物件。shared_ptr 使用引用計數,每一個 shared_ptr 的拷貝都指向相同的記憶體。每使用他一次,內部的引用計數加 1,每析構一次,內部的引用計數減 1,減為 0 時,自動刪除所指向的堆記憶體。shared_ptr 內部的引用計數是執行緒安全的,但是物件的讀取需要加鎖。
unique_ptr“唯一”擁有其所指物件,同一時刻只能有一個 unique_ptr 指向給定物件(通過禁用拷貝建構函式和賦值運算子、只有移動語義來實現)。
物件互相引用
當父類物件包含子類物件且子類物件包含父類物件,然二者又互相賦值的時候,將會發生互相引用的情況,資源將得不到釋放。
弱指標 weak_ptr 不控制物件的生命期,指向一個shared_ptr 管理的物件,但是引用計數不在進行加 1。
它只可以從一個 shared_ptr 或另一個 weak_ptr 物件構造。,然後賦值給它的構造和析構不會引起引用記數的增加或減少.防止兩個 shares_ptr 互相引用使得釋放時引用計數為 1,無法得到釋放。不能通過 weak_ptr 直接訪問物件的方法,需要先將 weak_ptr 轉為shared_ptr,才可以。某個 weak_ptr 呼叫 lock()轉變為 shared_ptr。也可以 weak..直接賦值給 shared…

map和unordered_map的區別

  1. unordered_map 和 map 類似,都是儲存的 key-value 的值,可以通過 key 快速索引到 value。不同的是 unordered_map 不會根據 key 的大小進行排序
  2. unordered_map 的底層實現是 hash_table,map 中的元素是按照紅黑樹儲存
  3. 如果需要內部元素自動排序,使用 map,不需要排序使用 unordered_map

介紹下deque

詳細

雙端佇列(deque)是一種支援向兩端高效地插入資料、支援隨機訪問的容器。和 vector 容器採用連續的線性空間不同,deque 容器儲存資料的空間是由一段一段等長的連續空間構成,各段空間之間並不一定是連續的,可以位於在記憶體的不同區域。為了管理這些連續空間,deque 容器用陣列(陣列名假設為 map)儲存著各個連續空間的首地址。也就是說,map 陣列中儲存的都是指標,指向那些真正用來儲存資料的各個連續空間

當 deque 容器需要在頭部或尾部增加儲存空間時,它會申請一段新的連續空間,同時在 map 陣列的開頭或結尾新增指向該空間的指標,由此該空間就串接到了 deque 容器的頭部或尾部。如果 map 陣列滿了怎麼辦?很簡單,再申請一塊更大的連續空間供 map 陣列使用,將原有資料(很多指標)拷貝到新的 map 陣列中,然後釋放舊的空間。

夥伴系統

Linux 核心中引入了夥伴系統演算法(buddy system)。把所有的空閒頁框分組為 11 個塊連結串列,每個塊連結串列分別包含大小為 1,2,4,8,16,32,64,128,256,512 和 1024 個連續頁框的頁框塊。最大可以申請 1024 個連續頁框,對應 4MB 大小的連續記憶體。每個頁框塊的第一個頁框的實體地址是該塊大小的整數倍。

假設要申請一個 256 個頁框的塊,先從 256 個頁框的連結串列中查詢空閒塊,如果沒有,就去 512 個頁框的連結串列中找,找到了則將頁框塊分為 2 個 256 個頁框的塊,一個分配給應用,另外一個移到 256 個頁框的連結串列中。如果 512 個頁框的連結串列中仍沒有空閒塊,繼續向 1024 個頁框的連結串列查詢,如果仍然沒有,則返回錯誤。頁框塊在釋放時,會主動將兩個連續的頁框塊合併為一個較大的頁框塊。

linux查詢程序的CPU佔用,開啟的埠號,TCP連線數量,記憶體使用情況

top, ps, lsof, netstat, df -h

檢視程式對應的程序號: ps -ef | grep 程序名字
檢視程序號所佔用的埠號: netstat -nltp | grep 程序號
檢視埠號所使用的程序號: lsof -i:埠號

多執行緒是如何通訊的

過載和重寫

什麼時候設定成虛擬函式

https加密過程

指標和引用的區別

new和malloc區別

智慧指標(auto_ptr,shared_ptr區別)

執行緒同步,程序同步方法

說一下四次揮手,為什麼要有time-wait

分配記憶體的時候作業系統做了什麼事情

epoll和select的區別

epoll的原始碼讀過嗎?描述一下其中的資料結構

epoll發展於介紹
epoll中就緒列表引用著就緒的socket,所以它應能夠快速的插入資料。程式可能隨時呼叫epoll_ctl新增監視socket,也可能隨時刪除。當刪除時,若該socket已經存放在就緒列表中,它也應該被移除。所以就緒列表應是一種能夠快速插入和刪除的資料結構。雙向連結串列就是這樣一種資料結構,epoll使用雙向連結串列來實現就緒佇列。
既然epoll將“維護監視佇列”和“程序阻塞”分離,也意味著需要有個資料結構來儲存監視的socket。至少要方便的新增和移除,還要便於搜尋,以避免重複新增。紅黑樹是一種自平衡二叉查詢樹,搜尋、插入和刪除時間複雜度都是O(log(N)),效率較好。epoll使用了紅黑樹作為索引結構

如果epoll_wait函式中定時了3秒,有事情和沒事情返回介面會發生什麼?

學校區域網到公共網時路由器是怎麼變化的

一個阻塞的io程序是如何被排程的?(作業系統會一直等待嗎?還是會定時去拉一把?

IO 準備好 / Sleep 時間到 前不會排程該執行緒

tcpdump抓包

IO複用(select/poll/epoll)區別

非關係型資料庫和關係型資料庫區別

分散式事務

Git

git,新建一個分支、比較兩個分支差異、合併分支

kill -9 與 kill -5的差別

linux:找一個資料夾下帶某一個關鍵字的檔案

TCP 和 UDP 區別?

TCP 是怎麼保障可靠性的

三次握手四次揮手過程

訊號量與訊號的區別和應用場景?

什麼是中斷?什麼是陷入?

中斷是指計算機執行過程中,出現某些意外情況需主機干預時,機器能自動停止正在執行的程式並轉入處理新情況的程式,處理完畢後又返回原被暫停的程式繼續執行.

  1. 硬體中斷

  2. 軟體中斷
    是一條CPU指令,用以自陷一箇中斷。由於軟中斷指令通常要執行一個切換CPU至核心態(Kernel Mode/Ring 0)的子例程,它常被用作實現系統呼叫(System call)

  • 中斷處理流程
    1、裝置發出中斷訊號
    2、硬體通過 PSW 和 PC 儲存現場,儲存在堆疊中
    3、根據中斷碼查詢中斷向量表
    4、把中斷處理程式入口地址推送給暫存器
    5、執行中斷處理程式
    6、回到之前斷點繼續執行

位元組碼層面如何體現多型

快取穿透,快取雪崩,快取擊穿,快取過期策略

  • 快取穿透

快取穿透是指快取和資料庫中都沒有的資料,而使用者不斷髮起請求,如發起為id為“-1”的資料或id為特別大且不存在的資料。這時的使用者很可能是攻擊者,攻擊會導致資料庫壓力過大。
解決方案:

  1. 介面層增加校驗,如使用者鑑權校驗,id做基礎校驗,id<=0的直接攔截;
    從快取取不到的資料,在資料庫中也沒有取到,這時也可以將key-value對寫為key-null,快取有效時間可以設定短點,如30秒(設定太長會導致正常情況也沒法使用)。這樣可以防止攻擊使用者反覆用同一個id暴力攻擊
  • 快取擊穿

快取擊穿是指快取中沒有但資料庫中有的資料(一般是快取時間到期),這時由於併發使用者特別多,同時讀快取沒讀到資料,又同時去資料庫去取資料,引起資料庫壓力瞬間增大,造成過大壓力
解決方案:
設定熱點資料永遠不過期
加互斥鎖降低從資料庫中讀取資料頻率

  • 快取雪崩

快取雪崩是指快取中資料大批量到過期時間,而查詢資料量巨大,引起資料庫壓力過大甚至down機。和快取擊穿不同的是,快取擊穿指併發查同一條資料,快取雪崩是不同資料都過期了,很多資料都查不到從而查資料庫
解決方案:

  1. 快取資料的過期時間設定隨機,防止同一時間大量資料過期現象發生。
  2. 如果快取資料庫是分散式部署,將熱點資料均勻分佈在不同搞得快取資料庫中。
  3. 設定熱點資料永遠不過期。

快取與資料庫的一致性

對記憶體洩漏的理解,以及在專案中如何排查解決

記憶體洩漏是指由於疏忽或錯誤造成了程式未能釋放掉不再使用的記憶體的情況。記憶體洩漏並非指記憶體在物理上消失,而是應用程式分配某段記憶體後,由於設計錯誤,失去了對該段記憶體的控制。

檢查方法:在 main 函式最後面一行,加上一句_CrtDumpMemoryLeaks()。除錯程式,自然關閉程式讓其退出,檢視輸出:
輸出這樣的格式{453}normal block at 0x02432CA8,868 bytes long 被{}包圍的 453 就是我們需要的記憶體洩漏定位值,868 bytes long 就是說這個地方有 868 位元記憶體沒有釋放。
定位程式碼位置
在 main 函式第一行加上_CrtSetBreakAlloc(453);意思就是在申請 453這塊記憶體的位置中斷。然後除錯程式,程式中斷了,檢視呼叫堆疊。加上標頭檔案#include <crtdbg.h>

大資料量分庫分表方式,作用

資料庫災備方案

vector如何實現執行緒安全

自旋鎖

輸入url後發生了什麼(詳細介紹整個過程)

純虛擬函式與虛擬函式的區別

MySQL索引、聯合索引、聯合索引應用特點

explain sql語句(我回答的是possible_keys、key、type等)

TCP三次握手、DNS負載均衡、長短連線

設計模型(口述下工廠、單例的寫法)

查一個檔案中含有某個關鍵字的行數

mysql中的檢視

改變一個檢視其它事務能看到嗎

mysql為什麼用b+樹

執行緒如何排程

多路複用

訊息佇列

1.什麼是訊息佇列
2.如何保證訊息不丟失
3.如何保證訊息不重複

如何保證執行緒安全

B+樹索引說說

MySQL半同步複製過程

詳細

  • 非同步複製(Asynchronous replication)
    MySQL預設的複製即是非同步的,主庫在執行完客戶端提交的事務後會立即將結果返給給客戶端,並不關心從庫是否已經接收並處理,這樣就會有一個問題,主如果crash掉了,此時主上已經提交的事務可能並沒有傳到從上,如果此時,強行將從提升為主,可能導致新主上的資料不完整。
  • 全同步複製(Fully synchronous replication)
    指當主庫執行完一個事務,所有的從庫都執行了該事務才返回給客戶端。因為需要等待所有從庫執行完該事務才能返回,所以全同步複製的效能必然會收到嚴重的影響。
  • 半同步複製(Semisynchronous replication)
    介於非同步複製和全同步複製之間,主庫在執行完客戶端提交的事務後不是立刻返回給客戶端,而是等待至少一個從庫接收到並寫到relay log中才返回給客戶端。相對於非同步複製,半同步複製提高了資料的安全性,同時它也造成了一定程度的延遲,這個延遲最少是一個TCP/IP往返的時間。所以,半同步複製最好在低延時的網路中使用。

HTTPS握手過程(是SSL的握手)

HTTPs 是以安全為目標的 HTTP 通道,簡單講是 HTTP 的安全版,即HTTP 下加入 SSL 層,HTTPS 的安全基礎是 SSL,因此加密的詳細內容就需要 SSL
HTTPs的握手過程包含五步

  1. 瀏覽器請求連線
  2. 伺服器返回證書:證書裡面包含了網站地址,加密公鑰,以及證書的頒發機構等資訊,伺服器採用非對稱加密演算法(RSA)生成兩個祕鑰,私鑰自己保留
  3. 瀏覽器收到證書後作以下工作:
    3.1 驗證證書的合法性
    3.2 生成隨機(對稱)密碼,取出證書中提供的公鑰對隨機密碼加密;瀏覽器即客戶端使用非對稱加密來加密對稱加密規則,對稱加密用於加密後續傳輸的資訊
    3.3 將之前生成的加密隨機密碼等資訊傳送給網站
  4. 伺服器收到訊息後作以下的操作
    4.1 使用自己的私鑰解密瀏覽器用公鑰加密後的訊息,並驗證 HASH 是否與瀏覽器發來的一致;獲得瀏覽器發過來的對稱祕鑰
    4.2 使用加密的隨機對稱密碼加密一段訊息,傳送給瀏覽器
  5. 瀏覽器解密並計算握手訊息的 HASH:如果與服務端發來的 HASH 一致,此時握手過程結束,之後進行通訊

c++ 11特性知道那些

tcp的幾個欄位ack,psh,rst之類什麼作用

SYN表示建立連線,
FIN表示關閉連線,
ACK表示響應,
PSH表示有 DATA資料傳輸,
RST表示連線重置

c++吐核,原因,怎麼排查,爆棧怎麼查

分散式鎖怎麼實現的

c++的智慧指標

虛擬地址空間

大端小端問題,怎樣通過網路傳送(考察網路序主機序轉換的問題)

大端模式:是指資料的高位元組儲存在記憶體的低地址中,而資料的低位元組儲存在記憶體的高地址端。
小端模式,是指資料的高位元組儲存在記憶體的高地址中,低位位元組儲存在在記憶體的低地址端

網路位元組序類似於大端模式,因為UDP/TCP/IP協議規定:把接收到的第一個位元組當作高位位元組看待,類似於大端模式低地址存放高位元組的儲存方式,實際上也確實像,因為無論是收還是發,都是從低位元組開始的,那麼收到的第一個位元組理應放到低地址。

場景題

#### 朋友之間的點對點關係用圖維護,怎麼判斷兩人是否是朋友,並查集,時間複雜度,過程

程式現在CPU突然爆了,如何定位

給定某天 200 萬用戶登入日誌(使用者,登入登出時間),求某一時間點使用者線上人數

兩個小頂堆的優先佇列,O(n)即可解決

如何從幾億個數中找到唯一出現的一個數(記憶體無法一次讀取全部資料)

1G記憶體對1個T的資料進行排序

演算法

最長迴文子串

每K節點反轉連結串列

class Solution {
public:
    // 翻轉一個子連結串列,並且返回新的頭與尾
    pair<ListNode*, ListNode*> myReverse(ListNode* head, ListNode* tail) {
        ListNode* prev = tail->next;
        ListNode* p = head;
        while (prev != tail) {
            ListNode* nex = p->next;
            p->next = prev;
            prev = p;
            p = nex;
        }
        return {tail, head};
    }

    ListNode* reverseKGroup(ListNode* head, int k) {
        ListNode* hair = new ListNode(0);
        hair->next = head;
        ListNode* pre = hair;

        while (head) {
            ListNode* tail = pre;
            // 檢視剩餘部分長度是否大於等於 k
            for (int i = 0; i < k; ++i) {
                tail = tail->next;
                if (!tail) {
                    return hair->next;
                }
            }
            ListNode* nex = tail->next;
            pair<ListNode*, ListNode*> result = myReverse(head, tail);
            head = result.first;
            tail = result.second;
            // 把子連結串列重新接回原連結串列
            pre->next = head;
            tail->next = nex;
            pre = tail;
            head = tail->next;
        }

        return hair->next;
    }
};
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        if (k <= 1) return head;
        vector<ListNode* > vec;
        while (head) {
            vec.emplace_back(head);
            head = head->next;
        }
        if (vec.size() < k) return head;
        ListNode* newHead = vec[k - 1];
        for (int i = 1; i < k; ++i) {
            vec[i]->next = vec[i - 1];
        }
        int last_index = 0;
        if (vec.size() == k) {
            vec[0]->next = nullptr;
            return vec[k - 1];
        }
        int j = k, tmp;

        while (j < vec.size()) {
            tmp = last_index + k - 1;
            if (tmp + 1 < vec.size()) vec[tmp + 1]->next = nullptr;
            if (tmp + k >= vec.size()) {
                if(tmp+2 < vec.size()) vec[tmp+1]->next = vec[tmp+2];
                vec[last_index]->next = vec[tmp + 1];
                return newHead;
            }
            j = tmp + 2;

            for (; j < vec.size() && j - tmp <= k; ++j) {
                vec[j]->next = vec[j - 1];
            }
            vec[last_index]->next = vec[j - 1];
            last_index = tmp + 1;
        }

        return newHead;
    }
};

兩個字串的最長公共子串

範圍1到1000的數,原本有1000個,互不重複,現多出來1個重複的數,怎麼找到他,統計次數,太慢,求和相減

N個糖果,每次只能取1個到6個,不能不取,你先取,請問是否有必勝策略,怎麼取

找出規律不能為7的倍數,每次取到只剩7的倍數個糖果即可

八皇后的程式碼填空題

二分查詢

海量資料topK的問題

合併有序連結串列

對稱的數字

排序陣列二分查詢

左上角到右下角的路有幾條?(中間存在障礙)

https://leetcode-cn.com/problems/unique-paths-ii/

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        vector<vector<int>> vvi(obstacleGrid.size(), vector<int>(obstacleGrid[0].size(), 0));
        if(obstacleGrid[0][0]) return 0;
        vvi[0][0] = 1;
        for(int j =1;j < obstacleGrid[0].size();j++){
            if(obstacleGrid[0][j]) break;
            vvi[0][j] = 1;
        }
        for(int i = 1;i < obstacleGrid.size();i++){
            if(obstacleGrid[i][0]) break;
            vvi[i][0] = 1;
        }
        

        for(int i = 1;i < obstacleGrid.size();i++){
            for(int j = 1;j < obstacleGrid[0].size();j++){
                if(obstacleGrid[i][j]) continue;
                vvi[i][j] = vvi[i-1][j]+vvi[i][j-1];
            }
        }
        return vvi[obstacleGrid.size()-1][obstacleGrid[0].size()-1];
    }
};

跳臺階問題

選硬幣問題

twoSum

反轉連結串列+判斷棧是否合法

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(!head || !head->next) return head;
        ListNode *t1 = head, *t2 = head->next, *t3;
        head->next = nullptr;
        while(t2){
            t3 = t2->next;
            t2->next = t1;
            t1 = t2;
            t2 = t3;
        }
        return t1;
    }
};

LeetCode 912.快速排序(要求分割槽點優化)& 堆排序

一本英文冊中有很多單詞,求單詞的個數

反轉一個字串(需要進行優化)

實現一個佇列

將字串按單詞反轉,字串結尾可能有句號,採用o(1)空間複雜度實現

lru,不用寫全,把雜湊表和雙向連結串列結構寫出來,增刪操作虛擬碼就行

lru和lfu演算法及缺點

最長無重複子串

Leetcode1166 設計檔案系統

寫一個簡單的計算器

找出兩個排序陣列的相同的數

反轉連結串列

字串“12345678910111213141516...”問第n個字元是啥。

一個ip字串,轉換成32位數字,考慮所有情況,把這個數字轉化成01這樣的儲存(回答用移位和與操作,問有其他方法嘛?這時候想到了用struct)

寫一個裝飾器模式