騰訊泛工業化後臺開發面試問題彙總

lihong1191發表於2020-10-21

自我介紹:

應該考察基本資訊,這個按照自己的實際情況回答。


做過的最難的東西是啥:

應該考察技術頂點是啥,這個按照自己的實際情況回答。(我回答了個spark演算法的優化點)


zookeeper 原理:

from:https://blog.csdn.net/java_66666/article/details/81015302
 


資料庫隔離機制:

隔離級別說明

MySQL定義了四種隔離級別,包括一些具體規則,用於限定事務內外哪些改變是可見的,哪些改變是不可見的。低階別的隔離一般支援更高的併發處理,並且擁有更低的系統開銷。

REPEATABLE READ Repeatable Read 可重複讀

MySQL資料庫預設的隔離級別。該級別解決了READ UNCOMMITTED隔離級別導致的問題。它保證同一事務的多個例項在併發讀取事務時,會“看到同樣的”資料行。不過,這會導致另外一個棘手問題“幻讀”。InnoDB和Falcon儲存引擎通過多版本併發控制機制解決了幻讀問題。

READ COMMITTED Read Committed 讀取提交內容

大多數資料庫系統的預設隔離級別(但是不是MySQL的預設隔離級別),滿足了隔離的早先簡單定義:一個事務開始時,只能“看見”已經提交事務所做的改變,一個事務從開始到提交前,所做的任何資料改變都是不可見的,除非已經提交。這種隔離級別也支援所謂的“不可重複讀”。這意味著使用者執行同一個語句兩次,看到的結果是不同的。

READ UNCOMMITTED Read UnCommitted 讀取未提交內容

在這個隔離級別,所有事務都可以“看到”未提交事務的執行結果。在這種級別上,可能會產生很多問題,除非使用者真的知道自己在做什麼,並有很好的理由選擇這樣做。本隔離級別很少用於實際應用,因為它的效能也不必其他效能好多少,而別的級別還有其他更多的優點。讀取未提交資料,也被稱為“髒讀”

SERIALIZABLE Serializable 可序列化

該級別是最高階別的隔離級。它通過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡而言之,SERIALIZABLE是在每個讀的資料行上加鎖。在這個級別,可能導致大量的超時Timeout和鎖競爭Lock Contention現象,實際應用中很少使用到這個級別,但如果使用者的應用為了資料的穩定性,需要強制減少併發的話,也可以選擇這種隔離級

下面的表格總結了各種隔離級別和各自的缺點

隔離級別髒讀可能性不可重複讀可能性幻讀可能性加鎖讀
READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE

from:https://blog.csdn.net/sinat_35322593/article/details/81040479


協程是什麼?

協程是比執行緒更小的一種執行單元,你可以認為是輕量級的執行緒,之所以說輕,其中一方面的原因是協程所持有的棧比執行緒要小很多,java當中會為每個執行緒分配1M左右的棧空間,而協程可能只有幾十或者幾百K,棧主要用來儲存函式引數、區域性變數和返回地址等資訊。

我們知道,而執行緒的排程是在作業系統中進行的,而協程排程則是在使用者空間進行的,是開發人員通過呼叫系統底層的執行上下文相關api來完成的,有些語言,比如nodejs、go在語言層面支援了協程,而有些語言,比如C,需要使用第三方庫才可以擁有協程的能力。

由於執行緒是作業系統的最小執行單元,因此也可以得出,協成是基於執行緒實現的,協程的建立、切換、銷燬都是在某個執行緒中來進行的。

使用協程是因為執行緒的切換成本比較高,而協程在這方面很有優勢。

為什麼協程的切換很廉價

關於這個問題,我找了很多資料,得到的答案都沒有太高的說服力,我瞭解了一下執行緒切換的過程:

  • 執行緒在進行切換的時候,需要將CPU中的暫存器的資訊儲存起來,然後讀入另外一個執行緒的資料,這個會花費一些時間
  • CPU的快取記憶體中的資料,也可能失效,需要重新載入
  • 執行緒的切換會涉及到使用者模式到核心模式的切換,據說每次模式切換都需要執行上千條指令,很耗時。

協程的切換之所以快,可能的原因是:

  • 在切換的時候,暫存器需要儲存和載入的資料量比較小。
  • 快取記憶體可以有效利用
  • 沒有使用者模式到核心模式的切換操作。
  • 更有效率的排程,因為協程是非搶佔式的,前一個協程執行完畢或者堵塞,才會讓出CPU,而執行緒則一般使用了時間片的演算法,會進行很多沒有必要的切換(為了儘量讓使用者感知不到某個執行緒卡)。

有哪些協程的實現

目前協程有很多版本的實現,比如雲風(原網易的研發總監,開發過《大話西遊》、《夢幻西遊》等知名遊戲)的基於ucontext實現的coroutine,還有人用C語言語法switch-case來實現的。

from:https://www.jianshu.com/p/658cb5360960


java的BIO、BIO和AIO分別是什麼,區別是什麼?

