2020年Shopee面試問題整理


------------恢復內容開始------------
個人的一二面記錄:https://www.cnblogs.com/Jun10ng/p/12616409.html

本文md文件在:https://github.com/Jun10ng/Gache/blob/master/Shopee面試問題整理.md
給個start吧

Shopee面試問題整理

三握手四揮手 及其狀態

Go操作redis

github 上面的rediGo

什么是平衡二叉樹

編程:實現反轉鏈表

MySQL復合索引

set的使用場景 有序set的使用場景

有序且去重的場景

1、 排行榜:有序集合經典使用場景。例如視頻網站需要對用戶上傳的視頻做排行榜,榜單維護可能是多方面:按照時間、按照播放量、按照獲得的贊數等。

2、用Sorted Sets來做帶權重的隊列,比如普通消息的score為1,重要消息的score為2,然后工作線程可以選擇按score的倒序來獲取工作任務。讓重要的任務優先執行。

反射 反射的弊端

優點:運行期類型的判斷,動態類加載,動態代理使用反射。

缺點:性能是一個問題,反射相當於一系列解釋操作,通知jvm要做的事情,性能比直接的java代碼要慢很多。

進程調度算法

先來先服務 時間片輪轉算法 短作業優先 最短剩余時間 高響應比 優先級

進程間怎么通信

管道 有名管道 套接字 消息隊列 信號量

線程間通信

主要分為共享內存和消息傳遞

volatile關鍵字 wait/notify機制

事務隔離級別

隔離級別 臟讀(Dirty Read) 不可重復讀 幻讀(Phantom Read)

未提交讀(Read uncommitted) 可能 可能 可能

已提交讀(Read committed) 不可能 可能 可能

可重復讀(Repeatable read) 不可能 不可能 可能

可串行化(Serializable ) 不可能 不可能 不可能

MyISAM和InnoDB差別

MyISAM不支持事務,InnoDB支持。MyISAM不支持行鎖,只支持表鎖,InnoDB支持行鎖。

InnoDB沒有保存具體的行數,所以在統計行數的時候回掃描全表,MyISAM有保存。

myisam的索引以表名+.MYI文件分別保存。innodb的索引和數據一起保存在表空間里。

LINUX kill命令

在Linux/unix下,中止一個Java進程有兩種方式,一種是kill -9 pid,一種是kill -15 pill(默認)。

SIGNKILL(9) 的效果是立即殺死進程. 該信號不能被阻塞, 處理和忽略

SIGNTERM(15) 的效果是正常退出進程,退出前可以被阻塞或回調處理。並且它是Linux缺省的程序中斷信號(默認是15)。

TCP四次揮手的TIME_WAIT

在第三次揮手的時候,服務端發FIN給客戶端,然后客戶端再發ACK命令給客戶端,然后進入TIME_WAIT狀態,2MSL之后,進入CLOSED狀態,從客戶端的角度來說,第四次揮手是為了告訴服務端,我收到了你的FIN信號,一切正常,等待2MSL是為了確保服務端收到了ACK,如果因為網絡波動導致服務端沒收到ACK,那么服務端會重傳FIN信號。從服務端的角度老說,第四次揮手能確保客戶端收到FIN信號。

TCP UDP

TCP面向連接,UDP是無連接的,TCP能通過校驗和,重傳控制等,保證可靠傳輸,UDP不能保證可靠傳輸,但UDP實時性高且UDP對資源需要的少。

TCP 如何保證數據傳輸的可靠性

校驗和 確認應答+序列號 超時重傳 流量控制 擁塞控制

TCP3次握手的過程,為什么要3次 ,SYN攻擊

大文件為什么越下載越快?

滑動窗口,慢啟動算法,越傳越快。

前面說過,還有一個ssthresh(slow start threshold),是一個上限,當cwnd >= ssthresh時,就會進入“擁塞避免算法”。一般來說ssthresh的值是65535,單位是字節,當cwnd達到這個值時后,算法如下:

1)收到一個ACK時,cwnd = cwnd + 1/cwnd

2)當每過一個RTT時,cwnd = cwnd + 1

這樣就可以避免增長過快導致網絡擁塞,慢慢的增加調整到網絡的最佳值。很明顯,是一個線性上升的算法。

Innodb 自增主鍵

上文討論過InnoDB的索引實現,InnoDB使用聚集索引,數據記錄本身被存於主索引(一顆B+Tree)的葉子節點上。這就要求同一個葉子節點內(大小為一個內存頁或磁盤頁)的各條數據記錄按主鍵順序存放,因此每當有一條新的記錄插入時,MySQL會根據其主鍵將其插入適當的節點和位置,如果頁面達到裝載因子(InnoDB默認為15/16),則開辟一個新的頁(節點)。

如果表使用自增主鍵,那么每次插入新的記錄,記錄就會順序添加到當前索引節點的后續位置,當一頁寫滿,就會自動開辟一個新的頁。這樣就會形成一個緊湊的索引結構,近似順序填滿。由於每次插入時也不需要移動已有數據,因此效率很高,也不會增加很多開銷在維護索引上。

HTTP 無狀態 無連接

無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答后,即斷開連接。采用這種方式可以節省傳輸時間。為請求時建連接、請求完釋放連接,以盡快將資源釋放出來服務其他客戶端,可以加KeepAlive彌補無連接的問題

無狀態是指協議對於事務處理沒有記憶能力,服務器不知道客戶端是什么狀態。即我們給服務器發送 HTTP 請求之后,服務器根據請求,會給我們發送數據過來,但是,發送完,不會記錄任何信息。 可以通過Cookie和Session來彌補這個問題。

cookie 是一種發送到客戶瀏覽器的文本串句柄,並保存在客戶機硬盤上,可以用來在某個WEB站點會話間持久的保持數據。

