深信服一面总结
1 項(xiàng)目
項(xiàng)目是C++集群聊天服務(wù)器里面涉及到主要的技術(shù)棧有 nginx負(fù)載均衡器、基于redis的發(fā)布訂閱序列、muduo網(wǎng)絡(luò)庫(kù)(使用的時(shí)候特別的簡(jiǎn)單,但是面試官一般會(huì)問它的底層代碼是怎么實(shí)現(xiàn)的,最主要的思想是epoll+線程池)、mysql、json序列化和反序列化
(1)怎么處理多個(gè)客戶端的連接
epoll去監(jiān)聽客戶端的連接,當(dāng)有多個(gè)客戶端到來(lái)之后條件變量利用廣播的方式去喚醒多個(gè)線程,線程來(lái)任務(wù)隊(duì)列取走任務(wù)。
線程池的創(chuàng)建
a 設(shè)置一個(gè)生產(chǎn)者消費(fèi)者隊(duì)列作為臨界資源
b 初始話n個(gè)線程 并讓其運(yùn)行起來(lái),加鎖去隊(duì)列去任務(wù)運(yùn)行(可以設(shè)置管理線程,根據(jù)任務(wù)的需要適時(shí)的增加和銷毀線程,增加和銷毀線程是有一定的步長(zhǎng),通過喚醒線程讓其自殺的方式去銷毀線程)
c 當(dāng)任務(wù)隊(duì)列為空的時(shí)候,所有線程阻塞
d 當(dāng)生產(chǎn)者隊(duì)列來(lái)了一個(gè)任務(wù)的時(shí)候,先對(duì)隊(duì)列加鎖,把任務(wù)掛在隊(duì)列上,然后使用條件變量去通知阻塞中的一個(gè)線程。
再來(lái)補(bǔ)充一下條件變量的知識(shí)貫通一下。
條件變量不是鎖,但是也可以使線程阻塞,經(jīng)常與互斥鎖聯(lián)合使用,條件變量一般會(huì)做三件事情
a? 阻塞等待條件變量滿足
b 釋放已經(jīng)掌握的互斥鎖相當(dāng)于 pthread_mutex_unlock(&mutex)(a ,b兩步為一個(gè)原子操作)
c 當(dāng)被喚醒,pthread_cond_wait函數(shù)返回時(shí),解除阻塞并重新申請(qǐng)獲取互斥鎖 pthread_mutex_lock(&mutex);
條件變量可以減少生產(chǎn)者內(nèi)部之間的競(jìng)爭(zhēng),減少資源的浪費(fèi)。
(2)如果一個(gè)線程一直讀一個(gè)socket怎么辦
將多個(gè)socket保存下來(lái),設(shè)置定時(shí)器,按照優(yōu)先級(jí)去讀socket。
(3)nginx負(fù)載均衡策略
輪詢,ip_hash,ip_least.ip_weight;
企業(yè)常采用 ip_hash加一致性哈希算法的策略,每個(gè)客戶最好連接固定的服務(wù)器,每個(gè)服務(wù)器上有固定的緩存。一致性哈希算法目的就是某臺(tái)服務(wù)器掛掉之后盡量減少影響。
一致性哈希算法
如果是32位系統(tǒng)。用緩存數(shù)據(jù)除以2的32 次方取余數(shù),通過這個(gè)余數(shù)把服務(wù)器映射到一個(gè)圓上,但是有可能會(huì)出現(xiàn)哈希傾斜的問題,針對(duì)此問題,最好虛擬出一些節(jié)點(diǎn)。使服務(wù)器均衡的映射到服務(wù)器。
nginx如何配置基于http或者基于tcp的負(fù)載均衡?
Nginx使用了一個(gè)新的stream模塊來(lái)實(shí)現(xiàn)TCP負(fù)載均衡,這個(gè)模塊,類似于http和mail模塊,允許我們配置一組監(jiān)聽TCP連接的服務(wù)。允許你配置多個(gè)服務(wù)的TCP連接,通過在upstream的server組中配置proxy_pass指令。修改nginx.conf文件,在http模塊的統(tǒng)計(jì)目錄,添加一個(gè)stream模塊(和http等同級(jí)):
(4)redis的五大數(shù)據(jù)類型
(a)string :最基本的是 string 可以包含任何數(shù)據(jù) 比如 圖片或者序列化的對(duì)象。一個(gè)redis中字符串value最多可以是512M
? (b) hash 是一個(gè)string類型的field和value的映射表,hash特別適合與存儲(chǔ)對(duì)象
(c) list 常作為消息隊(duì)列使用
(d)set? ?適合去重 求交集
? (e)zset
redis是基于內(nèi)存的操作,所以要比直接訪問數(shù)據(jù)庫(kù)快
Redis 持久化機(jī)制
Redis是一個(gè)支持持久化的內(nèi)存數(shù)據(jù)庫(kù),通過持久化機(jī)制把內(nèi)存中的數(shù)據(jù)同步到硬盤文件來(lái)保證數(shù)據(jù)持久化。當(dāng)Redis重啟后通過把硬盤文件重新加載到內(nèi)存,就能達(dá)到恢復(fù)數(shù)據(jù)的目的。
實(shí)現(xiàn):單獨(dú)創(chuàng)建fork()一個(gè)子進(jìn)程,將當(dāng)前父進(jìn)程的數(shù)據(jù)庫(kù)數(shù)據(jù)復(fù)制到子進(jìn)程的內(nèi)存中,然后由子進(jìn)程寫入到臨時(shí)文件中,持久化的過程結(jié)束了,再用這個(gè)臨時(shí)文件替換上次的快照文件,然后子進(jìn)程退出,內(nèi)存釋放。
RDB是redis默認(rèn)的持久化方式。
AOF:redis會(huì)將每一個(gè)收到的寫命令都通過write函數(shù)追加到文件最后
當(dāng)兩種方式同時(shí)開啟時(shí),數(shù)據(jù)恢復(fù)redis會(huì)優(yōu)先選擇AOF恢復(fù)。
緩存雪崩:原有緩存失效,新緩存未到,采用了相同的過期時(shí)間,再同一時(shí)刻出現(xiàn)大面積的緩存過期。
解決辦法:
(1)對(duì)數(shù)據(jù)進(jìn)行加鎖或者隊(duì)列的方式保證不會(huì)有大量的線程對(duì)數(shù)據(jù)庫(kù)進(jìn)行一次性讀寫
?(2)設(shè)置不同的緩存失效時(shí)間
緩存擊穿:
指一個(gè)key非常熱點(diǎn),高并發(fā)集中訪問這個(gè)key,當(dāng)這個(gè)key在失效瞬間,仍然持續(xù)的高并發(fā)訪問穿破緩存。
解決方法:
在訪問key之前,采用setnx 來(lái)設(shè)置另一個(gè)短期key來(lái)鎖住當(dāng)前key的訪問,訪問結(jié)束后再刪除該短期key
關(guān)于redis的總結(jié)暫且寫到這里,還有好多關(guān)于redis的問題
2 linux
(1)linux常見的信號(hào)
Ctrl + c? → 2) SIGINT(終止/中斷)? "INT" ----Interrupt
Ctrl + z? → 20) SIGTSTP(暫停/停止)? "T" ----Terminal 終端。
?Ctrl + \? → 3) SIGQUIT(退出)
除0操作?? → 8) SIGFPE (浮點(diǎn)數(shù)例外)????? "F" -----float 浮點(diǎn)數(shù)。
非法訪問內(nèi)存? → 11) SIGSEGV (段錯(cuò)誤)
?總線錯(cuò)誤? → 7) SIGBUS???
(2) linux查看進(jìn)程占用內(nèi)存的命令 top
(3)linux 查看cpu占用資源情況的命令 top
(4)僵尸進(jìn)程:子進(jìn)程退出 之后,還殘留一部分的PCB資源。父進(jìn)程未對(duì)其進(jìn)行回收
(5)僵尸進(jìn)程存在的意義:父進(jìn)程可以知道子進(jìn)程結(jié)束時(shí)的狀態(tài)信息。
(6)linux 查看連接數(shù)
?a? 查看網(wǎng)絡(luò)狀態(tài) netstat -an
b 查看 8080端口連接的情況? ?netstat -an|grep 80
c 統(tǒng)計(jì)80端口的連接數(shù) netstat -nat | grep -i "80" |wc -l
d 統(tǒng)計(jì)httpd協(xié)議連接數(shù)?ps?-ef?|?grep httpd?|?wc?-l
e? 統(tǒng)計(jì)已連接上的,狀態(tài)為“established”??netstat?-na?|?grep ESTABLISHED?|?wc?-l
f? ?查出每個(gè)IP地址連接數(shù)
netstat?-na?|?grep ESTABLISHED?|?awk?'{print$5}'?|?awk?-F?:?'{print$1}'?|sort?|uniq?-c?|?sort?-r
(7) ping 百度發(fā)送icmp包
(8)路由是怎么傳遞的??
(9)TCP與UDP的區(qū)別
? TCP: 面向連接的可靠的數(shù)據(jù)包傳遞
數(shù)據(jù)穩(wěn)定、速率穩(wěn)定、流量穩(wěn)定
使用場(chǎng)景:大文件,重要文件的傳輸
UDP :無(wú)連接的不可靠的報(bào)文傳遞;
效率高,速度快,不穩(wěn)定
使用場(chǎng)景,對(duì)實(shí)時(shí)性要求比較高的,視頻會(huì)議和視頻電話。
3 C++
(1)map的底層是什么?為什么
map的底層是紅黑樹,為什么用紅黑樹;紅黑樹在查找、插入、刪除的復(fù)雜度都是o(logn)且性能穩(wěn)定。
(2)c++內(nèi)存的模型
操作系統(tǒng)將C語(yǔ)言代碼分為四個(gè)區(qū):
1、棧區(qū)
2、堆區(qū)
3、全局區(qū)
4、程序代碼區(qū)
(3)malloc的原理
a 當(dāng)開辟的空間小于 128K 時(shí),調(diào)用 brk()函數(shù),malloc 的底層實(shí)現(xiàn)是系統(tǒng)調(diào)用函數(shù) brk(),其主要移動(dòng)指針 _enddata(此時(shí)的 _enddata 指的是 Linux 地址空間中堆段的末尾地址,不是數(shù)據(jù)段的末尾地址)
b 當(dāng)開辟的空間大于 128K 時(shí),mmap()系統(tǒng)調(diào)用函數(shù)來(lái)在虛擬地址空間中(堆和棧中間,稱為“文件映射區(qū)域”的地方)找一塊空間來(lái)開辟。
(4)堆的概念
a 堆中某個(gè)節(jié)點(diǎn)的值總是不大于或不小于其父節(jié)點(diǎn)的值;
b 堆總是一棵完全二叉樹。
4 算法題
1 LRU 已經(jīng)寫過答案
2 循環(huán)移動(dòng)K個(gè)元素
3 堆排序
?
?
? ??
總結(jié)
- 上一篇: LRU缓存淘汰策略
- 下一篇: c语言经典程序100txt例,C语言经典