webpack4.0各個擊破(3)—— Assets篇
789
2022-05-29
一、前言
最近博主也是歷盡千辛萬苦換了份工作,每次換之前不找點面試題看似乎就沒自信一樣。。奈何網上有些面試題是比較老套的,所以這里重新總結一份2020年的,題目是有些是博主自己不熟悉的點,有些是boss直聘論壇找到的,有的是朋友的面試經歷,僅作為記錄。
以下面試題部分帶有博主自己學習時候寫下的答案,也許并不全或者并不正確,大家只看題就好,希望能對大家有所幫助。
二、零散的知識點
1、laravel相關面試題
(1)什么是服務提供者
(2)什么是容器,什么是依賴注入,控制反轉 (ok)
(3)laravel的流程
(4)laravel的路由機制 (從index.php到router的web.php,然后找到對應的控制器和方法)
2、一個人余額有10塊,買了一個8塊的東西,同時點擊100次,那這個訂單會不會重復,并說出解決方案
(1)隔離級別串行化?
(2)RR隔離級別+間隙鎖next-key
(3)redis的hash保證唯一性,隨后再同步db
3、zookeeper是什么
配置管理,名字服務,提供分布式同步以及集群管理。目前HBase使用它來維護集群的配置信息,Kafka使用Zookeeper來維護broker的信息
zookeeper使用zab協議實現強一致性,1、選舉出leader;2、同步節點之間的狀態達到數據一致;3、數據的廣播
4、rpc是什么?
答:RPC就是要像調用本地的函數一樣去調遠程函數
主要作用:
(1)解決分布式系統中,服務之間的調用問題
(2)遠程調用時,要能夠像本地調用一樣方便,讓調用者感知不到遠程調用的邏輯。
原理步驟:
(1)call_id映射:客戶端和服務端維護一個類似于的表,對應方法id和方法名。當遠程調用的時候,需要的傳遞id過去,
這樣服務端才能知道你要調用哪個方法。一般是一個哈希表
(2)序列化和反序列化。由于傳輸都是二進制的,所以傳輸前要序列化,收到數據要反序列化
(3)網絡傳輸,一般使用tcp協議,也可以是udp
場景:
5、分布式面臨的首要問題就是nginx的負載均衡
(1)什么是負載均衡
(2)負載均衡實踐
1、輪詢
2、權重
3、綁定ip.ip_hash算法。 可以解決session不同步問題,但是均衡性差。比如高校等局域網ip一致,不能有效區分
(3)四層,七層負載均衡?
四層:IP+端口的負載均衡
七層:基于URL等應用層信息,可以分析應用層的信息,如HTTP協議URI或Cookie信息
6、nginx面試題
Nginx 常用命令有哪些?
需要熟悉:nginx -t ,nginx -s stop 之類
Nginx 返回 502 錯誤的可能原因?
(1)進程數不夠,需要更改配置
(2)php-fpm自動重啟問題
(3)php-fpm請求超時
(4)是否有大量數據庫句柄沒釋放,導致進程卡住
Nginx的504錯誤一般是fastcgi的超時配置方面有問題
正向代理和反向代理之間的區別是什么?
正向代理:代理端代理的是客戶端反向代理:代理端代理的是服務端
什么是負載均衡?
代理服務器將接收的請求均衡的分發到各服務器
(1)session同步問題
1、使用cookies (戶端把cookie禁掉了的話,那么session就無從同步)
2、存儲到數據庫 (增加數據庫的負擔。而且數據庫讀寫速度較慢,不利于session的適時同步)
3、存到memcache或者redis緩存(常用)
(2)一般是lvs做4層負載;nginx做7層負載(也能做4層負載, 通過stream模塊)
七層負載均衡基本都是基于http協議的,適用于web服務器的負載均衡。(nginx)
四層負載均衡主要是基于tcp協議報文,可以做任何基于tcp/ip協議的軟件的負載均衡。(haproxy、LVS)
7、swoole必須要學習下
(1)
https://blog.csdn.net/DarkAngel1228/article/details/82053360 (swoole的一些基礎概念)
新建laravel項目來使用swoole做一些簡單的demo
(2)easyswoole的文檔
http://noobcourse.php20.cn/NoobCourse/Introduction.html#%E6%96%B0%E6%89%8B%E5%85%A5%E9%97%A8
(3)swoole的文檔
http://wiki.swoole.com/wiki/page/487.html
(4)共享變量
(5)協成
(6)go的channel
8、linux查看性能調試等命令
top/iostat/vmstat/free/strace/tcpdump 等監控工具
top和iostat是查看cpu和硬盤的使用情況
strace是可以調試程序的,顯示系統調用的步驟
free是查看內存的使用情況的
9、epoll是干什么的 (此處僅作為了解)
(1)select,poll,epoll都是IO多路復用的機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程序進行相應的讀寫操作。
(2)select,poll,epoll本質上都是同步I/O,因為他們都需要在讀寫事件就緒后自己負責進行讀寫,也就是說這個讀寫過程是阻塞的,而異步I/O則無需自己負責進行讀寫,異步I/O的實現會負責把數據從內核拷貝到用戶空間。
(3)epoll可以理解為event poll,不同于忙輪詢和無差別輪詢,epoll會把哪個流發生了怎樣的I/O事件通知我們。所以我們說epoll實際上是事件驅動(每個事件關聯上fd)的,此時我們對這些流的操作都是有意義的。(復雜度降低到了O(1))
(4)表面上看epoll的性能最好,但是在連接數少并且連接都十分活躍的情況下,select和poll的性能可能比epoll好,畢竟epoll的通知機制需要很多函數回調。
(5)epoll是線程安全的
(6)nginx和epoll的關系?
https://www.zhihu.com/question/63193746
https://segmentfault.com/q/1010000010427586
10、部分面試題鏈接
https://blog.csdn.net/arvesri70299/article/details/101695117
https://blog.csdn.net/dongdonggegelovezcj/article/details/101347644
https://blog.csdn.net/lcli2009/article/details/82825890 (可以看看他的卡夫卡)
https://blog.csdn.net/lxw1844912514/article/details/100028857
https://blog.csdn.net/yilukuangpao/article/details/90234348 算法題
https://zhuanlan.zhihu.com/p/147569045?utm_source=wechat_session 面試題
三、redis和mysql相關
作為一名后端人員,mysql,Redis?永遠是繞不開的。。
1、redis的五大數據類型的使用場景
https://blog.csdn.net/fenghuoliuxing990124/article/details/84983694
(1)string 存儲字符串,場景是簡單緩存
(2)list 隊列,場景是模擬隊列,秒殺,,回復等有一些先后順序的
(3)set 無序的唯一列表, 場景:抽獎,去重,好友圈,共同好友之類的
(4)SortedSet 有序的 場景:排行榜,各種熱度排行
(5)hash 參考:https://www.cnblogs.com/pangzizhe/p/10657801.html 購物車
2、redis是單線程的嗎,可以多線程嗎? (可以多線程,redis6.0可以了)
優點:
(1) 絕大部分請求是純粹的內存操作(非常快速)
(2) 采用單線程,避免了不必要的上下文切換和競爭條件
(3) 非阻塞IO - IO多路復用(select,poll,epoll)
(4)高效的數據結構
(5)value大小:redis最大可以達到1GB,而memcache只有1MB
3、mysql的樂觀鎖和悲觀鎖
(1)樂觀鎖是不加鎖的方式,通過添加版本號實現。比如A事務要修改數據,此時版本號為1。B事務也要修改 ,此時讀取版本號也是1.
等A事務修改的時候,此時讀取version,當version=1的時候才更新version=2。 B事務要更新的時候,再次讀取version發現version=2了,
和初始讀取的version=1對不上,因此就會更新失敗。
可以理解為:比如當前版本是1,A和B獲取到version=1,此時更新,那A和B的更新條件都為“version = 1”,如果A先提交了,
此時表中該條數據version已經被A更新為2,B再提交,發現不滿足“version=1”,所以無法更新,排他異常
(2)樂觀鎖只能防止臟讀后數據的提交,不能解決臟讀。
(3)悲觀鎖包括:共享鎖,排它鎖。共享鎖是其它事務可以讀但是不能寫。排他鎖是只有自己得事務有權限對此數據進行讀寫
(4)事務A加上排它鎖,事務B在不加排它鎖的情況下,是可以select數據的。
(5)樂觀鎖適合讀比較多,寫比較少的場景。 悲觀鎖適合寫比較多的場景
(6)樂觀鎖的時候,當事務B更新不成功的時候,會繼續重試。如果重試的多了,會造成大量資源消耗,然而不如使用悲觀鎖了
4、測試redis秒殺
(1)通過redis的list類型,先創建一個列表,插入10條庫存。用戶搶購的時候,就從這10個庫存里面取,取完為止。這里因為pop操作是原子性的,可以防止超賣。
(2)如何保證每個用戶都只能搶到一個呢?
采用hash的算法。首先庫存還是存在列表里面。
hash部分,設置一個key,key中對應的屬性名和屬性值都是user_id。比如 test_key:1:1
在實際搶購的時候,通過hset($test_key, $user_id, $user_id) 判斷返回,當user_id不存在hash表的時候,則hash表會自動創建并返回1。當存在這個user_id的時候,會返回0
當返回1的時候,代表是新用戶,此時可以減庫存,通知存入用戶到hash中。
當返回0的時候,代表用戶重復,此時提示已經搶購過了
5、redis的分布式鎖setnx
(1)先拿setnx來爭搶鎖,搶到之后,再用expire給鎖加一個過期時間防止鎖忘記了釋放
(2)可以通過set命令,直接設置nx并設置過期時間,防止出現當拿到鎖之后,redis掛掉導致來不及設置過期時間的問題,鎖一直釋放不了
(3)keys讀取所有的鍵,會導致進程堵塞。可以用scan無阻塞的提取出指定模式的key列表,scan獲取的數據可能會重復,需要手動去重
(4)RDB持久化也分兩種:SAVE(阻塞)和BGSAVE(非阻塞,一般用這個)。 AOF的話,一般是1s同步一次,如果每條記錄都同步的話,會非常損耗性能
(5)redis同步機制:(1)master使用bgsave生成rbd快照,同時后續的修改等操作都會記錄到內存。快照生成之后,同步給從節點
(2)slave同步完快照,通知master,把后續的修改記錄都同步到從節點即可
6、用redis使用場景?
hash實現購物車:
(1)每個用戶的購物車作為一個hash表,user_id作為key,商品id作為field,商品數量作為value.
(2)hset添加商品,hincrby增加數量,hlen為商品總量。hdel刪除商品,hgetall獲取所有商品
list實現隊列,和棧:
(1)棧:LPUSH + LPOP (左側進,左側出。即先進后出)(棧是先進后出,類似于箱子里放東西)
(2)先進先出隊列:LPUSH + RPOP (左側進,右側出)
(3)先進先出,阻塞隊列:LPUSH+BRPOP :brpop意思 block right pop 阻塞式右側出隊
brpop(['queue1', 'queue2'], 0),當給定多個 key 參數時,按參數 key 的先后順序依次檢查各個列表,彈出第一個非空列表的頭元素
(4)先進先出,等待阻塞隊列: Lpush + Brpoplpush :
Brpoplpush 命令從列表中取出最后一個元素,并插入到另外一個列表的頭部; 如果列表沒有元素會阻塞列表直到等待超時或發現可彈出元素為止。
相當于減少無用的輪詢,而且每次消費隊列時候,還進行了備份,比較安全
(5)優先級隊列設計:
1、普通的隊列,碰到優先級高的,就從右側插入,這樣會優先消費。(缺點:連續多個優先級任務的話,會先進后出,無法保證順序)
2、使用brpop來阻塞的讀:brpop(['queue1', 'queue2'], 0),先讀優先級高的隊列,再讀優先級低的隊列
3、很多優先級的話,只設置一個隊列,并保證它是按照優先級排序號的。然后通過二分查找法查找一個任務合適的位置,并通過 lset 命令插入到相應的位置。
list使用場景:
(1)微信公眾號,后臺為每個訂閱用戶Lpush一條消息,id為key,文件id集合為value,查看的時候,只需要Lrange指定的消息即可
四、BOSS論壇上遇到的面試題
1、滴滴的面試題
(1)mysql保存在磁盤的數據格式是什么 ,然后又是如何變異成我們能識別的數據格式?
二進制的吧
(2)mysql索引在內存中以什么格式保存?
(3)B+樹是怎樣的樹狀,為什么會這樣
2、一個10年經驗大哥遇到的題
(1)什么是緩存穿透,什么是緩存擊穿,如何解決
緩存穿透是:不論redis還是數據庫,都沒有這個數據
(1)布隆過濾器 (4.0之后布隆過濾器作為一個插件加載到Redis Server中,就會給Redis提供了強大的布隆去重功能。)
主要是add和exists命令,就是判斷某個key在不在這個集合中
(2)判斷不存在,就吧空結果寫入到緩存。設置比較短的過期時間即可
緩存擊穿:redis沒有,mysql有
(1)利用鎖,先獲取這個key的鎖,然后同步db數據到緩存。沒獲取到鎖的時候,就先等待
(2)epoll和select的區別是什么 (ok)
(3)單機redis與集群redis
1、集群redis解決了單機redis宕機問題
2、解決了單機性能不足,內存不足的情況
3、同時借用主從,也解決了讀寫之間的分離問題
4、集群比較難以維護
(4)為什么memchace只支持kv,而redis支持類型這么多
1、這是由于redis高效的數據結構。len:用于記錄buf中已使用空間的長度,free:buf中空閑空間的長度,buf[]:存儲實際內容
2、由數據類型來記錄數據是什么方式存儲的
(5)redis的過期策略是什么
整體數據的LRU,random等
有過期時間的LRU,randow等
(6)如何快速定位php程序運行慢的地方
(1)打開php-fpm慢日志:slow_log
(2)使用xdebug來跟蹤程序
(3)phptrace跟蹤 (類似于linux下的trace命令,只不過一個是追蹤系統調用,一個是追蹤程序調用。也是命令行調用,需要輸入php-fpm的pid)
3、其他的面試題
(1)談談反射的優缺點
應用場景:插件,框架開發等
優點:可以通過反射類,獲取被反射類的屬性,方法等
(2)如何優化in_array的性能
1、array_flip: key,value,反轉之后,使用isset()
2、implode連接成字符串,直接用strpos判斷(php里面字符串取位置速度非常快,尤其是在大數據量的情況下)
(3)如何處理臟讀
1、隔離級別設置成RC及以上
(4)大文件讀取和存儲
1、yield生成器,一次讀取一行,返回的是生成器對象,可以防止內存溢出
2、php自帶的SplFileObject類去讀取,可以指定行數,指定位置讀取開始讀取
3、復制大文件的話還是用數據流,stream_copy_to_stream
(5)b樹和b+樹的異同,B+樹的葉子節點是雙向鏈表嗎
1、是的葉子也是根據頁中用戶記錄的主鍵大小順序排成一個雙向鏈表
(6)redis哪些操作和方法是原子性的
1、有種說法是,redis的單個命令都是原子性的
2、還有人說,pop,push是原子性的,而len這種不是原子性的,所以判斷庫存會用pop去減去庫存,而不是用len判斷
(7)mysql分區表和數據統計問題
分區和分表不一樣,分區是把一個表,通過Range、List、Hash、Key,其中Range比較常用 等方法,分成不同的磁盤文件存儲。
(8)yield
1、返回生成器對象,可以使用foreach進行迭代。比如讀取文件的時候,返回的是一行一行的數據,
就避免了之前容易出現的數組內存溢出情況
2、占用內存極小,近似為一行數據的內存大小
(9)二分查找
(10)解決卡夫卡的rebalance問題,還有事務的使用方法
1、Rebalance本身是Kafka集群的一個保護設定,用于剔除掉無法消費或者過慢的消費者
2、當消費數據過慢,或者比較耗時,都會觸發這個重平衡
3、壞處
(1)數據重復消費: 消費過的數據由于提交offset任務也會失敗,在partition被分配給其他消費者的時候,會造成重復消費,數據重復且增加集群壓力
(2)影響集群速度
(3)數據不能及時消費,會累積lag,在Kafka的TTL之后會丟棄數據
(4)頻繁的Rebalance反而降低了消息的消費速度,大部分時間都在重復消費和Rebalance
(11)redis的分布式鎖不適合高并發場景,如何優化
(1)比如悲觀鎖,分布式鎖,樂觀鎖,隊列串行化,異步隊列分散,Redis原子操作,等等,很多方案,我們對庫存超賣有自己的一整套優化機制
(2)問題:分布式鎖一旦加了之后,對同一個商品的下單請求,會導致所有客戶端都必須對同一個商品的庫存鎖key進行加鎖。不適合高并發,因為這個類似于串行化
(3)解決方案:
1、分段加鎖。就是1000個庫存,你分成20個key的庫,用戶請求隨機分配到這20個庫,這樣分開加鎖提升性能。(庫存不足則記得手動釋放鎖,并重新選擇其他庫)
(12)說一下悲觀鎖和互斥鎖的具體區別
1、互斥鎖、自旋鎖、讀寫鎖都屬于悲觀鎖,悲觀鎖認為并發訪問共享資源時,沖突概率可能非常高,所以在訪問共享資源前,都需要先加鎖。
2、互斥鎖和自旋鎖都是最基本的鎖
3、互斥鎖加鎖失敗后,線程會釋放 CPU ,給其他線程;自旋鎖加鎖失敗后,線程會忙等待,直到它拿到鎖;
(13)你pop了redis里的數據,最后進程掛了怎么辦
1、redis掛了的話,數據從內存溢出,但是沒有持久化到磁盤,這時候就要看持久化的策略了,是aof還是rdb,是一秒一寫還是每次命令都寫,然后恢復數據
2、綜合使用AOF和RDB兩種持久化機制,用AOF來保證數據不丟失,作為數據恢復的第一選擇; 用RDB來做不同程度的冷備,在AOF文件都丟失或損壞不可用的時候,還可以使用RDB來進行快速的數據恢復
3、如果是php進程被kill了。可以通過信號機制,重新push
(14)一句話描述binlog,undo log等
1、redo log是為了持久化數據,在數據還沒從內存刷新到磁盤時,如果發生故障,可讀取該日志持久化到磁盤。
2、binlog 是為了復制和恢復數據的,即Mysql從服務器可以讀取主服務器的binlog復制數據,數據庫數據丟失,也可以讀取binlog恢復
3、undo log是為了保證原子性的。(為了滿足事務的原子性,在操作任何數據之前,首先將數據備份到一個地方(這個存儲數據備份的地方稱為Undo Log)。然后進行數據的修改。如果出現了錯誤或者用戶執行了ROLLBACK語句,系統可以利用Undo Log中的備份將數據恢復到事務開始之前的狀態。)
五、部分公司面試題
1、甲公司
(1)laravel相關面試題
服務提供者是什么? :服務容器就是管理類的依賴和執行依賴注入的工具,它可以為你的類庫提供一套可以重用的實例化方案。
IoC 容器是什么?
(2)vue基礎面試題
(3)談談你對閉包的理解
1、通過匿名函數實現,一般是普通函數中調用匿名函數,返回數據。匿名函數也可以作為參數傳遞給普通函數
2、閉包要使用外界的變量,則需要使用use關鍵字
(4)什么是CSRF攻擊?XSS攻擊?如何防范
CSRF:跨站請求偽造 。 一般是token驗證的方案
XSS:跨域腳本攻擊。 一般是對輸入進行encode轉義和過濾
sql注入: (1)pdo的預處理 (2)對用戶參數進行過濾轉義處理
ddos: (1 防火墻 (2)禁用過濾ip (3 使用CDN,提供一層緩沖,不會全部涌向服務器
2、乙公司
(1)設計模式
單例,工廠,觀察者模式
https://www.cnblogs.com/yueguanguanyun/p/9584501.html
(2)php代碼優化
函數
數組
釋放內存
定義方法,注意循環
(3)可以于yy的上線下線功能,長連接方面
長連接還是通過websocket最好,主要是swoole部分
3、丙公司
(1)redis集群相關
(2)mysql回表 (ok)
(3)php-fpm有沒有掛過,怎么處理的
1、503錯誤,一般是進程太多導致的。比如max_children的數量等
2、502錯誤,php或者php-fpm超時
3、504是nginx錯誤
4、至于什么錯誤,可以查看php-fpm的日志文件
5、通過配置max_request等配置,可以自動重啟php-fpm
(4)慢查詢有沒有通過改框架去優化
1、一般使用原生的sql多一些
2、下載laravel-debuger文件,看看慢在哪里了。也可以使用x-debug查看
(5)redis單機掛了怎么辦,有什么策略:(單機的問題就是內存不夠,處理能力有限,不能高可用)
(1)查詢前先ping一下,無響應就先去數據庫
(2)定時腳本輪詢,ping redis,錯誤了就報警出來
(3)給key設置過期時間,減小內存壓力,釋放部分內存出來
(4)掛了就重啟,通過持久化恢復數據。業務不忙的話可以先預熱,業務比較忙的話,就直接恢復redis
(6)es怎么用的
(1)存儲日志用的
(2)從傳統的關系型表設計,改為文檔json設計
(3)連表沒那么方便了,可以進行聚合查詢等
(7)redis問的比較多
(8)php的安全策略
1、文件系統安全(盡量不要用root權限,php權限也不能太高)
2、數據庫安全(防止sql注入等)
3、用戶數據安全(對用戶數據進行過濾,能防止xss和csrf)
4、線上環境安全(php配置關閉錯誤提示,關閉危險函數等)
(9)redis過期策略
定時過期:每個設置過期時間的key都需要創建一個定時器,到過期時間就會立即清除。該策略可以立即清除過期的數據,對內存很友好;但是會占用大量的CPU資源去處理過期的數據,從而影響緩存的響應時間和吞吐量。
惰性過期:只有當訪問一個key時,才會判斷該key是否已過期,過期則清除。該策略可以最大化地節省CPU資源,卻對內存非常不友好。極端情況可能出現大量的過期key沒有再次被訪問,從而不會被清除,占用大量內存。
定期過期:每隔一定的時間,會掃描一定數量的數據庫的expires字典中一定數量的key,并清除其中已過期的key。該策略是前兩者的一個折中方案。通過調整定時掃描的時間間隔和每次掃描的限定耗時,可以在不同情況下使得CPU和內存資源達到最優的平衡效果。
(10)內存淘汰策略:
noeviction:當內存不足以容納新寫入數據時,新寫入操作會報錯。
allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key。
allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key。
volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的key。
volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個key。
volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的key優先移除。
(11)一臺服務器可以安裝多個redis,主要通過修改端口號,修改配置文件路徑等實現,互不干擾即可
2020最后幾天了,奧利給,沖沖沖!
PHP Redis
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。