Session的本質上也是cookie,但是不同點是存在服務器上的。這就導致,你如果使用cookie,你關閉瀏覽器之后,就丟掉Cookie了,但是如果關掉瀏覽器,重新打開之后,發現還有相應的信息,那就說明用的是Session。因為cookie是存在本地的,所以也會有相應的安全問題,攻擊者可以去偽造他,填寫相應的字段名,就能登錄你的賬戶,還有如果cookie的有效期很長的話,也不安全。

session 由服務器產生,對於客戶端,只存儲session id在cookie中。

LRU算法是如何實現的?

雙向鏈表加 哈希表

數組中出現次數最高的K個數

map+優先隊列

先用map統計每個數的出現次數,然后維護 一個大小為K的優先隊列(堆)。

volatile 內存屏障

CPU有可能會把相應代碼的CPU指令進行一次重排序,這雖然能提高運行的效率,但是也可能會影響一些數據的可見性,而volatile通過 內存屏障 這個指令,來保證了相應代碼塊的執行順序。內存屏障還會強制更新一次CPU緩存。加載最新的內容。

快排的優化

快排有三個步驟:

  1. 選擇基准
  2. 分割操作
  3. 遞歸地對兩個序列快速排列,直到序列為空或只有一個元素。

所以可以針對這三個方面做優化

選擇基准:最理想的基准就是,每次划分都能分成登長的兩個子序列。最壞的情況 就是基准是最大最小值。

可以選的基准有:固定位置,隨機位置,三數取中。

三數取中是指 取 最左 最右 中間元素 三個數的中間值。

其他優化方式

  1. 當排序序列分割到一定大小的時候,可以使用插入排序
  2. 如果有key相等的元素,可以聚在一起,下次排序的時候,就不用對相等的元素再排序了
  3. 優化遞歸操作
  4. 多線程

Mysql 的 redo undo

Undo日志記錄某數據被修改前的值,可以用來在事務失敗時進行回滾;Redo日志記錄某數據塊被修改后的值,可以用來恢復未寫入data file的已成功事務更新的數據。

死鎖的四個條件 和預防

互斥,不可剝奪,循環等待,請求和保持

預防,檢測,避免死鎖,接觸死鎖

銀行家算法

多路IO模型 NIO

在多路復用IO模型中,會有一個線程(Java中的Selector)不斷去輪詢多個socket的狀態,只有當socket真正有讀寫事件時,才真正調用實際的IO讀寫操作。因為在多路復用IO模型中,只需要使用一個線程就可以管理多個socket,系統不需要建立新的進程或者線程,也不必維護這些線程和進程,並且只有在真正有socket讀寫事件進行時,才會使用IO資源,所以它大大減少了資源占用。

五種網絡IO模型

阻塞IO 非阻塞IO 多路IO復用,信號驅動IO(不常用),異步IO,

前四種都是同步IO

像listen()、send()、recv()這些接口都是阻塞的,一問一答型的。這就給網絡編程帶來了一個問題,如果在調用send的時候,線程將被阻塞,在此期間,無法執行任何運算或相應任何的網絡請求。於是有了多路IO模型,一個socket可以多次accept多次,比如Java中的selcetor 不斷輪詢多喝socket的狀態,只有當socket真正有讀寫事件的時候,才會調用實際的IO讀寫操作,還有想Golang里的select+多個channel,這樣只需要一個線程就可以管理多個socket,能減少大量資源占用。

非阻塞IO模型

在非阻塞IO模型中,用戶進程不需要主動詢問對方是否准備好數據與否,比如進程發出read操作,如果對方沒有准備好,會返回一個error,這表示對方沒有准備好,但是進程並不會阻塞在這一步,而是繼續執行,等對方准備好數據后,再去調用它。

異步IO

異步IO是真正意義上的非阻塞IO,用戶進程發起read操作后,立刻就可以開始做其他事,而另一方面,當他收到一個異步請求時,會立即返回一個值,所以不會對用戶進程產生任何阻塞,等數據准備完后,再將數據拷貝到用戶內存,當這一切都完成后,再給用戶進程發送一個signal,告訴他read操作完成了。

非阻塞IO和異步IO的區別

雖然非阻塞IO在大多時間內不會被阻塞,但是它要求進程去主動監察對方數據是不是准備好了,一旦准備好了,會再次要求進程調用接收函數將數據拷貝過來。而異步IO完全不管這些,就像吧IO操作外包掉,等他人做完再發信號通知,這個期間內,進程不要檢查也不用主動的去拷貝。

Golang里的Sync包

互斥鎖:Mutex,讀寫鎖:RWMutex. WaitGoup,Cond實現一個條件變量,Once 使對象只執行一次。

Java線程的6種狀態及切換

初始:新建一個線程對象

運行:調用了start后就是運行狀態

阻塞:線程被鎖阻塞

等待,進入該狀態的線程需要等待其他線程做出一些動作(通知或者喚醒

超時等待:

終止:

虛擬內存

虛擬內存使得應用程序認為它擁有連續的可用內存,這樣一來,就在邏輯層面上擴大了內存容量。但是實際上,只是把比較常用的內存片段取出來了而已,還有部分資源是放在磁盤存儲器上的。需要的時候再進行數據交換。

調度方式有,分頁式,段式,段頁式。比較流行方式是段頁式,他結合了前兩者的優點,以頁為單位替換,以段為單位使用。

常見的替換替換算法有4種,隨機算法,先進先出算法,LRU算法,最優算法。 比較常使用的是LRU算法,他在redis里也有使用,當redis的內存滿了的時候就是使用LRU算法替換掉舊內存。

------------恢復內容結束------------


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM