HashMap面試題
HashMap與HashTable的區(qū)別
1.HashMap線程不安全 HashTable 線程是安全的采用synchronized
2.HashMap允許存放key 為null HashTable 不允許存放key 為null
3.在多線程的情況下,推薦使用ConcurrentHashMap 線程安全 且效率非常高
HashMap底層是如何實現(xiàn)的
在HashMap1.7版本中底層是基于數(shù)組+鏈表實現(xiàn)的,如果發(fā)生Hash沖突概率
比較大,會存放到同一個鏈表中,鏈表如果過長 會從頭查詢到尾部 效率非常低。
所以在HashMap1.8版本 (數(shù)組容量>=64&鏈表長度大于8) 就會將該鏈表轉(zhuǎn)化紅黑樹。
HashMap根據(jù)Key查詢時間復(fù)雜度?
1.Key沒有產(chǎn)生沖突 時間復(fù)雜度是為o(1); 只需要查詢一次
2.Key產(chǎn)生沖突 采用鏈表存放則為O(N) 從頭查詢到尾部
3.key產(chǎn)生沖突采用紅黑樹存放則為O(LogN)
HashMap底層是有序存放的嗎?
是無序的,因為Hash 算法是散列計算的 沒有順序,如果需要順序
可以使用LinkedHashMap集合采用雙向鏈表存放。
HashMap7擴容產(chǎn)生死循環(huán)問題有了解過嗎?
其實這個JDK官方不承認(rèn)這個bug,因為HashMap本身是線程不安全的,不推薦在
多線程的情況下使用,是早期阿里一名員工 發(fā)生在多線程 的情況下使用HashMap1.7 擴容會發(fā)生死循環(huán)問題,因為HashMap1.7 采用頭插入法 后來在在HashMap1.8 改為尾插法 。
如果是在多線程的情況下 推薦使用ConcurrentHashMap
HashMap Key 為null 存放在 什么位置
存放在數(shù)組 index為0的位置。
ConcurrentHashMap 底層是如何實現(xiàn)?
1.傳統(tǒng)方式 使用HashTable保證線程問題,是采用synchronized鎖將整個HashTable中的數(shù)組鎖住,
在多個線程中只允許一個線程訪問Put或者Get,效率非常低,但是能夠保證線程安全問題。
2.多線程的情況下 JDK官方推薦使用ConcurrentHashMap
ConcurrentHashMap 1.7 采用分段鎖設(shè)計 底層實現(xiàn)原理:數(shù)組+Segments分段鎖+HashEntry鏈表實現(xiàn)
大致原理就是將一個大的HashMap 分成n多個不同的小的HashTable
不同的key 計算index 如果沒有發(fā)生沖突 則存放到不同的小的HashTable中 ,從而可以實現(xiàn)多線程
同時做put操作,但是如果多個線程同時put操作 key 發(fā)生了index沖突落到同一個小的HashTable中
還是會發(fā)生競爭鎖。
3.ConcurrentHashMap 1.7 采用 Lock鎖+CAS樂觀鎖+UNSAFE類 里面有實現(xiàn) 類似于synchronized
鎖的升級過程。
4.ConcurrentHashMap 1.8版本 put操作 取消segment分段設(shè)計 直接使用Node數(shù)組來保存數(shù)據(jù)
index沒有發(fā)生沖突使用cas鎖 index 如果發(fā)生沖突則 使用 synchronized
分布式解決方案
請問你在生產(chǎn)環(huán)境中,如何搜索日志的呢?
回答:
- 傳統(tǒng)的方式采用tail 搜索文件日志,如果服務(wù)器是集群的
使用tail 指令搜索日志效率是非常低; - 所有我們構(gòu)建分布式ELK+Kafka采集日志 ,統(tǒng)一將我們的日志輸出到
ES中,通過可視化界面查詢。
3.或者整合skywalking監(jiān)控服務(wù)報警,直接通過skywalking定位服務(wù)追蹤鏈
報錯信息。
4.在一些較大的互聯(lián)網(wǎng)企業(yè)中,保證服務(wù)器端安全性,生產(chǎn)環(huán)境一般是不允許直接連接生產(chǎn)環(huán)境
服務(wù)器,而是通過日志采集系統(tǒng)查看日志。
生產(chǎn)環(huán)境中,你遇到了報錯的問題 你是如何定位的?
回答:
- 傳統(tǒng)的方式 在生產(chǎn)環(huán)境中遇到報錯問題,我們是通過搜索日志的方式,排查具體的錯誤。
2.采用aop形式攔截系統(tǒng)錯誤日志,在將這些錯誤日志調(diào)用微信公眾號接口 主動告訴給我們的開發(fā)人員
生產(chǎn)環(huán)境發(fā)生了故障。 - 我們公司采用apm系統(tǒng) skywalking ,監(jiān)控整個微服務(wù) 如果服務(wù)在一段時間
內(nèi)發(fā)生了故障或者報錯 會主動調(diào)用微信模板接口通知給開發(fā)人員 生產(chǎn)環(huán)境發(fā)生了故障。在通過skywalking 追蹤 鏈可以直接查看到具體的錯誤信息內(nèi)容
調(diào)用接口的時候,如果服務(wù)器端一直沒有及時響應(yīng) 怎么解決?
1.如果調(diào)用接口發(fā)生了響應(yīng)延遲:是因為我們http請求是采用同步的形式,基于請求與響應(yīng)模型如果服務(wù)器端沒有及時響應(yīng)給客戶端,客戶端就會認(rèn)為接口超時,接口發(fā)生了超時客戶端會不斷重試 ,重試的過程中 會導(dǎo)致 冪等性問題
冪等性問題(需要保證業(yè)務(wù)唯一性。)
2.如果接口響應(yīng)非常慢,就需要對代碼做優(yōu)化例如 加上緩存減輕db查詢壓力、減少GC回收頻率
2.如果接口代碼在怎么優(yōu)化 就是執(zhí)行非常耗時時間,因為采用mq異步的形式 不能夠使用 同步形式。
舉例子:接口代碼里面 需要調(diào)用非常多接口 在響應(yīng)客戶端
接口代碼:
1.調(diào)用征信報告接口---15s-30s
生產(chǎn)環(huán)境服務(wù)器宕機,如何解決呢?
- 我們公司生產(chǎn)環(huán)境,會對我們服務(wù)器 實現(xiàn)多個節(jié)點集群,如果某臺服務(wù)器
發(fā)生了宕機 會自動實現(xiàn)故障轉(zhuǎn)移,保證服務(wù)的高可用。
- 如果服務(wù)器宕機 我們可以在服務(wù)器上安裝keepalived 監(jiān)聽java進(jìn)程,如果該java進(jìn)程發(fā)生了宕機 會自動嘗試重啟該java進(jìn)程,這是屬于軟件層面。如果是物理機器比如關(guān)機了,可以使用硬件方式自動重啟服務(wù)器 例如向日葵
3.如果服務(wù)器發(fā)生了宕機,嘗試重啟n多次還是失敗,我們可以使用容器快速動態(tài)的實現(xiàn)擴容(docker或者k8s)
4.重啟該服務(wù),如果重啟多次還是失敗 則會發(fā)送短信模板的形式通知給運維人員。
注意:千萬不要回答 直接重啟服務(wù)器端。
SpringCloud
為什么不選擇dubbo?卻選擇SpringCloud?
- dubbo 屬于RPC框架;
- SpringCloud 不屬于RPC框架,屬于微服務(wù)全家桶框架,提供非常多
在分布式微服務(wù)架構(gòu)中遇到難題
2.1服務(wù)治理---nacos eureka zk
2.2分布式配置中心 nacos springcloud config 攜程阿波羅
3.3分布式事務(wù) lcn(被淘汰)、seata
3.4服務(wù)追蹤 zipkin /skwalking
3.5服務(wù)保護(hù) hystry、sentinel
3.6微服務(wù)網(wǎng)關(guān) zuul gateway
....
feign客戶端 rpc框架 類似于 dubbo
dubbo rpc框架 底層 netty 封裝dubbo 協(xié)議
整合分布式解決方案---自己單獨整合 單一功能
而springcloud 提供了成熟一套微服務(wù)解決方案。
dubbox 屬于當(dāng)當(dāng)網(wǎng)提供 http協(xié)議接口
feign 調(diào)用接口 http協(xié)議
開放平臺(阿里、騰訊) http協(xié)議 跨平臺
dubbo與feign 都是面向接口 調(diào)用 底層思想原理都是相同。
底層采用動態(tài)代理技術(shù)。
服務(wù)正在發(fā)布中?如何不影響用戶使用?
服務(wù)正在發(fā)布中,該jar中正在啟動...
客戶端訪問的時候,一直阻塞等待。
1.使用nginx 故障轉(zhuǎn)移即可。
2.灰度發(fā)布 先發(fā)布一小部分 如果沒有問題 在讓所有用戶都可以訪問。
灰度發(fā)布 nginx+nacos gateway+nacos(推薦)
對方調(diào)用你接口響應(yīng)比較慢?你會怎么排查?
項目搭建服務(wù)追蹤監(jiān)控系統(tǒng)
1.zipkin /skwalking 通過平臺形式可以查詢該接口響應(yīng)速度時間。
對方調(diào)用你接口響應(yīng)比較慢 多個維度思考?
帶寬→服務(wù)處理(cpu)→數(shù)據(jù)庫或者Redis→網(wǎng)絡(luò)IO操作(例如調(diào)用別人接口)
1.走外網(wǎng)傳輸數(shù)據(jù) 會有帶寬限制呢
2.請求如果達(dá)到服務(wù)端,服務(wù)足夠線程處理請求 如果服務(wù)器沒有足夠的線程
處理該請求? 導(dǎo)致客戶端會阻塞等待?
解決辦法:
1.調(diào)整最大線程數(shù)
2.調(diào)整最大線程數(shù) 治標(biāo)不治本,對接口做限流操作 例如服務(wù)器端沒有足夠
線程處理的時候(策略服務(wù)熔斷 降級 限流策略。)
3.服務(wù)cpu處理性能(多核cpu) 體現(xiàn)多線程同時處理 降低cpu上下文切換的次數(shù)。
如果發(fā)生了上下文切換會導(dǎo)致其他的線程 會短暫阻塞 有需要從新被cpu調(diào)度。
4.判斷sql語句查詢是否比較慢、做mysql調(diào)優(yōu) 快速響應(yīng)結(jié)果
5.網(wǎng)絡(luò)IO操作(例如調(diào)用別人接口)代碼在怎么優(yōu)化還是比較慢,將耗時的操作
采用異步的形式處理 例如多線程(消耗cpu的資源) 建議使用MQ。
開發(fā)者不小心刪除了生產(chǎn)環(huán)境數(shù)據(jù)?怎么恢復(fù)呢?
1.正常的情況下 在生產(chǎn)環(huán)境中 沒有delete或者rm -rf 通過update
隱藏的形式, 后期淘汰策略刪除。
2.構(gòu)建mysql主從集群環(huán)境 可以通過備份節(jié)點恢復(fù)數(shù)據(jù),一主一從。
3.如果執(zhí)行delete 我們是可以通過binlog 快速恢復(fù)數(shù)據(jù)。
你在開發(fā)過程中,遇到哪些難題?你是怎么解決的呢
如果在面試的過程中被面試官問到:你在開發(fā)過程中,遇到哪些難題?
不要答:空指針異常、常見錯誤異常。
遇到問題→你是如何分析的?→如何排查的?→最終是怎么解決的?
1.分布式事務(wù)
2.分布式冪等
例如 我們公司提供了一個接口,被其他公司進(jìn)行調(diào)用。
他的公司在調(diào)用我們公司接口的過程中,我們的接口響應(yīng)超時了,
最終觸發(fā)了客戶端重試了,重試的過程當(dāng)中請求的參數(shù)都是相同的,導(dǎo)致我們接口
會重復(fù)執(zhí)行業(yè)務(wù)邏輯。
解決辦法: 全局id 業(yè)務(wù)上防重復(fù)、 在db層面去重復(fù) 例如 創(chuàng)建唯一約束
3.定時任務(wù)調(diào)度
例如:我們項目在生產(chǎn)環(huán)境中做定時任務(wù),如果集群的情況下 定時任務(wù)重復(fù)執(zhí)行。
解決該問題
1.在打jar包的時候 加上一個開關(guān) 只讓一個jar包執(zhí)行定時任務(wù)
2.整合分布式任務(wù)調(diào)度平臺 xxljob 最終分片執(zhí)行 定時任務(wù)集群的執(zhí)行
定時任務(wù)1 【】跑批 1-10萬 定時任務(wù)2 11-20萬
4.數(shù)據(jù)同步延遲問題
我們公司 使用canal 解決mysql與redis+kafka 數(shù)據(jù)同步問題
發(fā)現(xiàn)就是在并發(fā)的情況下同步非常延遲,我們整合kafka分區(qū)模型
根據(jù)每張表都有自己獨立的topic主題,每個topic 主題有自己獨立
分區(qū) 每個分區(qū)有自己獨立消費者 ,解決消息順序一致性問題。
6.安全性問題
7生產(chǎn)環(huán)境發(fā)生cpu飆高、內(nèi)存泄漏
.......真實業(yè)務(wù)場景當(dāng)中遇到難題