「面试」美团肝了我30+问题
叮。。。。。美團來電。這次不是外賣而是電話面試。所報崗位為后端/服務端開發,但是從我的復盤來看,這和 Java 后端開發的內容差不多,除了部分的語言特性外,還是四大件基礎知識為重,下面我們來看看都問了啥,小心下次面你的時候就有這些問題哦
如果你問我,看了這些題就完事了?非也,這只是開始,你需要學習的還有很多,知道路子是怎么走才是重要的勒。
開始之前,我們先看提綱,大家默默的想一想,如果是你,你將怎么去回答這個問題,然后再看我的回答也許更佳哈。
提綱
1 一面(40分鐘)
自我介紹
老規矩,我叫啥,啥專業,技術棧是啥,能做啥
怎么理解分布式
其實如果沒有去實習,可能很少接觸分布式的內容。對于面試官而言,也沒多期望你們對分布式的理解到多深的地步,只是希望你們能對其有個初步的了解即可。
不管是高登摩爾提出的摩爾定律還是Gordon Moore堅持的2版本是啥,總之如果你的系統需承載的計算量的增長速度大于摩爾定律的預測,那么在未來的某一個時間點,集中式系統將無法承載你所需的計算 量。
在整個計算機系統發展的過程中,最實際的還是經濟的元素。人們發現使用更加廉價的機器,組合在一起的分布式系統,除了可以獲得超過CPU發展速度的性能以外,還可以有更好的性價比,所以得出如下結論:
無論是要以低價格獲得普通的性能,還是要以較高的價格獲 得極高的性能,分布式系統都能夠滿足。并且受規模效應的影響,系統越大,性價比帶來 的收益越高。
隨著計算機的飛速發展,科學家們發現分布式系統相比于集中式系統的另一個很明顯的優勢就是:具有更高的可用性。假設使用10個能夠承載10000流量相同的節點,其中的兩個節點掛了,只要實際的流量不超過8000,那么系統仍然正常運轉。
說這么多,分布式系統還是建立在「分治」和「冗余」的基礎上,這也就是分布式系統的本質
那么分治是什么?
這和我們大腦解決問題類似,大問題分解為小問題,然后治理最后歸并。
分治
為什么要這樣做?
小問題容易解決,解決了眾多的子問題,大問題也就更容易解決啦
如果拆分的父子問題有依賴關系怎么辦?
大問題拆分的過程中,非常重要的即不同分支的子問題不能相互依賴,需要各自獨立,因為如果存在依賴關系,父子問題就失去了「歸并」的意義,那么在開發中,這就是「聚合度」和「內聚度」的問題。
什么是聚合度和內聚度?
所謂聚合度即軟件系統中各個模塊的相互依賴程度。比如在調用A方法的時候都需要同步調用方法B,顯然這樣的耦合度就高
所謂內聚度即模塊之間具有共同點的相似程度,所以在拆分的時候要尤其注意這兩點。
什么是冗余?
這里的冗余不是代碼的冗余,而是容許系統在一定范圍內出現故障,但對系統的影響很小
冗余
如上圖將冗余的節點部署在單獨的服務器,完全是為了備用而做的冗余,如果不出現故障,那么資源是不是就浪費了,所以大多數情況會使用諸如雙主多活、讀寫分離之類的概念提高資源利用率
其實在生活中冗余也很常見,比如大部分的汽車系統中的底層控制系統也是有冗余機制,飛機發動機為什么是偶數,也是同樣的道理。還有更多的關于后端的基礎總結要點則參考另一篇文章42圖揭秘,「后端技術學些啥」
寫個代碼熱熱身----棧實現隊列
class?MyQueue?{ public:stack<int>?stIn;stack<int>?stOut;/**?Initialize?your?data?structure?here.?*/MyQueue()?{}/**?Push?element?x?to?the?back?of?queue.?*/void?push(int?x)?{stIn.push(x);}/**?Removes?the?element?from?in?front?of?queue?and?returns?that?element.?*/int?pop()?{//?只有當stOut為空的時候,再從stIn里導入數據(導入stIn全部數據)if?(stOut.empty())?{//?從stIn導入數據直到stIn為空while(!stIn.empty())?{stOut.push(stIn.top());stIn.pop();}}int?result?=?stOut.top();stOut.pop();return?result;}/**?Get?the?front?element.?*/int?peek()?{int?res?=?this->pop();?//?直接使用已有的pop函數stOut.push(res);?//?因為pop函數彈出了元素res,所以再添加回去return?res;}/**?Returns?whether?the?queue?is?empty.?*/bool?empty()?{return?stIn.empty()?&&?stOut.empty();} };介紹下第一個項目
注意:校招的的面試在我看來寫兩個項目差不多了,印象更深刻且自己的理解程度更好的放在上面。面試之前一定要搞懂這三個問題,且在練習的時候想想怎么能引面試官上鉤
項目的描述
自己在項目中擔任的角色,做了什么
在項目中遇到什么難點,怎么處理,有沒有測試過
說說快排思想?
如果我們的每一次分區操作都能正好將數組分成大小接近相等的兩個小區間,那么快排的時間復雜度和歸并是差不多的,所以其時間復雜度為O(nlogn)
這里特別注意所謂的每次分區操作有個前提條件,即選擇的pivot很合適,能掙好的將大區間對等的一分為二,如果原來的數據是一件排好序的,我們選擇最后一個元素為pivot,這樣每次分區得到的兩個區間是不均等,我們需要進行大約n次分區操作,每次分區平均掃描n/2個元素,此時的復雜度將退化為0(n ^ 2)
注:一定要能手撕快排啊,這真是無數次會被考!!!
public?class?QuickSort?{public?static?void?main(String[]?args)?{int[]?arr?=?{?49,?38,?65,?97,?23,?22,?76,?1,?5,?8,?2,?0,?-1,?22?};quickSort(arr,?0,?arr.length?-?1);System.out.println("排序后:");for?(int?i?:?arr)?{System.out.println(i);}}private?static?void?quickSort(int[]?arr,?int?low,?int?high)?{if?(low?<?high)?{//?找尋基準數據的正確索引int?index?=?getIndex(arr,?low,?high);//?進行迭代對index之前和之后的數組進行相同的操作使整個數組變成有序//quickSort(arr,?0,?index?-?1);?之前的版本,這種姿勢有很大的性能問題,謝謝大家的建議quickSort(arr,?low,?index?-?1);quickSort(arr,?index?+?1,?high);}}private?static?int?getIndex(int[]?arr,?int?low,?int?high)?{//?基準數據int?tmp?=?arr[low];while?(low?<?high)?{//?當隊尾的元素大于等于基準數據時,向前挪動high指針while?(low?<?high?&&?arr[high]?>=?tmp)?{high--;}//?如果隊尾元素小于tmp了,需要將其賦值給lowarr[low]?=?arr[high];//?當隊首元素小于等于tmp時,向前挪動low指針while?(low?<?high?&&?arr[low]?<=?tmp)?{low++;}//?當隊首元素大于tmp時,需要將其賦值給higharr[high]?=?arr[low];}//?跳出循環時low和high相等,此時的low或high就是tmp的正確索引位置//?由原理部分可以很清楚的知道low位置的值并不是tmp,所以需要將tmp賦值給arr[low]arr[low]?=?tmp;return?low;?//?返回tmp的正確位置} }半連接了解吧,如果SYN半連接隊列滿了怎么處理,只能丟棄連接?
如果你看過我之前寫的文章,這個問題應該就非常容易解決了。SYN半連接隊列已滿,通過開啟cookies功能就可以在不使用SYN隊列的情況下成功建立連接
syncookies是怎么操作的?
服務端返回 ACK 的時候會計算一個值放在發出的SYN+ACK報文中,當客戶端返回ACK的時候取出該值進行驗證,如果合法即連接成功
半連接隊列
Linux如何開啟syncookies呢?
通過將參數tcp_cookies設置1即可。如果參數值為2,表示無條件開啟這個功能。如果為1表示僅當SYN半連接隊列放不下的時候,再開啟。
開啟syncookies
那可不可以繞過三次握手?
還有這種操作?
三次握手中,一個較大的問題是HTTP請求必須在一次的RTT后才能發送。從而谷歌提出了TFO。想要繞過三次握手過程,如果是客戶端發起連接,想要在SYN的請求報文中放入數據,需要得到服務端的認可,所以事先需要有個約定。
首次建立連接走正常的三次握手,客戶端會在SYN報文中明確告訴服務器要使用TFO功能,服務端答應后就會將客戶端的IP地址用自己的密鑰加密(cookie)攜帶在返回的SYN+ACK中,客戶端收到后將cookie緩存到本地
下次客戶端再建立連接,就可以在SYN中攜帶請求的數據+緩存的cookie
繞過三次握手
剛才你說的密鑰是不會變的?
當然變化,不然就很容易產生SYN泛洪攻擊了。
Linux中如何打開TFO?
這里要注意了,需要客戶端和服務端都支持,TFO才會生效,當tcp_fastopen設置為3的時候才生效
net.ipv4.tcp_fastopen=3舉幾個使用緩存的例子
這里涉及面就非常廣了,什么數據庫緩存,如何選擇緩存的讀寫策略,如何做到緩存高可用,緩存穿透的怎么處理以及CDN相關,我們先舉幾個緩存的例子
我們知道虛擬地址到物理地址轉換的時候需要通過一個叫做MMU的硬件,每次這樣的轉換無疑會造成性能的轉換,所以接住了TLB來緩存最近轉換過的,下一次轉換的時候,如果緩存存在就直接轉換即可
在路由尋址的時候,會有個映射表讓我們知道該訪問哪個目的地址,同樣存在于緩存中
HTTP緩存機制。通過緩存協商方式減少網絡傳輸的數據大小從而提升頁面展示的性能
緩存怎么個分類?
緩存分類分為三種,分別為靜態緩存、分布式緩存與本地緩存。
靜態緩存
通常使用靜態HTML實現靜態緩存。通過在Nginx上部署靜態緩存減少對于后臺應用服務器的壓力。當然你也可以存放數據庫,然后前端穿透查詢,但是對于后端的服務器壓力是非常大的。比如內容系統,通常在錄入文章的時候先渲染成靜態頁面,然后放在前端Ngix服務器上,這樣用戶會直接訪問前端靜態頁面,但是如果是動態請求,這樣就需要分布式緩存了
分布式緩存
面試中高頻的Redis和Memchache,就是通過集群的方式突破單機瓶頸
熱點本地緩存
熱點嘛,微博每天都有熱點,尤其是什么XX明星出軌,這樣的查詢通常會命中某一個緩存節點,短時間內極高的緩存熱點查詢。這個時候就會在代碼中使用一些本地本地緩存方案。如hashmap
緩存的不足
從上面基本上知道,緩存的主要作用是提升訪問的速度,提升并發的能力。
緩存最好適用于讀多寫少且帶有一定的熱點屬性
因為既然是緩存受限于存儲介質,不可能緩存所有數據,只有當數據有一定的熱點屬性才能有更高的緩存命中率
緩存讓系統更加復雜,容易出現數據不一致的現象
比如更新數據庫成功了,但是更新緩存失敗了。這個時候可以考慮固定時間清理或者手動清理。
給運維帶來一定的成本
運維小哥需要了解一些緩存組件的使用
一面小結
一面面試涉及到了項目,計算機網絡,數據結構和后端的基本知識,也基本覆蓋了校招的各科且有一定的是實踐性考察,不同公司面試當然不一樣,看多了你會發現重點就是這些了,繼續復盤二面
2 二面
慢慢的到了10月,面試的越多不知道的越多,感覺需要學習的越多,當然越戰越勇,面完一面是一面,積累一面是一面。團團既然給臉,那就面唄
寫個代碼-----數組中數字出現的次數
我擦,上來就是寫代碼,不過大家習慣就好,每個面試官套路不同,資本社會接受即可,寫唄,準備這么久的你還怕啥。管他三七二十一,能上位運算就上位運算,盤它完事,小伙伴說能不能寫個python版本,那就py唄。如果這個題目還要猶豫,趕緊再去練練《劍指offer》和leetcode100題呀
class?Solution(object):def?singleNumbers(self,?nums):""":type?nums:?List[int]:rtype:?List[int]"""temp?=?0for?i?in?nums:#得到用于區分的數字temp?^=?inum?=?1while?not?(num?&?temp):#找到用于區分的數字中從右到左的第一位為1的值num?=?num?<<?1result1?=?0result2?=?0for?i?in?nums:if?num?&?i:#?劃分兩個數組result1?^=?i#兩個數組分別取異或else:result2?^=?ireturn[result1,result2]?說說TCP的收發包可通過哪些配置?
這個題就有點大了,我可以扯很久,而且只要問到TCP發送或者接受的類似問題,真是可以大干好幾百個回合。在這里就稍微詳細的說說,在以后的面試過程中,遇到此題講不在多說哈,還答不上來就打自己幾耳巴可好,別別,還是不能這么對自己,好了,不多BB了,上干貨
收包是數據到達網卡后交給應用程序處理的過程,發包則調用相應的發包函數將數據包從網卡發出的場景。
我們再看看類似的幾個問題
我明明是用了write和send進行發包,但是總是發不出去
通過抓包發現數據包已經到網卡了,但是應用程序為什么就是收不到
調整了緩沖區大小,不失效的原因
和前面一樣,都是需要了解相應的系統參數才能較好的回答這些問題且能體現你對網絡的了解深度
TCP數據包在發送的過程中會受到哪些影響?
TCP數據包發送過程
這個圖畫了一個小時,一定要好好看看,順便記得給我一個贊,么么噠,下面我們詳細看看這個圖
當我們通過write等發包函數進行發包的時候,這些系統調用都是將數據包先從用戶緩沖區拷貝到TCP發送緩沖區中,可是這個TCP緩沖區是有大小限制的,正是這個限制就會產生各種問題。
TCP發送緩沖區的默認受到 net.ipv4.tcp_wmen 控制
TCP發送緩沖區設置
這三個參數分別的叫做是min,default,max。TCP發送緩沖區會在min和max中浮動,初始的大小為default。
為什么需要自動調整,是不是越大越好?
首先這個動態調整是由內核來完成,不需要應用程序的干預,而且每次發包的大小不一樣,數據太小,緩沖區卻很大自然就浪費了內存,所以通過動態調整的方式滿足發包的需要。
TCP緩沖區設置太小或者太大有什么標志?
TCP的發送緩沖區設置太小,最明顯的特征即導致業務延遲。如何發現呢,可以通systemtap等工具在內核打點完成觀察,如果發現了有sk_stream_wait_memory就認為這發送緩沖區太小了,需要調大tcp_wemem:max
可不可以開發的時候指定需要發送的大小?
當然可以呀,通過setsockopt中的SO_SNDBUF設置固定的緩沖區大小。但是設置了這個參數,tcp_wmem就會失效,也就沒有了動態調整,設置的值不能超過net.core.wmem_max,如果超過了,內核會強制設置為wmem_max。所以通常情況下,我們不會通過SO_SNDBUF設置TCP緩沖區的大小,設置太大浪費內存,設置太小引起緩沖區不足的問題。
上面所說的tcp_wmem和wmem_max都是針對單個tcp連接,其單位是字節。系統中通常有非常多的tcp連接,連接太多可能導致內存耗盡
我們能不能設置tcp消耗內存的大小?所謂上限
tcp_mem
當所消耗的內存達到max就不會再發包
可以通過什么方式觀測到這種情況?
Linux內核給我們早就埋了點,sock_exceed_buf_limit。觀察的時候只需要打開tracepoint即可
sock_exceed_buf_limit
然后在日志中查看是否發生了事件
trace_pipe
伴隨tcp層數據包的處理完畢來到ip層,在IP層需要考慮端口范圍的問題,太小可能導致無法創建連接。
net.ipv4.ip_local_port_range = 1024
為了實現tcp/ip數據流進行流控,Linux內核在ip層實現了qdisc(排隊規則)。我們平時見的比較多的TC即是基于qdisc的流控工具,實際上我們通過ipconfig看到的txqueuelen即qdisc的隊列長度。它太小就會導致數據包被丟失
我們如何觀察到這個現象?
觀察現象
如果發現dropped不為0,則很可能是txqueuelen太小導致,此時就需要調大這個值
調大txqueuelen
經過ip層后就進入網卡了,此時需要發送的數據包走完TCP/IP協議棧
那么對于接受放而言,是怎么接受的?
同樣,先看看圖
TCP數據包接受過程
從上圖可以發現其接受流程和發送流程基本相反。當數據包到達接受方的網卡,就會觸發中斷,高速CPU讀取數據包,但是在高速網絡中,大量的數據包,如果每來一個數據包就觸發一次中斷勢必讓CPU的處理效率大大折扣,所以提出了NAPI技術,讓CPU一次性輪詢多個數據包,通過批量的方式來提升效率,降低中斷帶來的性能開銷
在poll的時候,一次輪詢多少個?
這個poll通過sysctl選項控制
netdev_budget
此值默認大小為300,通常會增加此值到600使得一次性能處理更多的的數據包
可以無限增大此值?
當然不行,系統存在太多進程,CPU需要權衡自己的時間照顧其他的進程,如果CPU在poll的時間太多,其他任務的調度就會延遲。
當poll了數據包就會到IP層處理,隨后到達tcp層,從而遇到我們之前所說的TCP接受緩沖區
默認通過tcp_rmem控制緩沖區的大小,通過適當的調整該值來獲取更好的網絡性能
tcp_rmem
TCP的默認緩沖區大小會在min和max之間動態的調整,不過和發送緩沖區不同的是,這個動態調整時通過選項tcp_moderade_rcvbuf。通常我們都會打開它
tcp_moderade_rcvbuf
為什么接受緩沖區時通過選項來自動調節,而發送緩沖區不是
因為tcp接受緩沖區會直接影響tcp擁塞控制,從而影響對端的發包,所以通過選項控制的方式更加靈活的控制對端的發包行為
還有其他方式控制tcp的接受緩沖區?
當然有,可以通過setsockopt()的配置選項SO_RECVBUF控制,如果設置了此值,那么tcp緩沖區的自動調整將關閉,總之只有當tcp_moderate_rcvbuf 為 1,并且應用程序沒有通過 SO_RCVBUF 來配置緩沖區大小的情況下,TCP 接收緩沖區才會動態調節
總結:
TCP/IP協議棧復雜無比,此文介紹了很多配置選析,后續給大家總結一個常用的參數表
好了,這個題目也許啰嗦,但是你會發現確實有點東西哈,盤它呀,接著面試
小伙子對這個問題的理解比較深刻,差不多都答在了點上,你說說一致性哈希是什么?
說一致性哈希是什么,那我們肯定需要告訴面試官為啥要用一致性哈希,直接使用哈希不香?有什么問題嘛?
我先用個簡單的例子讓大伙看一波為啥使用一致性哈希
現在我們有一個分布式緩存,需要存放6w張美女照片,別問我干啥,就是存著
三節點存儲image
方案1:直接采用哈希算法,對每個圖片進行分片
哈希
余數正好對應每個機器節點
這樣子會出現什么問題?
通過哈希算法,每個key可以尋址對應服務器,假設發過來的請求為key01,計算公式為hash(key01)%3
經過計算后尋址編號為1的服務器節點,如下圖所示
節點1服務器
此時加入新的服務器節點,就會出現路由失敗的情況。此時從三個節點變化為4個節點,之前的hash(kley01)%3=1就變化為 hash(key-01) % 4 = X,因為取模運算發生了變化,所以這個 X 大概率不是 1,這時你再查詢,就會找不到數據了,因為 key-01 對應的數據,存儲在節點 A 上,而不是節點 B。同樣的道理,如果我們需要下線 1 個服務器節點(也就是縮容),也會存在類似的可能查詢不到數據的問題
對于這個問題怎么解決呢
我們就需要遷移數據,基于新的計算公式 hash(key-01) % 4 ,來重新對數據和節點做映射。需要注意的是,數據的遷移成本是非常高的。
如何解決這個問題---一致性哈希
一致性哈希也是使用了取模運算,但是和傳統的取摸運算不同,一致性哈希算法是對2^32 - 1進行取模運算
即使這些數據均勻,但是數據的活躍度不同,存放熱點數據多的節點訪問量非常大,就很容易的達到CPU瓶頸。一致性哈希算法即將整個哈希值空間組織成一個虛擬的圓環---哈希環
通過哈希算法,將節點映射到哈希環上,通常是節點主機名,ip地址等如下圖
哈希環
在尋址的過程就只需要兩步
將key作為參數執行c-hash計算出哈希值,確定key在環的位置
從這個位置沿著哈希環順時針走,遇到的第一個節點即key對應的節點
如下圖所示
尋址案例
從上圖可以發現,key01對應節點A,key03對應節點C,如果此時C宕機了,只需要將key03定位到節點A即可,key01和key02并不需要改變。所以一致性哈希算法在增加和減少節點的時候,只需要重新定位一小部分數據而不需要重新定位所有數據,這樣就實現了"增加/減少節點需要大規模遷移"這個問題
節點B失效
如果節點比較少,是不是很容易就將請求數據打到一個節點呢?
這個問題即"數據傾斜問題",由于節點的不均勻是的大量你的請求訪問到節點A上,造成負載不均衡。
數據傾斜
鑒于這個問題引入了虛擬節點,簡單的來說通過增加節點的個數來緩解節點的不均勻現象
所謂虛擬節點即對每個服務器節點計算多個哈希值,假設一個真實的節點有2個虛擬節點,此時我的三個節點就共有6個虛擬節點,如下圖所示
引入虛擬節點
此時如果在環上順時針尋找虛擬節點,假設key01選擇虛擬節點nodeB02,那么此時將請求映射到真是節點B即可
所以通過虛擬節點擴充節點數量的方式解決節點較少情況下數據傾斜的問題,代價非常小,只需要增加一個字典map維護真實節點和虛擬節點的映射關系即可
說說HTTP1.0 1.1 2 3的演進
之前有一篇文章單獨說了這個問題,現在粗略總結下,希望讀者們再去查查相關資料
http/1.1 相對于http/1.0性能上的改進:
http/1.0 采用的是短連接,會有較大的三次握手和四次揮手的開銷
支持管道傳輸,http/1.0 只有第一個響應回來才能發這個請求,但是http/1.1 可以連續發送,并不需要等待其回來,減少了整體響應時間
http/1.1 性能瓶頸:
請求/響應的頭部沒有經改壓縮就發送,只能壓縮body部分
發送冗長的首部,每次互相發送相同的首部造成的浪費較多
服務器是按順序響應的,會出現隊頭擁塞的情況
沒有請求優先級控制
請求只能從客戶端開始,服務器只能被動響應
http/2
采用了HPACK算法避免傳送相同的頭部,并且對頭部數據進行了壓縮
對傳輸的數據采用二進制的方式傳輸,分為頭部幀和數據幀
對連接進行了復用,只要訪問同一個域名下的資源,不必進行TCP連接的重新建立
支持服務端push
對于服務端的響應也不會不會出現隊頭擁塞的情況,可以根據優先級進行響應
http/3 QUIC
采用了基于UDP的傳輸層協議,希望取代TCP
仍然也有隊頭阻塞的情況,例如當TCP出現丟包重傳時
支持應用層級別的重傳,而且在只丟失一個數據包的情況下不需要重傳,使用糾錯機制恢復丟失的包
說說數據庫事務的四大特性
事務時一個可執行的邏輯單元,該邏輯單元的操作要么都執行,要么都不執行,事務具有ACID四個性質
原子性:指事務包含的所有操作,要么都被執行成功,如果中間有一條語句失敗,則進行回滾。
一致性:指事務執行前和執行后都必須處于一致性狀態
隔離性:事務之間是相互獨立的,中間狀態對外是不可見的
持久性:數據的修改是永久的
多加索引一定很好嗎
索引主要用于加速查詢速度,但并發越多越好,因為索引需要占用物理空間的,且索引的維護需要時間的,所以如果建索引,一般來說,應該查詢的次數大于插入的次數,同時我們一般只對例如where或者having子句中涉及的字段進行設置索引,因為其它的地方就算建立了索引,一般也用不到,只是浪費。
請問TCP哪些保證了數據傳輸的可靠性
序列號、確認重傳、超時重傳、擁塞控制(ps 看過我之前文章的小伙伴,問這個問題如果不能扯上一小時,自罰三杯)
三個線程順序打印A-Z
5 總結
請記下以下幾點:
公司招你去是干活了,不會因為你怎么怎么的而降低對你的要求標準。
工具上面寫代碼和手撕代碼完全不一樣。
珍惜每一次面試機會并學會復盤。
對于應屆生主要考察的還是計算機基礎知識的掌握,項目要求沒有那么高,是自己做的就使勁摳細節,做測試,只有這樣,才知道會遇到什么問題,遇到什么難點,如何解決的。從而可以侃侃而談了。
非科班也不要怕,怕了你就輸了!一定要多嘗試。
有道無術,術可成;有術無道,止于術
歡迎大家關注Java之道公眾號
好文章,我在看??
總結
以上是生活随笔為你收集整理的「面试」美团肝了我30+问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你这样的“垃圾“,就应该进入老年代!!!
- 下一篇: redis主从架构宕机问题手动解决