更新時間:2019-10-16 15:56:24 來源:動力節(jié)點 瀏覽29833次
今天動力節(jié)點java培訓(xùn)機構(gòu)小編為大家匯總了史上最全的中高級JAVA工程師面試題及答案,分別是java緩存技術(shù)面試題和java中的hashmap面試題,希望能夠幫助到正在找工作的中高級JAVA程序員,下面就隨小編一起來看看吧。
1.memcache的分布式原理
memcached 雖然稱為 “ 分布式 ” 緩存服務(wù)器,但服務(wù)器端并沒有 “ 分布式 ” 功能。每個服務(wù)器都是完全獨立和隔離的服務(wù)。memcached 的分布式,則是完全由客戶端程序庫實現(xiàn)的。這種分布式是 memcached 的最大特點。
2.memcache的內(nèi)存分配機制
如何存放數(shù)據(jù)到memcached緩存中?(memcache內(nèi)存分配機制)
Slab Allocator內(nèi)存分配機制:預(yù)先將內(nèi)存分配成數(shù)個slab倉庫,每個倉庫再切出不同大小的chunk,去適配收到的數(shù)據(jù)。多余的只能造成浪費,不可避免。 增長因子(Grace factor):一般而言觀察數(shù)據(jù)大小的變化規(guī)律設(shè)置合理的增長因子,默認(rèn)1.25倍. 太大容易造成浪費。memcached.exe -m 64 -p 11211 -f 1.25
如果有100byte的內(nèi)容要存儲,但122大小的倉庫的chunk用滿了怎么辦?
答:是并不會尋找更大倉庫的chunk來存儲,而是把122倉庫中的舊數(shù)據(jù)踢掉!
3.memcache的惰性失效機制
4.memcache緩存的無底洞現(xiàn)象
5.一致性Hash算法的實現(xiàn)原理
(1)Hash環(huán)
我們把232次方想成一個環(huán),比如鐘表上有60個分針點組成一個圓,那么hash環(huán)就是由232個點組成的圓。第一個點是0,最后一個點是232-1,我們把這232個點組成的環(huán)稱之為HASH環(huán)。
(2)一致性Hash算法
將memcached物理機節(jié)點通過Hash算法虛擬到一個虛擬閉環(huán)上(由0到232構(gòu)成),key請求的時候通過Hash算法計算出Hash值然后對232取模,定位到環(huán)上順時針方向最接近的虛擬物理節(jié)點就是要找到的緩存服務(wù)器。
假設(shè)有ABC三臺緩存服務(wù)器:我們使用這三臺服務(wù)器各自的IP進(jìn)行hash計算然后對232取模即:==**Hash(服務(wù)器IP)%232== 計算出來的結(jié)果是0到232-1的一個整數(shù),那么Hash環(huán)上必有一個點與之對應(yīng)。比如:
現(xiàn)在緩存服務(wù)器已經(jīng)落到了Hash環(huán)上,接下來我們就看我們的數(shù)據(jù)是怎么放到緩存服務(wù)器的?我們可以同樣對Object取Hash值然后對232取模,比如落到了接近A的一個點上:
那么這個數(shù)據(jù)理應(yīng)存到A這個緩存服務(wù)器節(jié)點上
所以,在緩存服務(wù)器節(jié)點數(shù)量不變的情況下,緩存的落點是不會變的。
但是如果B掛掉了呢? 按照hash且取模的算法,圖中3這個Object理應(yīng)就分配到了C這個節(jié)點上去了,所以就會到C上找緩存數(shù)據(jù),結(jié)果當(dāng)然是找不到,進(jìn)而從DB讀取數(shù)據(jù)重新放到了C上。
但是對于編號為1,2的Object還是落到A,編號為4的Object還是落到C,B宕機所影響的僅僅是3這個Object。這就是一致性Hash算法的優(yōu)點。
(3)Hash環(huán)的傾斜
前面我們理想化的把三臺memcache機器均勻分到了Hash環(huán)上:
但是現(xiàn)實情況可能是:
如果Hash環(huán)傾斜,即緩存服務(wù)器過于集中將會導(dǎo)致大量緩存數(shù)據(jù)被分配到了同一個服務(wù)器上。比如編號1,2,3,4,6的Object都被存到了A,5被存到B,而C上竟然一個數(shù)據(jù)都沒有,這將造成內(nèi)存空間的浪費。為了解決這個問題,一致性Hash算法中使用“虛擬節(jié)點”解決。
虛擬節(jié)點解決Hash環(huán)傾斜
“虛擬節(jié)點”是“實際節(jié)點”在hash環(huán)上的復(fù)制品,一個實際節(jié)點可能對應(yīng)多個虛擬節(jié)點。這樣就可以將ABC三臺服務(wù)器相對均勻分配到Hash環(huán)上,以減少Hash環(huán)傾斜的影響,使得緩存被均勻分配到hash環(huán)上。
6.hash算法平衡性
平衡性指的是hash的結(jié)果盡可能分布到所有的緩存中去,這樣可以使得所有的緩存空間都可以得到利用。但是hash算法不保證絕對的平衡性,為了解決這個問題一致性hash引入了“虛擬節(jié)點”的概念。虛擬節(jié)點”( virtual node )是實際節(jié)點在 hash 空間的復(fù)制品( replica ),一實際個節(jié)點對應(yīng)了若干個“虛擬節(jié)點”,這個對應(yīng)個數(shù)也成為“復(fù)制個數(shù)”,“虛擬節(jié)點”在 hash 空間中以 hash 值排列。“虛擬節(jié)點”的hash計算可以采用對應(yīng)節(jié)點的IP地址加數(shù)字后綴的方式。
例如假設(shè) cache A 的 IP 地址為202.168.14.241 。引入“虛擬節(jié)點”前,計算 cache A 的 hash 值:Hash(“202.168.14.241”); 引入“虛擬節(jié)點”后,計算“虛擬節(jié)”點 cache A1 和 cache A2 的 hash 值:
Hash(“202.168.14.241#1”); // cache A1 ?
Hash(“202.168.14.241#2”); // cache A2 ??
這樣只要是命中cacheA1和cacheA2節(jié)點,就相當(dāng)于命中了cacheA的緩存。這樣平衡性就得到了提高。
7.memcached與redis的區(qū)別
8.Redis的主從復(fù)制
9.Redis的部分復(fù)制過程
部分同步工作原理如下:
10.Redis的主從復(fù)制阻塞模式
11.Redis的數(shù)據(jù)持久化方式
Rdb快照和aof ?RDB快照:可以配置在n秒內(nèi)有m個key修改就做自動化快照方式 ?AOF:每一個收到的寫命令都通過write函數(shù)追加到文件中。更安全。
12.Redis的高可用部署方式
(1)哨兵模式
redis3.0之前的Sentinel哨兵機制,redis3.0之前只能使用一致性hash方式做分布式緩存。哨兵的出現(xiàn)主要是解決了主從復(fù)制出現(xiàn)故障時需要人為干預(yù)的問題。
(2)Redis哨兵主要功能
(3)Redis哨兵的高可用
原理:當(dāng)主節(jié)點出現(xiàn)故障時,由Redis Sentinel自動完成故障發(fā)現(xiàn)和轉(zhuǎn)移,并通知應(yīng)用方,實現(xiàn)高可用性
(4)哨兵如何判斷redis主從節(jié)點是否正常?
涉及兩個新的概念:主觀下線和客觀下線。
原理:基本上哪個哨兵節(jié)點最先判斷出這個主節(jié)點客觀下線,就會在各個哨兵節(jié)點中發(fā)起投票機制Raft算法(選舉算法),最終被投為領(lǐng)導(dǎo)者的哨兵節(jié)點完成主從自動化切換的過程。
(5)集群模式
redis3.0之后的容錯集群方式,無中心結(jié)構(gòu),每個節(jié)點保存數(shù)據(jù)和整個集群狀態(tài),每個節(jié)點都和其他所有節(jié)點連接,需要至少三個master提供寫的功能。
因此集群中至少應(yīng)該有奇數(shù)個節(jié)點,因此至少有三個節(jié)點,每個節(jié)點至少有一個備份節(jié)點,所以redis集群應(yīng)該至少6個節(jié)點。
每個Master有一個范圍的slot槽位用于寫數(shù)據(jù)。
13.Redis可以在線擴容嗎?zk呢
Reids的在線擴容,不需要重啟服務(wù)器,動態(tài)的在原始集群中添加新的節(jié)點,并分配slot槽。但是zk不能在線擴容,需要重啟,但是我們可以選擇一個一個重啟。
14.Redis高并發(fā)和快速的原因
缺點:無法發(fā)揮多核CPU性能
15.瀏覽器本地緩存的了解和使用
資源在瀏覽器端的本地緩存可以通過Expires和Last-Modified返回頭信息進(jìn)行有效控制。
(1)Expires告訴瀏覽器在該指定過期時間前再次訪問同一URL時,直接從本地緩存讀取,無需再向服務(wù)器發(fā)起http請求;
(2)當(dāng)服務(wù)器返回設(shè)置了Last-Modified頭,下次發(fā)起同一URL的請求時,請求頭會自動包含If-Modified-Since頭信息,服務(wù)器對靜態(tài)內(nèi)容會根據(jù)該信息跟文件的最后修改時間做比較,如果最后修改時間不大于If-Modified-Since頭信息,則返回304:告訴瀏覽器請求內(nèi)容未更新可直接使用本地緩存。(注意:只對靜態(tài)內(nèi)容有效,如js/css/image/html等,不包括動態(tài)內(nèi)容,如JSP)
16.緩存雪崩
如果緩存集中在一段時間內(nèi)失效,發(fā)生大量的緩存穿透,所有的查詢都落在數(shù)據(jù)庫上,造成了緩存雪崩。
解決辦法:沒有完美的解決方案,可以通過隨機算法讓失效時間隨機分布,避免同一時刻失效。
17.緩存穿透
訪問一個不存在的key,緩存不起作用,請求會穿透到DB,可能DB也沒查到,流量大時DB會掛掉。
解決辦法: 1.采用布隆過濾器,使用一個足夠大的bitmap,用于存儲可能訪問的key,不存在的key直接被過濾;2訪問key未在DB查詢到值,也將空值寫進(jìn)緩存,但可以設(shè)置較短過期時間。
HashMap的Hash碰撞
Hash值沖突問題是Hash表存儲模型需要解決的一個問題。通常有兩種方法:
將相同Hash值的Entry對象組織成一個鏈表放置在hash值對應(yīng)的槽位。HashMap采用的是鏈表法,且是單向鏈表(通過head元素就可以操作后續(xù)所有元素,對鏈表而言,新加入的節(jié)點會從頭節(jié)點加入。) 核心源碼:
private void addEntry(int hash, K key, V value, int bucketIndex) {
Entrye = table[bucketIndex];
table[bucketIndex] = new Entry(hash, key, value, e);
if (size++ >= threshold)
resize(2 * table.length);
}
以上代碼說明:系統(tǒng)總是將新添加的 Entry 對象放入 table 數(shù)組的 bucketIndex 索引處。
18.HashMap的get和put原理
PUT原理:當(dāng)調(diào)用HashMap的put方法傳遞key和value時,先調(diào)用key的hashcode方法。通過key的Hash值來找到Bucket----‘桶’的位置,然后迭代這個位置的Entry列表 判斷是否存在key的hashcode和equals完全相同的key,如果完全相同則覆蓋value, 否則插入到entry鏈的頭部。
HashMap在put時的Entry鏈形成的場景?
當(dāng)程序試圖將一個key-value對放入HashMap中時,程序首先根據(jù)該 key 的 hashCode() 返回值決定該 Entry 的存儲位置:
如果這兩個 Entry 的 key 的 hashCode() 返回值相同,那它們的存儲位置相同。
如果這兩個 Entry 的 key 通過 equals 比較返回 true,新添加 Entry 的 value 將覆蓋集合中原有 Entry 的 value,但key不會覆蓋。
如果這兩個 Entry 的 key 通過 equals 比較返回 false,新添加的 Entry 將與集合中原有 Entry 形成 Entry 鏈,而且新添加的 Entry 位于 Entry 鏈的頭部
GET原理:根據(jù)該 key 的 hashCode 值計算它的 hash 碼,遍歷并循環(huán)取出 Entry 數(shù)組中指定索引處的Entry值,如果該 Entry 的 key 與被搜索 key 相同 ,且Enrty的hash值跟key的hash碼相同,然后看是否是Entry鏈,如果是則迭代這個位置的Entry列表,判斷是否存在key的hashcode和equals完全相同的key,如果完全相同則獲取value。
19.HashMap的rehash
HashMap初始容量大小為16,一般來說,當(dāng)有數(shù)據(jù)要插入時,都會檢查容量有沒有超過設(shè)定的thredhold,如果超過,需要增大Hash表的尺寸,但是這樣一來,整個Hash表里的元素都需要被重算一遍。這叫rehash,這個成本相當(dāng)?shù)拇?/p>
20.HashMap的線程不安全問題
比如put操作時,有兩個線程A和B,首先A希望插入一個key-value對到HashMap中,首先計算記錄所要落到的桶的索引BucketIndex坐標(biāo),然后獲取到該桶里面的Entry鏈表header頭結(jié)點,此時線程A的時間片用完了,而此時線程B被調(diào)度得以執(zhí)行,和線程A一樣執(zhí)行,只不過線程B成功將記錄插到了桶里面,假設(shè)線程A插入的記錄計算出來的桶索引和線程B要插入的記錄計算出來的桶索引是一樣的,那么當(dāng)線程B成功插入之后,線程A再次被調(diào)度運行時,它依然持有過期的鏈表頭但是它對此一無所知,以至于它認(rèn)為它應(yīng)該這樣做,如此一來就覆蓋了線程B插入的記錄,這樣線程B插入的記錄就憑空消失了,造成了數(shù)據(jù)不一致的行為。另一個不安全的體現(xiàn)是是get操作可能由于resize而死循環(huán)。
21.HashMap和Hashtable的區(qū)別
相同點:
不同點:
22.為什么collection沒有實現(xiàn)clonable接口
Collection接口有很多不同的集合實現(xiàn)形式,而clonable只對具體的對象有意義。
23.為什map沒有實現(xiàn)collection接口
Set 和List 都繼承了Conllection,Map沒有繼承于Collection接口,Map提供的是key-Value的映射,而Collection代表一組對象。
24.Map接口的實現(xiàn)有哪些,區(qū)別是什么
HashMap,LinkedHashMap,Hashtable,TreeMap。
LinkedHashMap 是HashMap的一個子類,保存了記錄的插入順序 Hashtable和HashMap類似,它繼承自Dictionary類,不同的是它不允許鍵或值為空。TreeMap實現(xiàn)SortMap接口,能夠把它保存的記錄根據(jù)鍵排序,默認(rèn)是按鍵值的升序排序,也可以指定排序的比較器。
以上就是動力節(jié)點java培訓(xùn)機構(gòu)小編介紹的“中高級JAVA工程師面試題及答案”的內(nèi)容,希望對大家有幫助,更多中高級java面試題請繼續(xù)關(guān)注動力節(jié)點java培訓(xùn)機構(gòu)官網(wǎng),每天會有精彩內(nèi)容分享與你。
?由于“史上最全的中高級JAVA工程師面試題及答案”內(nèi)容太多,本文已滿,請看下文鏈接
25~52道中高級JAVA工程師面試題及答案請看鏈接:http://m.ilovecolors.com.cn/javazixun/2191.html
53~64道中高級JAVA工程師面試題及答案請看鏈接:http://m.ilovecolors.com.cn/javazixun/2169.html
java面試題推薦
相關(guān)閱讀
0基礎(chǔ) 0學(xué)費 15天面授
有基礎(chǔ) 直達(dá)就業(yè)
業(yè)余時間 高薪轉(zhuǎn)行
工作1~3年,加薪神器
工作3~5年,晉升架構(gòu)
提交申請后,顧問老師會電話與您溝通安排學(xué)習(xí)