from:https://blog.csdn.net/m0_38109046/article/details/89449305?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param


aAuth是如何登陸?

OAuth2.0是什麼——豆瓣和QQ的故事

OAuth簡單說就是一種授權的協議,只要授權方和被授權方遵守這個協議去寫程式碼提供服務,那雙方就是實現了OAuth模式。

舉個例子,你想登入豆瓣去看看電影評論,但你丫的從來沒註冊過豆瓣賬號,又不想新註冊一個再使用豆瓣,怎麼辦呢?不用擔心,豆瓣已經為你這種懶人做了準備,用你的qq號可以授權給豆瓣進行登入,請看

from:https://www.cnblogs.com/flashsun/p/7424071.html


java的 hash 原理是什麼,假如自己實現一個,如何實現,思路是什麼?

hashmap是一個key-value鍵值對的資料結構,從結構上來講在jdk1.8之前是用陣列加連結串列的方式實現,jdk1.8加了紅黑樹,hashmap陣列的預設初始長度是16,hashmap陣列只允許一個key為null,允許多個value為null
hashmap的內部實現,hashmap是使用陣列+連結串列+紅黑樹的形式實現的,其中陣列是一個一個Node[]陣列,我們叫他hash桶陣列,它上面存放的是key-value鍵值對的節點。HashMap是用hash表來儲存的,在hashmap裡為解決hash衝突,使用鏈地址法,簡單來說就是陣列加連結串列的形式來解決,當資料被hash後,得到陣列下標,把資料放在對應下表的連結串列中。
然後再說一下hashmap的方法實現
put方法,put方法的第一步,就是計算出要put元素在hash桶陣列中的索引位置,得到索引位置需要三步,去put元素key的hashcode值,高位運算,取模運算,高位運算就是用第一步得到的值h,用h的高16位和低16位進行異或操作,第三步為了使hash桶陣列元素分佈更均勻,採用取模運算,取模運算就是用第二步得到的值和hash桶陣列長度-1的值取與。這樣得到的結果和傳統取模運算結果一致,而且效率比取模運算高
jdk1.8中put方法的具體步驟,先判斷hashmap是否為空,為空的話擴容,不為空計算出key的hash值i,然後看table[i]是否為空,為空就直接插入,不為空判斷當前位置的key和table[i]是否相同,相同就覆蓋,不相同就檢視table[i]是否是紅黑樹節點,如果是的話就用紅黑樹直接插入鍵值對,如果不是開始遍歷連結串列插入,如果遇到重複值就覆蓋,否則直接插入,如果連結串列長度大於8,轉為紅黑樹結構,執行完成後看size是否大於閾值threshold,大於就擴容,否則直接結束
get方法就是計算出要獲取元素的hash值,去對應位置取即可。
擴容機制,hashmap的擴容中主要進行兩部,第一步把陣列長度變為原來的兩倍,第二部把舊陣列的元素重新計算hash插入到新陣列中,在jdk1.8時,不用重新計算hash,只用看看原來的hash值新增的一位是零還是1,如果是1這個元素在新陣列中的位置,是原陣列的位置加原陣列長度,如果是零就插入到原陣列中。擴容過程第二部一個非常重要的方法是transfer方法,採用頭插法,把舊陣列的元素插入到新陣列中。
3.hashmap大小為什麼是2的冪次方
在計算插入元素在hash桶陣列的索引時第三步,為了使元素分佈的更加均勻,用取模操作,但是傳統取模操作效率低,然後優化成h&(length-1),設定成2冪次方,是因為2的冪次方-1後的值每一位上都是1,然後與第二步計算出的h值與的時候,最終的結果只和key的hashcode值本身有關,這樣不會造成空間浪費並且分佈均勻,如果不是2的冪次方
如果length不為2的冪,比如15。那麼length-1的2進位制就會變成1110。在h為隨機數的情況下,和1110做&操作。尾數永遠為0。那麼0001、1001、1101等尾數為1的位置就永遠不可能被entry佔用。這樣會造成浪費,不隨機等問題。

from:https://blog.csdn.net/qq_40574571/article/details/91569521

微服務架構的優勢和劣勢是什麼?

微服務架構的好處

微服務架構模式有很多好處。首先,通過分解巨大單體應用為多個服務方法解決了複雜性問題。在功能不變的情況下,應用被分解為多個可管理的分支或服務。每個服務都有一個用 RPC- 或者訊息驅動 API 定義清楚的邊界。微服務架構模式給採用單體式編碼方式很難實現的功能提供了模組化的解決方案,由此,單個服務很容易開發、理解和維護。

第二,這種架構使得每個服務都可以有專門開發團隊來開發。開發者可以自由選擇開發技術,提供 API 服務。當然,許多公司試圖避免混亂,只提供某些技術選擇。然後,這種自由意味著開發者不需要被迫使用某專案開始時採用的過時技術,他們可以選擇現在的技術。甚至於,因為服務都是相對簡單,即使用現在技術重寫以前程式碼也不是很困難的事情。

