最近面試的小夥伴不少,對此我整理了一份Java面試題手冊:基礎知識、JavaOOP、Java集合/泛型面試題、Java異常面試題、Java中的IO與NIO面試題、Java反射、Java序列化、Java註解、多線程&併發、JVM、Mysql、Redis、Memcached、MongoDB、Spring、SpringBoot、SpringCloud、RabbitMQ、Dubbo、MyBatis、ZooKeeper、數據結構、算法、Elasticsearch、Kafka、微服務、Linux等等。能夠分享給你們學習。【持續更新中】前端
完整版Java面試題地址:【2021最新版】Java面試真題彙總mysql
序號 | 內容 | 地址連接 |
---|---|---|
1 | 【2021最新版】JavaOOP面試題總結 | http://www.noobyard.com/article/p-rncfmibs-oe.html |
2 | 【2021最新版】Java基礎面試題總結 | http://www.noobyard.com/article/p-ykqnztan-oe.html |
3 | 【2021最新版】多線程&併發面試題總結 | http://www.noobyard.com/article/p-nhidektg-oe.html |
4 | 【2021最新版】JVM面試題總結 | http://www.noobyard.com/article/p-anzurdyn-oe.html |
5 | 【2021最新版】Mysql面試題總結 | http://www.noobyard.com/article/p-vvarpaer-oe.html |
6 | 【2021最新版】Redis面試題總結 | http://www.noobyard.com/article/p-gpqwxdxv-oe.html |
7 | 【2021最新版】MongoDB面試題總結 | 未更新 |
8 | 【2021最新版】Spring面試題總結 | 未更新 |
9 | 【2021最新版】Spring Boot面試題總結 | 未更新 |
10 | 【2021最新版】Spring Cloud面試題總結 | 未更新 |
11 | 【2021最新版】RabbitMQ面試題總結 | 未更新 |
12 | 【2021最新版】Dubbo面試題總結 | 未更新 |
13 | 【2021最新版】MyBatis面試題總結 | 未更新 |
14 | 【2021最新版】ZooKeeper面試題總結 | 未更新 |
15 | 【2021最新版】數據結構面試題總結 | 未更新 |
16 | 【2021最新版】算法面試題總結 | 未更新 |
17 | 【2021最新版】Elasticsearch面試題總結 | 未更新 |
18 | 【2021最新版】Kafka面試題總結 | 未更新 |
19 | 【2021最新版】微服務面試題總結 | 未更新 |
20 | 【2021最新版】Linux面試題總結 | 未更新 |
答:
Memcached是一個開源的,高性能的內存綬存軟件,從名稱上看Mem就是內存的意思,而Cache就是緩存的意思。
Memcached的做用:經過在事先規劃好的內存空間中臨時綬存數據庫中的各種數據,以達到減小業務對數據庫的直接高併發訪問,從而達到提高數據庫的訪問性能,加速網站集羣動態應用服務的能力。web
答:面試
1、做爲數據庫的前端緩存應用redis
a、完整緩存(易),靜態緩存算法
例如:商品分類(京東),以及商品信息,可事先放在內存裏,而後再對外提供數據訪問,這種先放到內存,咱們稱之爲預熱,(先把數據存緩存中),用戶訪問時能夠只讀取memcached緩存,不讀取數據庫了。sql
b、執點緩存(難)數據庫
須要前端web程序配合,只緩存熱點的數據,即緩存常常被訪問的數據。先預熱數據庫裏的基礎數據,而後在動態更新,選讀取緩存,若是緩存裏沒有對應的數據,程序再去讀取數據庫,而後程序把讀取的新數據放入緩存存儲。後端
特殊說明 :數組
若是碰到電商秒殺等高併發的業務,必定要事先預熱,或者其它思想實現,例如:稱殺只是獲取資格,而不是瞬間秒殺到手商品。
那麼什麼是獲取資格?
就是在數據庫中,把 0 標成 1.就有資格啦。再慢慢的去領取商品訂單。由於秒殺過程太長會佔用服務器資源。
若是數據更新,同時觸發緩存更新,防止給用戶過時數據。
對於持久化緩存存儲系統,例如:redis,能夠替代一部分數據庫的存儲,一些簡單的數據業務,投票,統計,好友關注,商品分類等。nosql=not onlysql
2、做業集羣的 session 會話共享存儲。
Memcached服務在不一樣企業業務應用場景中的工做流程
當web程序須要訪問後端數據庫獲取數據時會優先訪問Memcached內存緩存,若是緩存中有數據就直接獲取返回前端服務及用戶,若是沒有數據(沒有命中),在由程序請求後端的數據庫服務器,獲取到對應的數據後,除了返回給前端服務及用戶數據外,還會把數據放到Memcached內存中進行緩存,等待下次請求被訪問,Memcache內存始終是數據庫的擋箭牌,從而大大的減輕數據庫的訪問壓力,提升整個網站架構的響應速度,提高了用戶體驗。
當程序更新,修改或刪除數據庫中已有的數據時,會同時發送請求通知Memcached 已經緩存的同一個ID內容的舊數據失效,從而保證Memcache中數據和數據庫中的數據一致。
若是在高併發場合,除了通知Memcached過程的緩存失效外,還會經過相關機制,使得在用戶訪問新數據前,經過程序預先把更新過的數據推送到memcache中緩存起來,這樣能夠減小數據庫的訪問壓力,提高Memcached中緩存命中率。
數據庫插件能夠再寫入更新數據庫後,自動拋給MC緩存起來,自身不Cache。
答:
特殊說明:Memcached集羣和web服務集羣是不同的,全部Memcached的數據總和纔是數據庫的數據。每臺Memcached 都是部分數據。(一臺memcached的數據,就是一部分mysql數據庫的數據)
a、程序端實現
程序加載全部mc的ip列表,經過對key作hash (一致性哈希算法)
例如:web1 (key)===>對應 A,B,C,D,E,F,G……若干臺服務器。(經過哈希算法實現)
b、負載均衡器
經過對key作hash (一致性哈希算法)一致哈希算法的目的是不但保證每一個對象只請求一個對應的服務器,並且當節點宕機,緩存服務器的更新從新分配比例降到最低。
答:
a、徹底基於內存緩存的
b、節點之間相互獨立
c、C/S 模式架構,C 語言編寫,總共 2000 行代碼。
d、異步I/O 模型,使用 libevent 做爲事件通知機制。
e、被緩存的數據以 key/value 鍵值對形式存在的。
f、所有數據存放於內存中,無持久性存儲的設計,重啓服務器,內存裏的數據會丟失。
g、當內存中緩存的數據容量達到啓動時設定的內存值時,就自動使用 LRU 算法刪除過時的緩存數據。
h、能夠對存儲的數據設置過時時間,這樣過時後的數據自動被清除,服務自己不會監控過時,而是在訪問的時候查看 key 的時間戳,判斷是否過時。
j、memcache 會對設定的內存進行分塊,再把塊分組,而後再提供服務
答:
早期的Memcached內存管理方式是經過malloc的分配的內存,使用完後經過free來回收內存,這種方式容易產生內存碎片,並下降操做系統對內存的管理效率。加劇操做系統內存管理器的負擔,最壞的狀況下,會致使操做系統比memcached進程自己還慢,爲了解決這個問題,Slab Allocation內存分配機制就延生了。
如今Memcached利用Slab Allocation機制來分配和管理內存。
Slab Allocation機制原理是按照預先規定的大小,將分配給memcached的內存分割成特定長度的內存塊(chunk),再把尺寸相同的內存塊,分紅組(chunks slab class),這些內存塊不會釋放,能夠重複利用。
並且,slab allocator還有重複使用已分配的內存的目的。 也就是說,分配到的內存不會釋放,而是重複利用。
Slab Allocation的主要術語Page分配給Slab的內存空間,默認是1MB。分配給Slab以後根據slab的大小切分紅chunk。
Chunk用於緩存記錄的內存空間。
SlabClass特定大小的chunk的組。
答:
Memcached的神奇來自兩階段哈希(two-stage hash)。Memcached就像一個巨大的、存儲了不少<key,value>對的哈希表。經過key,能夠存儲或查詢任意的數據。
客戶端能夠把數據存儲在多臺memcached上。當查詢數據時,客戶端首先參考節點列表計算出key的哈希值(階段一哈希),進而選中一個節點;客戶端將請求發送給選中的節點,而後memcached節點經過一個內部的哈希算法(階段二哈希),查找真正的數據(item)
答:
Memcached最大的好處就是它帶來了極佳的水平可擴展性,特別是在一個巨大的系統中。因爲客戶端本身作了一次哈希,那麼咱們很容易增長大量memcached到集羣中。memcached之間沒有相互通訊,所以不會增長memcached的負載;沒有多播協議,不會網絡通訊量爆炸(implode)。memcached的集羣很好用。內存不夠了?增長几臺memcached吧;CPU不夠用了?再增長几臺吧;有多餘的內存?
在增長几臺吧,不要浪費了。
基於memcached的基本原則,能夠至關輕鬆地構建出不一樣類型的緩存架構。除了這篇FAQ,在其餘地方很容易找到詳細資料的。
答:
cache相比,有什麼優缺點?
把memcached引入應用中,仍是須要很多工做量的。MySQL有個使用方便的query cache,能夠自動地緩存SQL查詢的結果,被緩存的SQL查詢能夠被反覆地快速執行。Memcached與之相比,怎麼樣呢?MySQL的query cache是集中式的,鏈接到該query cache的MySQL服務器都會受益。
當您修改表時,MySQL的query cache會馬上被刷新(flush)。存儲一個memcached item只須要不多的時間,可是當寫操做很頻繁時,MySQL的query cache會常常讓全部緩存數據都失效。
在多核CPU 上,MySQL的query cache會遇到擴展問題(scalabilityissues)。在多核CPU上,query cache會增長一個全局鎖(global lock), 因爲須要刷新更多的緩存數據,速度會變得更慢。
在MySQL的query cache中,咱們是不能存儲任意的數據的(只能是SQL查詢結果)。而利用emcached,咱們能夠搭建出各類高效的緩存。好比,能夠執行多個獨立的查詢,構建出一個用戶對象(user object),而後將用戶對象緩存到memcached 中。而query cache是SQL語句級別的,不可能作到這一點。在小的網站中,query cache會有所幫助,但隨着網站規模的增長,query cache的弊將大於利。
query cache可以利用的內存容量受到MySQL服務器空閒內存空間的限制。給數據庫服務器增長更多的內存來緩存數據,當然是很好的。可是,有了memcached,只要您有空閒的內存,均可以用來增長memcached集羣的規模,而後您就能夠緩存更多的數據。
答:
首先,local cache有許多與上面(query cache)相同的問題。local cache可以利用的內存容量受到(單臺)服務器空閒內存空間的限制。不過,local cache有一 點比memcached和query cache都要好, 那就 是它不但能夠存儲任意的數據 ,而 且沒有網絡存取的延遲 。
local cache的數據查詢更快。考慮把highly common的數據放在localcache中吧。若是每一個頁面都須要加載一些數量較少的數據,考慮把它們放在local cached吧。
local cache缺乏集體失效(groupinvalidation)的特性。在memcached集羣中,刪除或更新一個key會讓全部的觀察者覺察到。可是在local cache中, 咱們只能通知全部的服務器刷新cache(很慢,不具擴展性),或者僅僅依賴緩存超時失效機制。
local cache面臨着嚴重的內存限制,這一點上面已經提到。
答:
Memcached主要的cache機制是LRU(最近最少用 )算法+超時失效 。當您存數據到memcached 中, 能夠指定該數據在緩存中能夠呆多久Which is forever,or some time in the future。若是memcached的內存不 夠用 了, 過時 的slabs會優先被替換 ,接着就輪到最老的未被使用的slabs。
答:
不實 現!咱們對這個問題感到很驚訝。
Memcached應該是應用的緩存 層。它的設計自己就不帶有任何冗餘機制。 若是一個memcached節點失去了全部數 據, 您應該能夠從數據源 (好比數據庫 )再次獲取到數據 。您應該特別注意 ,您的應用應該能夠容忍節點的失效。 不要寫一些糟糕的查詢代碼,寄但願於memcached來保證一切!若是您擔憂節點失效會大大加劇數據庫的負擔,那麼您能夠採起一些辦法。好比您能夠增長更多的節點(來減小丟失一個節點的影響),熱備節點(在其餘節點down了的時候接管IP),等等。
答:
不處理! 在memcached節點失效的狀況下,集羣沒有必要作任何容錯處理。若是發生了節點失效,應對的措施徹底取決於用戶。節點失效時,下面列出幾種方案供您選擇:
忽略它!在失效節點被恢復或替換以前,還有不少其餘節點能夠應對節點失效帶來的影響。
把失效的節點從節點列表中移除。作這個操做千萬要當心!在默認狀況下(餘數式哈希算法),客戶端添加或移除節點,會致使全部的緩存數據不可用!由於哈希參照的節點列表變化了,大部分key會由於哈希值改變而被映射到(與原來)不一樣的節點上。
啓動熱備節點,接管失效節點鎖佔用的IP。這樣能夠防止哈希紊亂(hashing chaos)。
若是但願添加和移除節點,而不影響原先的哈希結果,可使用-致性哈希算法( consistent hashing)您能夠百度-下一致性哈希算法。支持一致性哈希的客戶端已經很成熟,並且被普遍使用。去嘗試一下吧!
兩次哈希( reshing)當客戶端存取數據時,若是發現一一個節點down了,就再作一次哈希(哈希算法與前一次不一樣) , 從新選擇另外一個節點(須要注意的是,客戶端並無把down的節點從節點列表中移除,下次仍是有可能先哈希到它)。若是某個節點時好時壞,兩次哈希的方法就有風險了,好的節點和壞的節點上均可能存在髒數據( stale data )。
答:
您不該該這樣作!Memcached是一個非阻塞的服務器。任何可能致使memcached暫停或瞬時拒絕服務的操做都應該值得深思熟慮。向memcached中批量導入數據每每不是您真正想要的!想象看,若是緩存數據在導出導入之間發生了變化,您就須要處理髒數據了。
答:
所以,批量導出導入數據並不像您想象中的那麼有用。
不過在一個場景卻是頗有用。若是您有大量的從不變化的數據,而且但願緩存很快熱(warm)起來,批量導入緩存數據是頗有幫助的。雖然這個場景並不典型,但卻常常發生,所以咱們會考慮在未來實現批量導出導入的功能。
若是一個memcached節點down了讓您很痛苦,那麼您還會陷入其餘不少麻煩。您的系統太脆弱了。您須要作一些優化工做。好比處理」驚羣」問題(好比memcached節點都失效了,反覆的查詢讓您的數據庫不堪重負,這個問題在FAQ的其餘提到過),或者優化很差的查詢。記住,Memcached並非您逃避優化查詢的藉口。
答:
沒有身份認證機制!memcached是運行在應用下層的軟件(身份驗證應該是應用上層的職責)。memcached的客戶端和服務器端之因此是輕量級的,部分緣由就是徹底沒有實現身份驗證機制。
這樣,memcached能夠很快地建立新鏈接,服務器端也無需任何配置。若是您但願限制訪問,您可使用防火牆,或者讓memcached監聽unix domain socket。
答:
線程就是定律(threads rule)!在Steven Grimm和Facebook的努力下,memcached1.2及更高版本擁有了多線程模式。多線程模式容許 memcached 可以充分利用多個CPU,並在CPU之間共享全部的緩存數據。memcached使用一種簡單的鎖機制來保證數據更新操做的互斥。相比在同一個物理機器上運行多個memcached實例,這種方式可以更有效地處理multi gets。
若是您的系統負載並不重,也許您不須要啓用多線程工做模式。若是您在運行一個擁有大規模硬件的、龐大的網站,您將會看到多線程的好處。
簡單地總結一下:命令解析(memcached在這裏花了大部分時間)能夠運行在多線程模式下。memcached內部對數據的操做是基於不少全局鎖的(所以這部分工做不是多線程的)。將來對多線程模式的改進,將移除大量的全局鎖,提升memcached 在負載極高的場景下的性能。
答:
key的最大長度是250個字符。須要注意的是,250是memcached服務器端內部的限制,若是您使用的客戶端支持」key的前綴」或相似特性,那麼key(前綴+原始key)的最大長度是能夠超過250個字符的。咱們推薦使用使用較短的key,由於能夠節省內存和帶寬。
答:
過時時間最大能夠達到30天。memcached把傳入的過時時間(時間段)解釋成時間點後,一旦到了這個時間點,memcached 就把item置爲失效狀態。這是一個簡單但obscure的機制。
答:
1MB。若是你的數據大於1MB,能夠考慮在客戶端壓縮或拆分到多個key中。
爲何單個item的大小被限制在 1M byte 以內?
這是一個你們常常問的問題!
簡單的回答:由於內存分配器的算法就是這樣的。
詳細的回答:Memcached的內存存儲引擎(引擎未來可插拔…),使用slabs來管理內存。內存被分紅大小不等的slabs chunks(先分紅大小相等的slabs,而後每一個slab被分紅大小相等chunks,不一樣slab的chunk大小是不相等的)。chunk的大小依次從一個最小數開始,按某個因子增加,直到達到最大的可能值。
答:
Memcache客戶端僅根據哈希算法來決定將某個key存儲在哪一個節點上,而不考慮節點的內存大小。所以,您能夠在不一樣的節點上使用大小不等的緩存。可是通常都是這樣作的:擁有較多內存的節點上能夠運行多個memcached實例,每一個實例使用的內存跟其餘節點上的實例相同。
答:
關於二進制最好的信息固然是二進制協議規範:
二進制協議嘗試爲端提供一個更有效的、可靠的協議,減小客戶端/服務器端因處理協議而產生的CPU時間。
根據Facebook的測試,解析ASCII協議是memcached中消耗CPU時間最多的環節。因此,咱們爲何不改進ASCII協議呢?
答:
實際上,這是一個編譯時選項。默認會使用內部的slab分配器。您確實確實應該使用內建的slab分配器。最先的時候,memcached只使用malloc/free來管理內存。然而,這種方式不能與OS的內存管理之前很好地工做。反覆地malloc/free形成了內存碎片,OS最終花費大量的時間去查找連續的內存塊來知足malloc的請求,而不是運行memcached進程。
若是您不一樣意,固然可使用malloc!
只是不要在郵件列表中抱怨啊
slab分配器就是爲了解決這個問題而生的。內存被分配並劃分紅chunks,一直被重複使用。由於內存被劃分紅大小不等的slabs,若是item的大小與被選擇存放它的slab不是很合適的話,就會浪費一些內存。Steven Grimm正在這方面已經作出了有效的改進。
答:
全部的被髮送到memcached的單個命令是徹底原子的。若是您針對同一份數據同時發送了一個set命令和一個get命令,它們不會影響對方。它們將被串行化、前後執行。即便在多線程模式,全部的命令都是原子的,除非程序有bug:)
命令序列不是原子的。若是您經過get命令獲取了一個item,修改了它,而後想把它set回memcached,咱們不保證這個item沒有被其餘進程(process,未必是操做系統中的進程)操做過。在併發的狀況下,您也可能覆寫了一個被其餘進程set的item。
memcached1.2.5以及更高版本,提供了gets和cas命令,它們能夠解決上面的問題。若是您使用gets命令查詢某個key的item,memcached會給您返回該item當前值的惟一標識。
果您覆寫了這個item並想把它寫回到memcached中,您能夠經過 cas命令把那個惟一標識一塊兒發送給memcached。
若是該 item存放在memcached中的惟一標識與您提供的一致,您的寫操做將會成功。
若是另外一個進程在這期間也修改了這個item,那麼該item存放在memcached中的惟一標識將會改變,您的寫操做就會失敗。
答:
Session是運行在一臺服務器上的,全部的訪問都會到達咱們的惟一服務器上,這樣咱們能夠根據客戶端傳來的sessionID,來獲取session,或在對應Session不存在的狀況下(session生命週期到了/用戶第一次登陸),建立一個新的Session。
可是,若是咱們在集羣環境下,假設咱們有兩臺服務器A,B,用戶的請求會由Nginx服務器進行轉發(別的方案也是同理),用戶登陸時,Nginx將請求轉發至服務器A 上,A建立了新的session,並將SessionID返回給客戶端,用戶在瀏覽其餘頁面時,客戶端驗證登陸狀態,Nginx將請求轉發至服務器B,因爲B上並無對應客戶端發來sessionId的session,因此會從新建立一個新的session,而且再將這個新的sessionID返回給客戶端,這樣,咱們能夠想象一下,用戶每一次操做都有1/2的機率進行再次的登陸,這樣不只對用戶體驗特別差,還會讓服務器上的session激增,加大服務器的運行壓力。
爲了解決集羣環境下的seesion共享問題,共有4種解決方案:
1.粘性session
粘性session是指Ngnix每次都將同一用戶的全部請求轉發至同一臺服務器上,即將用戶與服務器綁定。
2.服務器session 複製
即每次session發生變化時,建立或者修改,就廣播給全部集羣中的服務器,使全部的服務器上的session相同。
3.session共享
緩存session,使用redis, memcached。
4.session持久化
將session存儲至數據庫中,像操做數據同樣才作session
答:
一、Redis不只僅支持簡單的k/v類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。而memcache只支持簡單數據類型,須要客戶端本身處理複雜對象。
二、Redis支持數據的持久化,能夠將內存中的數據保持在磁盤中,重啓的時候能夠再次加載進行使用(PS:持久化在rdb、aof)。
三、因爲Memcache沒有持久化機制,所以宕機全部緩存數據失效。Redis配置爲持久化,宕機重啓後,將自動加載宕機時刻的數據到緩存系統中。具備更好的災備機制。
四、Memcache可使用Magent在客戶端進行一致性 hash 作分佈式。Redis支持在服務器端作分佈式。
(PS:Twemproxy/Codis/Redis cluster多種分佈式實現方式)。
五、Memcached的簡單限制就是鍵(key)和Value的限制。最大鍵長爲250個字符。能夠接受的儲存數據不能超過1MB(可修改配置文件變大),由於這是典型slab的最大值,不適合虛擬機使用。而 Redis的Key長度支持到512k。
六、Redis使用的是單線程模型,保證了數據按順序提交。Memcache須要使用cas保證數據一致性。CAS(Check and Set)是一個確保併發一致性的機制,屬於「樂觀鎖」範疇;原理很簡單:拿版本號,操做,對比版本號,若是一致就操做,不一致就放棄任何操做cpu利用。因爲Redis只使用單核,而Memcached可使用多核,因此平均每個核上Redis在存儲小數據時比 Memcached 性能更高。而在100k以上的數據中,Memcached性能要高於Redis 。
七、memcache內存管理:使用Slab Allocation。原理至關簡單,預先分配一系列大小固定的組,而後根據數據大小選擇最合適的塊存儲。
避免了內存碎片。(缺點:不能變長,浪費了必定空間)memcached默認狀況下下一個slab的最大值爲前一個的1.25倍。
八、Redis內存管理: Redis經過定義一個數組來記錄全部的內存分配狀況, Redis採用的是包裝的malloc/free,相較於 Memcached的內存管理方法來講,要簡單不少。因爲malloc首先以鏈表的方式搜索已管理的內存中可用的空間分配,致使內存碎片比較多。
該面試題答案解析完整文檔獲取方式:Memcached面試題總結