- 什么是內核態和用戶態?
作業系統為了安全把CPU分成了特權模式和用戶模式,也就是內核態和用戶態,在操作敏感地帶時,只能由內核操作,或者用戶向內核請求,內核操作完了傳給用戶,也就是說用戶的操作是受限的,僅能操作一些不敏感的東西,
在實際作業系統概念中就叫做內核態,在CPU設計上則叫做特權模式;我們叫做應用程式狀態的,在實際作業系統概念中叫做用戶態,CPU設計上叫做用戶模式
- 對執行緒模型有多少了解?
執行緒的實作曾有3種模型:
多對一(M:1)的用戶級執行緒模型
一對一(1:1)的內核級執行緒模型
多對多(M:N)的兩級執行緒模型
執行緒模型有n:
內核執行緒模型
用戶級執行緒模型
混合型執行緒模型
- 行程、執行緒、協程的區別?
行程是資源分配的最小單位(CPU時間片、記憶體等資源)
執行緒又叫做輕量級行程,由作業系統調度,是CPU調度的最小單位,一個行程可以有多個執行緒,最少有一個執行緒,但一個執行緒只能有一個行程
協程是協作式的用戶態執行緒
行程和執行緒是搶占式執行,協程需要要用戶手動來切換
行程面向的主要內容是記憶體分配管理,而執行緒主要面向的CPU調度
執行緒的切換有背景關系切換且會保存到CPU的堆疊里,協程擁有自己的暫存器背景關系和堆疊,無背景關系切換,復用的就是它所在的執行緒的記憶體空間
協程不是被作業系統內核所管理,而完全是由程式所控制
執行緒是被動掛起恢復,協程是主動掛起恢復
執行緒的大小一般是2M,協程只有2K
- 談談GMP模型.
G(Goroutine) : 每個 Goroutine 對應一個 G 結構體,G 存盤 Goroutine 的運行堆疊、狀態以及任務函式
M(Machine): 對OS內核級執行緒的封裝,數量對應真實的CPU數(真正干活的物件).
P (Processor): 邏輯處理器,即為G和M的調度物件,用來調度G和M之間的關聯關系,其數量可通過 GOMAXPROCS()來設定,默認為核心數,
- 空struct的常見用法.
1.占位符,不占記憶體
2.實作set集合
3.channel傳參
4.只包含方法的空結構體
- defer常見用途.
資源釋放(http client釋放、鎖釋放、檔案關閉)
呼叫堆疊,后入先出
recover捕獲.
-
什么是IO多路復用?
多路指的是多個 socket 連接,復用指的是復用一個執行緒,多路復用主要有三種技術:select,poll,epoll,epoll 是最新的也是目前最好的多路復用技術,
select/epoll 提供了基于事件的回呼機制,即針對不同事件的發生,呼叫相應的事件處理器
內核不是監視應用程式本身的連接,而是監視應用程式的檔案描述符 -
談談golang的鎖.
互斥鎖mutex和讀寫鎖rwmutex. -
什么是nil切片和空切片,有什么區別?
空切片就是長度為0的切片,指標指向底層陣列的地址len=0,容量有指向的底層陣列決定, make([]int,0),可以append,且沒有分配底層陣列,
nil切片簡單來說就是切片的零值,指標并不指向底層的陣列,而是指向一個沒有實際意義的地址,len = 0 且 cap = 0 如 var s []int,未初始化不可以賦值,但是可以append,append 會初始化 nil slice,與此類似的函式還有 copy ,這兩個函式內部都進行 make 初始化,每次對 slice 的操作內部是會產生一個新的陣列,然后回傳, -
goroutine 什么時候發生阻塞?
1.channel 在等待網路請求或者資料操作的IO回傳的時候會發生阻塞
2.發生一次系統呼叫等待回傳結果的時候
3.goroutine進行sleep操作的時候
- 記憶體泄漏常見場景?
暫時性:
- 獲取長字串中的一段導致長字串未釋放
- 獲取長slice中的一段導致長slice未釋放
- 在長slice新建slice導致泄漏.
永久性:
- goroutine永久阻塞而導致泄漏
- time.Ticker未關閉導致泄漏
- 不正確使用Finalizer導致泄漏
- defer close忘記添加,導致檔案句柄耗盡.
12.Mutex的模式?
- 正常模式:鎖的等待者會按照先進先出的順序獲取鎖,一旦 Goroutine 超過 1ms 沒有獲取到鎖,它就會將當前互斥鎖切換饑餓模式,
- 饑餓模式:互斥鎖會直接交給等待佇列最前面的 Goroutine,新的 Goroutine 在該狀態下不能獲取鎖、也不會進入自旋狀態,它們只會在佇列的末尾等待
13.談談http三次握手,四次揮手
握手:
- 客戶端發起請求服務端(說明自己有發送能力)
- 服務端確認客戶端有發送能力,確認客戶端的接收能力
- 客戶端確認接收能力正常.
揮手:
- 客戶端請求斷開
- 服務端確認
- 服務端確認資料發送完成
- 客戶端確認已斷開
14.RPC和http區別.
- RPC要求服務提供方和服務呼叫方都需要使用相同的技術,而http無需關注語言的實作,它不關心實作細節,跨平臺、跨語言更靈活
- RPC的開發要求較多,RPC實作較為復雜
- RPC可以基于TCP和UDP,而http只能基于TCP
- 速度來看,RPC要比http更快,雖然底層都是TCP,但是http協議的資訊往往比較臃腫
- RPC面向C/S HTTP面向B/S.
15.REST特點.
- 服務端專注資料存盤,客戶端關注于展示
- 無狀態(stateless),客戶端保存會話資訊,每次請求必須包括所有資訊
- 所有服務端回應都要被標為可快取或不可快取
- 介面設計盡可能統一通用,且介面與實作解耦,使前后端可以獨立開發迭代
- 分層系統 客戶端無法分辨代理或者真實服務器,還有安全層、負載均衡、快取層
- 按需代碼.
16.linux中常見的行程間通訊方式.
1.管道pipe,
2.命名管道FIFO,
3.訊息佇列,
4.共享記憶體,
5.信號量,
6.套接字,
7.信號,
高級的有 dbus等
17.make和new的區別?
make回傳的是參考型別,new回傳的是指標型別
18.簡述map的原理
type hmap struct {
count int // 元素的個數
B uint8 // buckets 陣列的長度就是 2^B 個
overflow uint16 // 溢位桶的數量
?
buckets unsafe.Pointer // 2^B個桶對應的陣列指標
oldbuckets unsafe.Pointer // 發生擴容時,記錄擴容前的buckets陣列指標
?
extra *mapextra //用于保存溢位桶的地址
}
在go的map實作中,它的底層結構體是hmap,hmap里維護著若干個bucket陣列 (即桶陣列),
Bucket陣列中每個元素都是bmap結構,也即每個bucket(桶)都是bmap結構,每個桶中保存了8個kv對,如果8個滿了,又來了一個key落在了這個桶里,會使用overflow連接下一個桶(溢位桶),
假設當前 B=4 即桶數量為2^B=16個
GET獲取資料
①計算k4的hash值
②通過最后的“B”位來確定在哪號桶
③根據k4對應的hash值前8位快速確定是在這個桶的哪個位置
④對比key完整的hash是否匹配
⑤如果都沒有找到,就去連接的下一個溢位桶中找
PUT存放資料
①通過key的hash值后“B”位確定是哪一個桶
② 遍歷當前桶,通過key的tophash和hash值,防止key重復,然后找到第一個可以插入的位置,即空位置處存盤資料,
③如果當前桶元素已滿,會通過overflow鏈接創建一個新的桶,來存盤資料,當兩個不同的 key 落在同一個桶中,就是發生了哈希沖突,沖突的解決手段是采用鏈表法:在 桶 中,從前往后找到第一個空位進行插入,如果8個kv滿了,那么當前桶就會連接到下一個溢位桶(bmap)
擴容的方式
擴容有兩種,一種是等量擴容,另一種是2倍擴容
等量擴容:元素會發生重排,但不會換桶
2倍擴容: 當前桶陣列確實不夠用了,發生這種擴容時,元素會重排,可能會發生桶遷移,
擴容條件
裝載因子(loadFactor)
loadFactor:=count / (2^B) 即 裝載因子 = map中元素的個數 / map中當前桶的個數
通過計算公式我們可以得知,裝載因子是指當前map中,每個桶中的平均元素個數,
擴容條件1:裝載因子 > 6.5 (原始碼中定義的)
擴容條件2: 溢位桶的數量過多
擴容時的細節
1.在我們的hmap結構中有一個oldbuckets嗎,擴容剛發生時,會先將老資料存到這個里面,
2.每次對map進行刪改操作時,會觸發從oldbucket中遷移到bucket的操作【非一次性,分多次】
3.在擴容沒有完全遷移完成之前,每次get或者put遍歷資料時,都會先遍歷oldbuckets,然后再遍歷buckets,
19.go什么時候會死鎖?
1.無緩沖的channel,讀與寫沒配對準備好(包括單channel自己讀寫、單channel寫的時候新協程未準備好讀、多channel時要求對方先讀/寫)
2.讀寫鎖相互阻塞,形成隱形死鎖
20.context的原理和使用場景?
goroutine的相關環境快照,其中包含函式呼叫以及涉及的相關的變數值,拓撲結構是一個樹型關系,
當一個 context 被取消時,從它派生的所有 context 也將被取消,
當一個context找元素時,會往父級context一級一級往上查找元素,知道根節點或者找到為止,
場景:
1.請求鏈路傳值,
2.取消耗時操作,及時釋放資源,
3.防止 goroutine 泄露,主動取消未完成的任務,
21.channel的實作原理?
22.slice的擴容機制?
容量小于1024時兩倍擴容,大于1024時1.25倍擴容
23.談談Go記憶體管理
1.記憶體池,Go 的程式在啟動之初, 會一次性從OS那里申請一大塊記憶體作為記憶體池,使用時是如下圖一級一級申請一級一級還