第三,微服務架構模式使得每個微服務獨立部署,開發者不再需要協調其它服務部署對本服務的影響。這種改變可以加快部署速度,譬如 UI 團隊可以採用 AB 測試並快速部署變化。微服務架構模式使得持續化部署成為可能。

最後,微服務架構模式使得每個服務獨立擴充套件。你可以根據每個服務的規模來部署滿足需求的實利。甚至於,你可以使用更適合於服務資源需求的硬體。比如,你可以在 EC2 Compute Optimized instances 上部署 CPU 敏感的服務,而在 EC2 memory-optimized instances 上部署記憶體資料庫。

微服務架構的不足

Fred Brooks 在 30 年前寫道 “there are no silver bullets”,像任何其它科技一樣,微服務架構也有不足。其中一個跟他的名字類似,“微服務”強調了服務大小,實際上,有一些開發者鼓吹建立稍微大一些的,10-100 LOC服務組。儘管小服務更樂於被採用,但是不要忘了微服務只是結果,而不是最終目的。微服務的目的是有效的拆分應用,實現敏捷開發和部署。

另外一個不足之處在於,微服務應用是分散式系統,由此會帶來固有的複雜性。開發者需要在 RPC 或者訊息傳遞之間選擇並完成程式間通訊機制。此外,他們必須寫程式碼來處理訊息傳遞中速度過慢或者不可用等區域性失效問題。當然這並不是什麼難事,但相對於單體式應用中通過語言層級的方法或者程式呼叫,微服務下這種技術顯得更復雜一些。

另外一個關於微服務的挑戰來自於分割槽的資料庫架構。同時更新多個業務主體的事務很普遍。這種事務對於單體式應用來說很容易,因為只有一個資料庫。在微服務架構應用中,需要更新不同服務所使用的不同的資料庫。使用分散式事務並不一定是好的選擇,不僅僅是因為 CAP 理論,還因為當前高擴充套件性的 NoSQL 資料庫和訊息傳遞中介軟體並不支援這一需求。最終你不得不使用一個最終一致性的方法,從而對開發者提出了更高的要求和挑戰。

測試一個基於微服務架構的應用也是很複雜的任務。比如,對於採用流行的 Spring Boot 架構的單體式 web 應用,測試它的 REST API,是很容易的事情。反過來,同樣的服務測試需要啟動與它有關的所有服務(至少需要這些服務的 stubs)。再重申一次,不能低估了採用微服務架構帶來的複雜性。

另外一個挑戰在於,微服務架構模式應用的改變將會波及多個服務。比如,假設你在完成一個案例,需要修改服務A、B、C,而 A 依賴 B,B 依賴 C。在單體應用中,你只需要改變相關模組,整合變化,部署就好了。對比之下,微服務架構模式就需要考慮相關改變對不同服務的影響。比如,你需要更新服務 C,然後是 B,最後才是 A。幸運的是,許多改變一般隻影響一個服務,而需要協調多服務的改變很少。

部署一個微服務應用也很複雜,一個單體應用只需要在複雜均衡器後面部署各自的伺服器就好了。每個應用例項是需要配置諸如資料庫和訊息中介軟體等基礎服務。相比之下,一個微服務應用一般由大批服務構成。根據 Adrian Cockcroft 的分享,Hailo 由 160 個不同服務構成,而 NetFlix 則超過 600 個服務。每個服務都有多個例項,這就形成大量需要配置、部署、擴充套件和監控的部分。除此之外,你還需要完成一個服務發現機制(後續文章中發表),以用來發現與它通訊服務的地址(包括伺服器地址和埠)。傳統的解決問題辦法並不能解決這麼複雜的問題。最終,成功部署一個微服務應用需要開發者有足夠的控制部署方法,並高度自動化。

自動化的方法之一是使用譬如 Cloud Foundry 這樣的 PaaS 服務。PaaS 能讓開發者輕鬆部署和管理微服務,讓他們無需為獲取並配置 IT 資源勞神。同時,配置 PaaS 的系統和網路專家可以採用最佳實踐和策略來簡化這些問題。另外一個自動部署微服務應用的方法是開發自己的基礎 PaaS 系統。通常的起步方式是 Mesos 或 Kubernetes 這樣的叢集管理方案,配合 Docker 使用。作為一種基於軟體的應用交付方法,NGINX 能夠方便地在微服務層面提供緩衝、許可權控制、API 統計、以及監控。我們會在後續的文章中分析它如何解決這些問題。


伺服器網路連線達到上限,應該怎麼處理?

1 受記憶體限制

每個tcp連線是一個開啟的socket檔案,因此linux伺服器的最大連線數受linux作業系統單個程式同時開啟的最大檔案數的限制。

這個限制本質上是對單個程式記憶體的限制。

檢視程式最大檔案數:

ulimit -n 

設定進行最大檔案數:

ulimit -n 100000

from:https://www.cnblogs.com/hustdc/p/10918744.html


總結:

基本上得按照簡歷進行準備,熟悉簡歷中的各個知識點。

相關文章