2.逃逸分析,逃逸到堆中的變數需要自己去手動清理,速度沒有堆疊中元素清理速度快(由系統管理,使用起來高效無感知)
3.垃圾回收
24.Go垃圾回識訓制?
三色標記法
1.首先創建三個集合:白、灰、黑,
2.將所有物件放入白色集合中,
3.從根節點開始掃描,把遍歷到的物件從白色集合放入灰色集合,
4.之后遍歷灰色集合,將灰色物件參考的物件從白色集合放入灰色集合,之后將此灰色物件放入黑色集合
5.重復4直至灰色物件為空
6.收集所有白色物件(垃圾)
25.Go語言的并發模型?
1.內核級執行緒
2.用戶級執行緒
3.兩級執行緒模型(混合執行緒模型)
4.GMP模型
26.談談沾包拆包的理解?
UDP沒有粘包只有丟包, TCP粘包的原因
TCP是基于流式的發送 并且存在丟包重發機制 TCP是可靠連接而UDP是不可靠的,TCP連接建立后可以一直不停的發送并沒有明確的邊界定義,會開辟一個緩沖區 發送端往其中寫入資料 每過一段時間就發送出去 然后接收端接收到這些資料,有可能后續發送的資料和之前發送的資料同時存在緩沖區中隨后一起發送(是粘包的一種形式 ),另一種是應用程式沒有及時處理緩沖區中的資料 那么后續到達的資料會繼續存放到緩沖區中 也就是2次接收的資料同時存在緩沖區中 下次取緩沖區的時候就會取出2次粘包后的資料 這是粘包的另外一種形式,填充緩沖區到一半緩沖區滿了直接發送了 但是其實那個包還沒填充完全 這個就是不完整的粘包了
27.TCP為什么是可靠的?
序列號和確認應答信號
超時重發控制
連接管理(三次握手四次揮手)
滑動視窗控制
流量控制
擁塞控制,
28.發布訂閱模式和觀察者模式有什么區別?
發布訂閱模式是面向中間渠道開發的,依賴中間服務才能互動,觀察者模式有更高的耦合,
29.mysql為什么要使用B+樹存盤索引?
因為B樹不管葉子節點還是非葉子節點,都會保存資料,這樣導致在非葉子節點中能保存的指標數量變少(有些資料也稱為扇出),指標少的情況下要保存大量資料,只能增加樹的高度,導致IO操作變多,查詢性能變低
30.分布式鎖實作方式
1.資料庫
1.唯一索引
2.樂觀鎖 版本號
3.悲觀鎖
2.redis setnx 或者 set key value nx px
3.etcd lock
4.zoomkeeper
31.高并發情況下使用快取需要注意什么?
1.設定有效期
2.提高快取命中率(快取預熱注意有效期要有隨機事件波動防止快取雪崩、增加存盤容量、調整快取粒度、更新快取等手段來提高命中率)
3.快取并發(設定lock,排隊等待獲取快取結果),
4.防止快取穿透 快取空結果避免錯判,或者布隆過濾器快取所有結果,
5.注意快取一致性(資料庫和快取不一致),未命中快取后判斷鎖是否存在,不存在去判斷設定鎖存在不,不存在就設定鎖,并去查詢資料庫,更新快取,其他情況等待,
6.防重放:(登錄之類的token、唯一索引、分布式鎖、加密請求并且添加時間戳,統一mq異步處理等)
7.快取一致性:(雙刪機制,修改資料庫之前刪,修改完成后再刪)
32.分表后的ID怎么保證唯一性?
1.設定步長
2.分布式ID,UUID或者雪花演算法
3.分表后不使用主鍵作為查詢依據,而是每張表單獨新增一個欄位作為唯一主鍵使用,如訂單表訂單ID
33.分表后非sharding_key的查詢應該怎么處理?
1.添加映射關系表,比如商家要查詢訂單串列,添加商家和用戶關系表,查詢的時候先通過商家查詢到用戶串列,再通過user_id去查詢,
2.寬表,(mysql不合適,可用數倉或者已完成的資料遷移到時序資料庫,或者ES查詢)
3.多執行緒查詢,合并清洗
34.談談GRPC模式
1. 簡單模式:簡單模式只是使用引數和回傳值作為服務器與客戶端傳遞資料的方式,最簡單,
2. 客戶端流模式:即從客戶端往服務器端發送資料使用的是流,即服務器端的引數為流型別,然而在服務器相應后返還資料給客戶端,使用的也是流的send方...
3.服務器端流模式:即服務器端回傳結果的時候使用的是流模式,即傳入的資料是通過引數形式傳入的,但是在往客戶端發送資料時使用send方法,與客戶端...
4.雙向模式:客戶端如果不適用協程,那么發送必須在接收之前,如果使用協程,發送與接收并沒有先后順序,為了保證協程的同步,可以使用互斥量進行約束
35.https 原理
1.客戶端去CA平臺獲取公鑰
2.客戶端生成亂數,根據公鑰加密亂數生成報文
3.客戶端將報文發送給服務端
4.服務端根據私鑰解密報文獲取亂數,向客戶端確認
5.以上是非對稱加密,后面服務端和客戶端根據亂數對稱加密http報文互動
原因:非對稱加密的加解密效率是非常低的,前面的非對稱加密是為了防止中間人攻擊,
抓包流程:生成一個證書,用戶需要手動把證書安裝到客戶端中,然后終端發起的所有請求通過該證書完成與抓包工具的互動,然后抓包工具再轉發請求到服務器,最后把服務器回傳的結果在控制臺輸出后再回傳給終端,從而完成整個請求的倍訓,
36.linux中常見的行程間通訊方式
1.管道pipe,
2.命名管道FIFO,
3.訊息佇列,
4.共享記憶體,
5.信號量,
6.套接字,
7.信號,
8.dbus等
37.瀏覽器打開網頁的步驟
1.決議 URL
2.瀏覽器封裝 HTTP 請求報文
3.DNS 域名決議獲取 IP 地址
4. 建立 TCP 連接
5. 瀏覽器發送請求
6.負責傳輸的 IP 協議
7.使用 ARP 協議憑借 MAC 地址通信
8.服務器回應請求
9.斷開 TCP 連接
10.瀏覽器渲染顯示界面
38.介面冪等性怎么保證?也就是防重放
1.前端提交時每次推送唯一token,防重放攻擊,ID被消費了就丟棄
2.前端添加按鈕一次性點擊或者等待結果成功回應才能繼續點擊的功能
3.添加分布式鎖(setNx 必須得有過期時間和每次設定時的隨機值,只能洗掉自己設定的鎖)
4.mq異步佇列單執行緒消費,重復的直接丟棄
5.設定狀態機(狀態流轉 1->2->3->4)
6.資料庫添加悲觀鎖, select for update
7.資料庫添加樂觀鎖,查詢之后回傳版本號,版本號不匹配則取消操作
8.update添加條件
9.加唯一索引
10.防重表(只有ID+唯一索引控制,洗掉業務資料的時候需要洗掉防重表資料)
11.insert on duplicate key update(如果不存在就插入,存在就更新)
12.inert ignore
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/501081.html
標籤:其他
上一篇:QT官方社區及版本說明
