寫本文之前,其實(shí)我自己已經(jīng)開(kāi)源了一個(gè) Java學(xué)習(xí)指南的文檔恤浪,里面包含了一些基礎(chǔ)知識(shí)和一些偏后端(Java方向)的知識(shí)畅哑。到目前為止收獲了 6.1k star 以及 1.5 k fork,close 了 10個(gè) pr 以及 10 個(gè)issue水由。開(kāi)源只是為了讓更多的人看到和參與進(jìn)來(lái)荠呐,這樣文檔的正確性和質(zhì)量才能很好的保證。畢竟砂客,我個(gè)人能力泥张、時(shí)間以及知識(shí)廣度和深度有限,一份好的項(xiàng)目的誕生肯定離不開(kāi)和其他人的共同努力鞠值。
另外媚创,我個(gè)人覺(jué)得不論你是前端還是后端(部分內(nèi)容可能會(huì)偏 Java 方向一點(diǎn))都能從本文中學(xué)到東西。
本人技術(shù)水品有限彤恶,歡迎各位指正筝野!寫的不好的話晌姚,請(qǐng)多見(jiàn)諒!
目錄
- 前言
一 簡(jiǎn)歷該如何寫1.1 為什么說(shuō)簡(jiǎn)歷很重要歇竟?
- 1.2-這3點(diǎn)你必須知道
- 1.3-兩大法則了解一
- 1.4-項(xiàng)目經(jīng)歷怎么寫挥唠?
- 1.5-專業(yè)技能該怎么寫?
- 1.6-開(kāi)源程序員簡(jiǎn)歷模板分享
- 1.7 其他的一些小tips
二 計(jì)算機(jī)網(wǎng)絡(luò)常見(jiàn)面試點(diǎn)總結(jié)計(jì)算機(jī)網(wǎng)絡(luò)常見(jiàn)問(wèn)題回顧
- 2.1 TCP焕议、UDP 協(xié)議的區(qū)別
- 2.2 在瀏覽器中輸入url地址 ->> 顯示主頁(yè)的過(guò)程
- 2.3 各種協(xié)議與HTTP協(xié)議之間的關(guān)系
- 2.4 HTTP長(zhǎng)連接宝磨、短連接
- 2.5 TCP 三次握手和四次揮手
三 Linux3.1-簡(jiǎn)單介紹一下-linux-文件系統(tǒng)?
- 3.2 一些常見(jiàn)的 Linux 命令了解嗎盅安?
四 MySQL4.1 說(shuō)說(shuō)自己對(duì)于 MySQL 常見(jiàn)的兩種存儲(chǔ)引擎:MyISAM與InnoDB的理解
- 4.2 數(shù)據(jù)庫(kù)索引了解嗎唤锉?
- 4.3 對(duì)于大表的常見(jiàn)優(yōu)化手段說(shuō)一下
五 Redis5.1 redis 簡(jiǎn)介
- 5.2 為什么要用 redis /為什么要用緩存
- 5.3 為什么要用 redis 而不用 map/guava 做緩存?
- 5.4 redis 和 memcached 的區(qū)別
- 5.5 redis 常見(jiàn)數(shù)據(jù)結(jié)構(gòu)以及使用場(chǎng)景分析
- 5.6 redis 設(shè)置過(guò)期時(shí)間
- 5.7 redis 內(nèi)存淘汰機(jī)制
- 5.8 redis 持久化機(jī)制(怎么保證 redis 掛掉之后再重啟數(shù)據(jù)可以進(jìn)行恢復(fù))
- 5.9 緩存雪崩和緩存穿透問(wèn)題解決方案
- 5.10 如何解決 Redis 的并發(fā)競(jìng)爭(zhēng) Key 問(wèn)題
- 5.11 如何保證緩存與數(shù)據(jù)庫(kù)雙寫時(shí)的數(shù)據(jù)一致性?
六 Java6.1 Java 基礎(chǔ)知識(shí)
- 6.2 Java 集合框架
- 6.3 Java多線程
- 6.4 Java虛擬機(jī)
- 6.5 設(shè)計(jì)模式
七 數(shù)據(jù)結(jié)構(gòu)
八 算法
九 Spring9.1 Spring Bean 的作用域
- 9.2 Spring 事務(wù)中的隔離級(jí)別
- 9.3 Spring 事務(wù)中的事務(wù)傳播行為
- 9.4 AOP
- 9.5 IOC
十 實(shí)際場(chǎng)景題
點(diǎn)此處點(diǎn)擊鏈接加入群聊【java架構(gòu)高級(jí)進(jìn)階群】:https://jq.qq.com/?_wv=1027&k=ygubvvnv”獲取往期Java高級(jí)架構(gòu)資料别瞭、源碼窿祥、筆記、視頻
Dubbo蝙寨、Redis晒衩、Netty、zookeeper墙歪、Spring cloud听系、分布式、高并發(fā)等架構(gòu)技術(shù)
前言
不論是校招還是社招都避免不了各種面試虹菲、筆試靠胜,如何去準(zhǔn)備這些東西就顯得格外重要。不論是筆試還是面試都是有章可循的毕源,我這個(gè)“有章可循”說(shuō)的意思只是說(shuō)應(yīng)對(duì)技術(shù)面試是可以提前準(zhǔn)備浪漠。 我其實(shí)特別不喜歡那種臨近考試就提前背啊記啊各種題的行為,非常反對(duì)霎褐!我覺(jué)得這種方法特別極端址愿,而且在稍有一點(diǎn)經(jīng)驗(yàn)的面試官面前是根本沒(méi)有用的。建議大家還是一步一個(gè)腳印踏踏實(shí)實(shí)地走瘩欺。
運(yùn)籌帷幄之后必盖,決勝千里之外!不打毫無(wú)準(zhǔn)備的仗俱饿,我覺(jué)得大家可以先從下面幾個(gè)方面來(lái)準(zhǔn)備面試:
- 自我介紹歌粥。(你可千萬(wàn)這樣介紹:“我叫某某,性別拍埠,來(lái)自哪里失驶,學(xué)校是那個(gè),自己愛(ài)干什么”枣购,記祖姨健:多說(shuō)點(diǎn)簡(jiǎn)歷上沒(méi)有的擦耀,多說(shuō)點(diǎn)自己哪里比別人強(qiáng)!)
- 自己面試中可能涉及哪些知識(shí)點(diǎn)涩堤、那些知識(shí)點(diǎn)是重點(diǎn)眷蜓。
- 面試中哪些問(wèn)題會(huì)被經(jīng)常問(wèn)到、面試中自己改如何回答胎围。(強(qiáng)烈不推薦背題吁系,第一:通過(guò)背這種方式你能記住多少?能記住多久白魂?第二:背題的方式的學(xué)習(xí)很難堅(jiān)持下去汽纤!)
- 自己的簡(jiǎn)歷該如何寫。
“80%的offer掌握在20%的人手中” 這句話也不是不無(wú)道理的福荸。決定你面試能否成功的因素中實(shí)力固然占有很大一部分比例蕴坪,但是如果你的心態(tài)或者說(shuō)運(yùn)氣不好的話,依然無(wú)法拿到滿意的 offer敬锐。運(yùn)氣暫且不談背传,就拿心態(tài)來(lái)說(shuō),千萬(wàn)不要因?yàn)槊嬖囀《鴼怵H或者說(shuō)懷疑自己的能力滞造,面試失敗之后多總結(jié)一下失敗的原因续室,后面你就會(huì)發(fā)現(xiàn)自己會(huì)越來(lái)越強(qiáng)大栋烤。
另外谒养,大家要明確的很重要的幾點(diǎn)是:
- 寫在簡(jiǎn)歷上的東西一定要慎重,這可能是面試官大量提問(wèn)的地方明郭;
- 大部分應(yīng)屆生找工作的硬傷是沒(méi)有工作經(jīng)驗(yàn)或?qū)嵙?xí)經(jīng)歷买窟;
- 將自己的項(xiàng)目經(jīng)歷完美的展示出來(lái)非常重要。
筆主能力有限薯定,如果有不對(duì)的地方或者和你想法不同的地方始绍,敬請(qǐng)雅正、不舍賜教话侄。
一 簡(jiǎn)歷該如何寫
俗話說(shuō)的好:“工欲善其事亏推,必先利其器”。準(zhǔn)備一份好的簡(jiǎn)歷對(duì)于能不能找到一份好工作起到了至關(guān)重要的作用年堆。
1.1 為什么說(shuō)簡(jiǎn)歷很重要吞杭?
假如你是網(wǎng)申,你的簡(jiǎn)歷必然會(huì)經(jīng)過(guò)HR的篩選变丧,一張簡(jiǎn)歷HR可能也就花費(fèi)10秒鐘看一下芽狗,然后HR就會(huì)決定你這一關(guān)是Fail還是Pass。
假如你是內(nèi)推痒蓬,如果你的簡(jiǎn)歷沒(méi)有什么優(yōu)勢(shì)的話童擎,就算是內(nèi)推你的人再用心滴劲,也無(wú)能為力。
另外顾复,就算你通過(guò)了篩選班挖,后面的面試中,面試官也會(huì)根據(jù)你的簡(jiǎn)歷來(lái)判斷你究竟是否值得他花費(fèi)很多時(shí)間去面試芯砸。
1.2 這3點(diǎn)你必須知道
- 大部分應(yīng)屆生找工作的硬傷是沒(méi)有工作經(jīng)驗(yàn)或?qū)嵙?xí)經(jīng)歷聪姿;
- 寫在簡(jiǎn)歷上的東西一定要慎重,這可能是面試官大量提問(wèn)的地方乙嘀;
- 將自己的項(xiàng)目經(jīng)歷完美的展示出來(lái)非常重要末购。
1.3 兩大法則了解一下
目前寫簡(jiǎn)歷的方式有兩種普遍被認(rèn)可,一種是 STAR虎谢, 一種是 FAB盟榴。
STAR法則(Situation Task Action Result):
- Situation: 事情是在什么情況下發(fā)生;
- Task:: 你是如何明確你的任務(wù)的婴噩;
- Action: 針對(duì)這樣的情況分析擎场,你采用了什么行動(dòng)方式;
- Result: 結(jié)果怎樣几莽,在這樣的情況下你學(xué)習(xí)到了什么迅办。
FAB 法則(Feature Advantage Benefit):
- Feature: 是什么;
- Advantage: 比別人好在哪些地方章蚣;
- Benefit: 如果雇傭你站欺,招聘方會(huì)得到什么好處。
1.4 項(xiàng)目經(jīng)歷怎么寫纤垂?
簡(jiǎn)歷上有一兩個(gè)項(xiàng)目經(jīng)歷很正常矾策,但是真正能把項(xiàng)目經(jīng)歷很好的展示給面試官的非常少。對(duì)于項(xiàng)目經(jīng)歷大家可以考慮從如下幾點(diǎn)來(lái)寫:
- 對(duì)項(xiàng)目整體設(shè)計(jì)的一個(gè)感受
- 在這個(gè)項(xiàng)目中你負(fù)責(zé)了什么峭沦、做了什么贾虽、擔(dān)任了什么角色
- 從這個(gè)項(xiàng)目中你學(xué)會(huì)了那些東西,使用到了那些技術(shù)吼鱼,學(xué)會(huì)了那些新技術(shù)的使用
- 另外項(xiàng)目描述中蓬豁,最好可以體現(xiàn)自己的綜合素質(zhì),比如你是如何協(xié)調(diào)項(xiàng)目組成員協(xié)同開(kāi)發(fā)的或者在遇到某一個(gè)棘手的問(wèn)題的時(shí)候你是如何解決的菇肃。
1.5 專業(yè)技能該怎么寫地粪?
先問(wèn)一下你自己會(huì)什么,然后看看你意向的公司需要什么巷送。一般HR可能并不太懂技術(shù)驶忌,所以他在篩選簡(jiǎn)歷的時(shí)候可能就盯著你專業(yè)技能的關(guān)鍵詞來(lái)看。對(duì)于公司有要求而你不會(huì)的技能近她,你可以花幾天時(shí)間學(xué)習(xí)一下台诗,然后在簡(jiǎn)歷上可以寫上自己了解這個(gè)技能。比如你可以這樣寫:
- Dubbo:精通
- Spring:精通
- Docker:掌握
- SOA分布式開(kāi)發(fā) :掌握
- Spring Cloud:了解
1.6 開(kāi)源程序員簡(jiǎn)歷模板分享
- 盡量避免主觀表述乡括,少一點(diǎn)語(yǔ)義模糊的形容詞几苍,盡量要簡(jiǎn)潔明了翻屈,邏輯結(jié)構(gòu)清晰。
- 注意排版(不需要花花綠綠的)妻坝,盡量使用Markdown語(yǔ)法伸眶。
- 如果自己有博客或者個(gè)人技術(shù)棧點(diǎn)的話,寫上去會(huì)為你加分很多刽宪。
- 如果自己的Github比較活躍的話厘贼,寫上去也會(huì)為你加分很多。
- 注意簡(jiǎn)歷真實(shí)性圣拄,一定不要寫自己不會(huì)的東西嘴秸,或者帶有欺騙性的內(nèi)容
- 項(xiàng)目經(jīng)歷建議以時(shí)間倒序排序,另外項(xiàng)目經(jīng)歷不在于多庇谆,而在于有亮點(diǎn)岳掐。
- 如果內(nèi)容過(guò)多的話,不需要非把內(nèi)容壓縮到一頁(yè)饭耳,保持排版干凈整潔就可以了串述。
- 簡(jiǎn)歷最后最好能加上:“感謝您花時(shí)間閱讀我的簡(jiǎn)歷,期待能有機(jī)會(huì)和您共事寞肖「傩铮”這句話,顯的你會(huì)很有禮貌逝淹。
二 計(jì)算機(jī)網(wǎng)絡(luò)常見(jiàn)面試點(diǎn)總結(jié)
計(jì)算機(jī)網(wǎng)絡(luò)常見(jiàn)問(wèn)題回顧
- TCP三次握手和四次揮手耕姊、
- 在瀏覽器中輸入url地址->>顯示主頁(yè)的過(guò)程
- TCP 協(xié)議如何保證可靠傳輸
- HTTP和HTTPS的區(qū)別
- TCP桶唐、UDP協(xié)議的區(qū)別
- 常見(jiàn)的狀態(tài)碼栅葡。
下面列舉幾個(gè)常見(jiàn)問(wèn)題的回答!
2.1 TCP尤泽、UDP 協(xié)議的區(qū)別
UDP 在傳送數(shù)據(jù)之前不需要先建立連接欣簇,遠(yuǎn)地主機(jī)在收到 UDP 報(bào)文后,不需要給出任何確認(rèn)坯约。雖然 UDP 不提供可靠交付熊咽,但在某些情況下 UDP 確是一種最有效的工作方式(一般用于即時(shí)通信),比如: QQ 語(yǔ)音闹丐、 QQ 視頻 横殴、直播等等
TCP 提供面向連接的服務(wù)。在傳送數(shù)據(jù)之前必須先建立連接,數(shù)據(jù)傳送結(jié)束后要釋放連接衫仑。 TCP 不提供廣播或多播服務(wù)梨与。由于 TCP 要提供可靠的,面向連接的運(yùn)輸服務(wù)(TCP的可靠體現(xiàn)在TCP在傳遞數(shù)據(jù)之前文狱,會(huì)有三次握手來(lái)建立連接粥鞋,而且在數(shù)據(jù)傳遞時(shí),有確認(rèn)瞄崇、窗口呻粹、重傳、擁塞控制機(jī)制苏研,在數(shù)據(jù)傳完后等浊,還會(huì)斷開(kāi)連接用來(lái)節(jié)約系統(tǒng)資源),這一難以避免增加了許多開(kāi)銷摹蘑,如確認(rèn)凿掂,流量控制,計(jì)時(shí)器以及連接管理等纹蝴。這不僅使協(xié)議數(shù)據(jù)單元的首部增大很多庄萎,還要占用許多處理機(jī)資源。TCP 一般用于文件傳輸塘安、發(fā)送和接收郵件糠涛、遠(yuǎn)程登錄等場(chǎng)景。
2.2 在瀏覽器中輸入url地址 ->> 顯示主頁(yè)的過(guò)程
百度好像最喜歡問(wèn)這個(gè)問(wèn)題兼犯。
打開(kāi)一個(gè)網(wǎng)頁(yè)忍捡,整個(gè)過(guò)程會(huì)使用哪些協(xié)議
圖片來(lái)源:《圖解HTTP》
總體來(lái)說(shuō)分為以下幾個(gè)過(guò)程:
- DNS解析
- TCP連接
- 發(fā)送HTTP請(qǐng)求
- 服務(wù)器處理請(qǐng)求并返回HTTP報(bào)文
- 瀏覽器解析渲染頁(yè)面
- 連接結(jié)束
2.3 各種協(xié)議與HTTP協(xié)議之間的關(guān)系
一般面試官會(huì)通過(guò)這樣的問(wèn)題來(lái)考察你對(duì)計(jì)算機(jī)網(wǎng)絡(luò)知識(shí)體系的理解。
圖片來(lái)源:《圖解HTTP》
2.4 HTTP長(zhǎng)連接切黔、短連接
在HTTP/1.0中默認(rèn)使用短連接砸脊。也就是說(shuō),客戶端和服務(wù)器每進(jìn)行一次HTTP操作纬霞,就建立一次連接凌埂,任務(wù)結(jié)束就中斷連接。當(dāng)客戶端瀏覽器訪問(wèn)的某個(gè)HTML或其他類型的Web頁(yè)中包含有其他的Web資源(如JavaScript文件诗芜、圖像文件瞳抓、CSS文件等),每遇到這樣一個(gè)Web資源伏恐,瀏覽器就會(huì)重新建立一個(gè)HTTP會(huì)話孩哑。
而從HTTP/1.1起,默認(rèn)使用長(zhǎng)連接翠桦,用以保持連接特性横蜒。使用長(zhǎng)連接的HTTP協(xié)議,會(huì)在響應(yīng)頭加入這行代碼:
Connection:keep-alive
在使用長(zhǎng)連接的情況下,當(dāng)一個(gè)網(wǎng)頁(yè)打開(kāi)完成后丛晌,客戶端和服務(wù)器之間用于傳輸HTTP數(shù)據(jù)的TCP連接不會(huì)關(guān)閉鹰霍,客戶端再次訪問(wèn)這個(gè)服務(wù)器時(shí),會(huì)繼續(xù)使用這一條已經(jīng)建立的連接茵乱。Keep-Alive不會(huì)永久保持連接茂洒,它有一個(gè)保持時(shí)間,可以在不同的服務(wù)器軟件(如Apache)中設(shè)定這個(gè)時(shí)間瓶竭。實(shí)現(xiàn)長(zhǎng)連接需要客戶端和服務(wù)端都支持長(zhǎng)連接督勺。
HTTP協(xié)議的長(zhǎng)連接和短連接,實(shí)質(zhì)上是TCP協(xié)議的長(zhǎng)連接和短連接斤贰。
2.5 TCP 三次握手和四次揮手(面試持前В客)
為了準(zhǔn)確無(wú)誤地把數(shù)據(jù)送達(dá)目標(biāo)處,TCP協(xié)議采用了三次握手策略荧恍。
漫畫圖解:
圖片來(lái)源:《圖解HTTP》
簡(jiǎn)單示意圖:
- 客戶端–發(fā)送帶有 SYN 標(biāo)志的數(shù)據(jù)包–一次握手–服務(wù)端
- 服務(wù)端–發(fā)送帶有 SYN/ACK 標(biāo)志的數(shù)據(jù)包–二次握手–客戶端
- 客戶端–發(fā)送帶有帶有 ACK 標(biāo)志的數(shù)據(jù)包–三次握手–服務(wù)端
為什么要三次握手?
三次握手的目的是建立可靠的通信信道瓷叫,說(shuō)到通訊,簡(jiǎn)單來(lái)說(shuō)就是數(shù)據(jù)的發(fā)送與接收送巡,而三次握手最主要的目的就是雙方確認(rèn)自己與對(duì)方的發(fā)送與接收是正常的摹菠。
第一次握手:Client 什么都不能確認(rèn);Server 確認(rèn)了對(duì)方發(fā)送正常
第二次握手:Client 確認(rèn)了:自己發(fā)送骗爆、接收正常次氨,對(duì)方發(fā)送、接收正常摘投;Server 確認(rèn)了:自己接收正常煮寡,對(duì)方發(fā)送正常
第三次握手:Client 確認(rèn)了:自己發(fā)送、接收正常犀呼,對(duì)方發(fā)送幸撕、接收正常;Server 確認(rèn)了:自己發(fā)送外臂、接收正常坐儿,對(duì)方發(fā)送接收正常
所以三次握手就能確認(rèn)雙發(fā)收發(fā)功能都正常,缺一不可专钉。
為什么要傳回 SYN
接收端傳回發(fā)送端所發(fā)送的 SYN 是為了告訴發(fā)送端挑童,我接收到的信息確實(shí)就是你所發(fā)送的信號(hào)了。
SYN 是 TCP/IP 建立連接時(shí)使用的握手信號(hào)跃须。在客戶機(jī)和服務(wù)器之間建立正常的 TCP 網(wǎng)絡(luò)連接時(shí),客戶機(jī)首先發(fā)出一個(gè) SYN 消息娃兽,服務(wù)器使用 SYN-ACK 應(yīng)答表示接收到了這個(gè)消息菇民,最后客戶機(jī)再以 ACK(Acknowledgement[漢譯:確認(rèn)字符 ,在數(shù)據(jù)通信傳輸中,接收站發(fā)給發(fā)送站的一種傳輸控制字符。它表示確認(rèn)發(fā)來(lái)的數(shù)據(jù)已經(jīng)接受無(wú)誤第练。 ])消息響應(yīng)阔馋。這樣在客戶機(jī)和服務(wù)器之間才能建立起可靠的TCP連接,數(shù)據(jù)才可以在客戶機(jī)和服務(wù)器之間傳遞娇掏。
傳了 SYN,為啥還要傳 ACK
雙方通信無(wú)誤必須是兩者互相發(fā)送信息都無(wú)誤呕寝。傳了 SYN,證明發(fā)送方到接收方的通道沒(méi)有問(wèn)題婴梧,但是接收方到發(fā)送方的通道還需要 ACK 信號(hào)來(lái)進(jìn)行驗(yàn)證下梢。
斷開(kāi)一個(gè) TCP 連接則需要“四次揮手”:
- 客戶端-發(fā)送一個(gè) FIN,用來(lái)關(guān)閉客戶端到服務(wù)器的數(shù)據(jù)傳送
- 服務(wù)器-收到這個(gè) FIN塞蹭,它發(fā)回一 個(gè) ACK孽江,確認(rèn)序號(hào)為收到的序號(hào)加1 。和 SYN 一樣番电,一個(gè) FIN 將占用一個(gè)序號(hào)
- 服務(wù)器-關(guān)閉與客戶端的連接岗屏,發(fā)送一個(gè)FIN給客戶端
- 客戶端-發(fā)回 ACK 報(bào)文確認(rèn),并將確認(rèn)序號(hào)設(shè)置為收到序號(hào)加1
為什么要四次揮手
任何一方都可以在數(shù)據(jù)傳送結(jié)束后發(fā)出連接釋放的通知漱办,待對(duì)方確認(rèn)后進(jìn)入半關(guān)閉狀態(tài)这刷。當(dāng)另一方也沒(méi)有數(shù)據(jù)再發(fā)送的時(shí)候,則發(fā)出連接釋放通知娩井,對(duì)方確認(rèn)后就完全關(guān)閉了TCP連接崭歧。
舉個(gè)例子:A 和 B 打電話,通話即將結(jié)束后撞牢,A 說(shuō)“我沒(méi)啥要說(shuō)的了”率碾,B回答“我知道了”,但是 B 可能還會(huì)有要說(shuō)的話屋彪,A 不能要求 B 跟著自己的節(jié)奏結(jié)束通話所宰,于是 B 可能又巴拉巴拉說(shuō)了一通,最后 B 說(shuō)“我說(shuō)完了”畜挥,A 回答“知道了”仔粥,這樣通話才算結(jié)束。
三 Linux
3.1 簡(jiǎn)單介紹一下 Linux 文件系統(tǒng)蟹但?
Linux文件系統(tǒng)簡(jiǎn)介
在Linux操作系統(tǒng)中躯泰,所有被操作系統(tǒng)管理的資源,例如網(wǎng)絡(luò)接口卡华糖、磁盤驅(qū)動(dòng)器麦向、打印機(jī)、輸入輸出設(shè)備客叉、普通文件或是目錄都被看作是一個(gè)文件诵竭。
也就是說(shuō)在LINUX系統(tǒng)中有一個(gè)重要的概念:一切都是文件话告。其實(shí)這是UNIX哲學(xué)的一個(gè)體現(xiàn),而Linux是重寫UNIX而來(lái)卵慰,所以這個(gè)概念也就傳承了下來(lái)沙郭。在UNIX系統(tǒng)中,把一切資源都看作是文件裳朋,包括硬件設(shè)備病线。UNIX系統(tǒng)把每個(gè)硬件都看成是一個(gè)文件,通常稱為設(shè)備文件鲤嫡,這樣用戶就可以用讀寫文件的方式實(shí)現(xiàn)對(duì)硬件的訪問(wèn)送挑。
文件類型與目錄結(jié)構(gòu)
Linux支持5種文件類型 :
Linux的目錄結(jié)構(gòu)如下:
Linux文件系統(tǒng)的結(jié)構(gòu)層次鮮明,就像一棵倒立的樹(shù)泛范,最頂層是其根目錄:
常見(jiàn)目錄說(shuō)明:
- /bin: 存放二進(jìn)制可執(zhí)行文件(ls,cat,mkdir等)让虐,常用命令一般都在這里;
- /etc: 存放系統(tǒng)管理和配置文件罢荡;
- /home: 存放所有用戶文件的根目錄赡突,是用戶主目錄的基點(diǎn),比如用戶user的主目錄就是/home/user区赵,可以用~user表示惭缰;
- /usr : 用于存放系統(tǒng)應(yīng)用程序;
- /opt: 額外安裝的可選應(yīng)用程序包所放置的位置笼才。一般情況下漱受,我們可以把tomcat等都安裝到這里;
- /proc: 虛擬文件系統(tǒng)目錄骡送,是系統(tǒng)內(nèi)存的映射昂羡。可直接訪問(wèn)這個(gè)目錄來(lái)獲取系統(tǒng)信息摔踱;
- /root: 超級(jí)用戶(系統(tǒng)管理員)的主目錄(特權(quán)階級(jí)o)虐先;
- /sbin: 存放二進(jìn)制可執(zhí)行文件,只有root才能訪問(wèn)派敷。這里存放的是系統(tǒng)管理員使用的系統(tǒng)級(jí)別的管理命令和程序蛹批。如ifconfig等;
- /dev: 用于存放設(shè)備文件篮愉;
- /mnt: 系統(tǒng)管理員安裝臨時(shí)文件系統(tǒng)的安裝點(diǎn)腐芍,系統(tǒng)提供這個(gè)目錄是讓用戶臨時(shí)掛載其他的文件系統(tǒng);
- /boot: 存放用于系統(tǒng)引導(dǎo)時(shí)使用的各種文件试躏;
- /lib : 存放著和系統(tǒng)運(yùn)行相關(guān)的庫(kù)文件 猪勇;
- /tmp: 用于存放各種臨時(shí)文件,是公用的臨時(shí)文件存儲(chǔ)點(diǎn)冗酿;
- /var: 用于存放運(yùn)行時(shí)需要改變數(shù)據(jù)的文件埠对,也是某些大文件的溢出區(qū)络断,比方說(shuō)各種服務(wù)的日志文件(系統(tǒng)啟動(dòng)日志等裁替。)等项玛;
- /lost+found: 這個(gè)目錄平時(shí)是空的,系統(tǒng)非正常關(guān)機(jī)而留下“無(wú)家可歸”的文件(windows下叫什么.chk)就在這里弱判。
3.2 一些常見(jiàn)的 Linux 命令了解嗎襟沮?
目錄切換命令
- cd usr: 切換到該目錄下usr目錄
- cd ..(或cd../): 切換到上一層目錄
- cd /: 切換到系統(tǒng)根目錄
- cd ~: 切換到用戶主目錄
- cd -: 切換到上一個(gè)所在目錄
目錄的操作命令(增刪改查)
- mkdir 目錄名稱: 增加目錄
- ls或者ll(ll是ls -l的縮寫,ll命令以看到該目錄下的所有目錄和文件的詳細(xì)信息):查看目錄信息
- find 目錄 參數(shù): 尋找目錄(查)
- mv 目錄名稱 新目錄名稱: 修改目錄的名稱(改)
- 注意:mv的語(yǔ)法不僅可以對(duì)目錄進(jìn)行重命名而且也可以對(duì)各種文件昌腰,壓縮包等進(jìn)行 重命名的操作开伏。mv命令用來(lái)對(duì)文件或目錄重新命名,或者將文件從一個(gè)目錄移到另一個(gè)目錄中遭商。后面會(huì)介紹到mv命令的另一個(gè)用法固灵。
- mv 目錄名稱 目錄的新位置: 移動(dòng)目錄的位置---剪切(改)
- 注意:mv語(yǔ)法不僅可以對(duì)目錄進(jìn)行剪切操作,對(duì)文件和壓縮包等都可執(zhí)行剪切操作劫流。另外mv與cp的結(jié)果不同巫玻,mv好像文件“搬家”,文件個(gè)數(shù)并未增加祠汇。而cp對(duì)文件進(jìn)行復(fù)制仍秤,文件個(gè)數(shù)增加了。
- cp -r 目錄名稱 目錄拷貝的目標(biāo)位置: 拷貝目錄(改)可很,-r代表遞歸拷貝
- 注意:cp命令不僅可以拷貝目錄還可以拷貝文件诗力,壓縮包等,拷貝文件和壓縮包時(shí)不 用寫-r遞歸
- rm [-rf] 目錄: 刪除目錄(刪)
- 注意:rm不僅可以刪除目錄我抠,也可以刪除其他文件或壓縮包苇本,為了增強(qiáng)大家的記憶, 無(wú)論刪除任何目錄或文件菜拓,都直接使用rm -rf 目錄/文件/壓縮包
文件的操作命令(增刪改查)
- touch 文件名稱: 文件的創(chuàng)建(增)
- cat/more/less/tail 文件名稱 文件的查看(查)
- cat: 只能顯示最后一屏內(nèi)容
- more: 可以顯示百分比瓣窄,回車可以向下一行, 空格可以向下一頁(yè)尘惧,q可以退出查看
- less: 可以使用鍵盤上的PgUp和PgDn向上 和向下翻頁(yè)康栈,q結(jié)束查看
- tail-10 : 查看文件的后10行,Ctrl+C結(jié)束
- 注意:命令 tail -f 文件 可以對(duì)某個(gè)文件進(jìn)行動(dòng)態(tài)監(jiān)控喷橙,例如tomcat的日志文件啥么, 會(huì)隨著程序的運(yùn)行,日志會(huì)變化贰逾,可以使用tail -f catalina-2016-11-11.log 監(jiān)控 文 件的變化
- vim 文件: 修改文件的內(nèi)容(改)
- vim編輯器是Linux中的強(qiáng)大組件悬荣,是vi編輯器的加強(qiáng)版,vim編輯器的命令和快捷方式有很多疙剑,但此處不一一闡述氯迂,大家也無(wú)需研究的很透徹践叠,使用vim編輯修改文件的方式基本會(huì)使用就可以了。
- 在實(shí)際開(kāi)發(fā)中嚼蚀,使用vim編輯器主要作用就是修改配置文件禁灼,下面是一般步驟:
- vim 文件------>進(jìn)入文件----->命令模式------>按i進(jìn)入編輯模式----->編輯文件 ------->按Esc進(jìn)入底行模式----->輸入:wq/q! (輸入wq代表寫入內(nèi)容并退出,即保存轿曙;輸入q!代表強(qiáng)制退出不保存弄捕。)
- rm -rf 文件: 刪除文件(刪)
- 同目錄刪除:熟記 rm -rf 文件 即可
壓縮文件的操作命令
1)打包并壓縮文件:
Linux中的打包文件一般是以.tar結(jié)尾的,壓縮的命令一般是以.gz結(jié)尾的导帝。
而一般情況下打包和壓縮是一起進(jìn)行的守谓,打包并壓縮后的文件的后綴名一般.tar.gz。 命令:tar -zcvf 打包壓縮后的文件名 要打包壓縮的文件 其中:
z:調(diào)用gzip壓縮命令進(jìn)行壓縮
c:打包文件
v:顯示運(yùn)行過(guò)程
f:指定文件名
比如:加入test目錄下有三個(gè)文件分別是 :aaa.txt bbb.txt ccc.txt,如果我們要打包test目錄并指定壓縮后的壓縮包名稱為test.tar.gz可以使用命令:tar -zcvf test.tar.gz aaa.txt bbb.txt ccc.txt或:tar -zcvf test.tar.gz /test/
2)解壓壓縮包:
命令:tar [-xvf] 壓縮文件
其中:x:代表解壓
示例:
1 將/test下的test.tar.gz解壓到當(dāng)前目錄下可以使用命令:tar -xvf test.tar.gz
2 將/test下的test.tar.gz解壓到根目錄/usr下:tar -xvf xxx.tar.gz -C /usr(- C代表指定解壓的位置)
其他常用命令
- pwd: 顯示當(dāng)前所在位置
- grep 要搜索的字符串 要搜索的文件 --color: 搜索命令您单,--color代表高亮顯示
- ps -ef/ps aux: 這兩個(gè)命令都是查看當(dāng)前系統(tǒng)正在運(yùn)行進(jìn)程斋荞,兩者的區(qū)別是展示格式不同。如果想要查看特定的進(jìn)程可以使用這樣的格式:ps aux|grep redis (查看包括redis字符串的進(jìn)程)
- 注意:如果直接用ps((Process Status))命令虐秦,會(huì)顯示所有進(jìn)程的狀態(tài)平酿,通常結(jié)合grep命令查看某進(jìn)程的狀態(tài)。
- kill -9 進(jìn)程的pid: 殺死進(jìn)程(-9 表示強(qiáng)制終止羡疗。)
- 先用ps查找進(jìn)程染服,然后用kill殺掉
- 網(wǎng)絡(luò)通信命令:
- 查看當(dāng)前系統(tǒng)的網(wǎng)卡信息:ifconfig
- 查看與某臺(tái)機(jī)器的連接情況:ping
- 查看當(dāng)前系統(tǒng)的端口使用:netstat -an
- shutdown: shutdown -h now: 指定現(xiàn)在立即關(guān)機(jī);shutdown +5 "System will shutdown after 5 minutes":指定5分鐘后關(guān)機(jī)叨恨,同時(shí)送出警告信息給登入用戶柳刮。
- reboot: reboot: 重開(kāi)機(jī)。reboot -w: 做個(gè)重開(kāi)機(jī)的模擬(只有紀(jì)錄并不會(huì)真的重開(kāi)機(jī))痒钝。
四 MySQL
4.1 說(shuō)說(shuō)自己對(duì)于 MySQL 常見(jiàn)的兩種存儲(chǔ)引擎:MyISAM與InnoDB的理解
關(guān)于二者的對(duì)比與總結(jié):
- count運(yùn)算上的區(qū)別:因?yàn)镸yISAM緩存有表meta-data(行數(shù)等)秉颗,因此在做COUNT(*)時(shí)對(duì)于一個(gè)結(jié)構(gòu)很好的查詢是不需要消耗多少資源的。而對(duì)于InnoDB來(lái)說(shuō)送矩,則沒(méi)有這種緩存蚕甥。
- 是否支持事務(wù)和崩潰后的安全恢復(fù): MyISAM 強(qiáng)調(diào)的是性能,每次查詢具有原子性,其執(zhí)行數(shù)度比InnoDB類型更快栋荸,但是不提供事務(wù)支持菇怀。但是InnoDB 提供事務(wù)支持事務(wù),外部鍵等高級(jí)數(shù)據(jù)庫(kù)功能晌块。 具有事務(wù)(commit)爱沟、回滾(rollback)和崩潰修復(fù)能力(crash recovery capabilities)的事務(wù)安全(transaction-safe (ACID compliant))型表。
- 是否支持外鍵: MyISAM不支持匆背,而InnoDB支持呼伸。
MyISAM更適合讀密集的表,而InnoDB更適合寫密集的的表钝尸。 在數(shù)據(jù)庫(kù)做主從分離的情況下括享,經(jīng)常選擇MyISAM作為主庫(kù)的存儲(chǔ)引擎搂根。 一般來(lái)說(shuō),如果需要事務(wù)支持铃辖,并且有較高的并發(fā)讀取頻率(MyISAM的表鎖的粒度太大剩愧,所以當(dāng)該表寫并發(fā)量較高時(shí),要等待的查詢就會(huì)很多了)澳叉,InnoDB是不錯(cuò)的選擇隙咸。如果你的數(shù)據(jù)量很大(MyISAM支持壓縮特性可以減少磁盤的空間占用)沐悦,而且不需要支持事務(wù)時(shí)成洗,MyISAM是最好的選擇。
4.2 數(shù)據(jù)庫(kù)索引了解嗎藏否?
Mysql索引使用的數(shù)據(jù)結(jié)構(gòu)主要有BTree索引 和 哈希索引 瓶殃。對(duì)于哈希索引來(lái)說(shuō),底層的數(shù)據(jù)結(jié)構(gòu)就是哈希表副签,因此在絕大多數(shù)需求為單條記錄查詢的時(shí)候遥椿,可以選擇哈希索引,查詢性能最快淆储;其余大部分場(chǎng)景冠场,建議選擇BTree索引。
Mysql的BTree索引使用的是B數(shù)中的B+Tree本砰,但對(duì)于主要的兩種存儲(chǔ)引擎的實(shí)現(xiàn)方式是不同的碴裙。
- MyISAM: B+Tree葉節(jié)點(diǎn)的data域存放的是數(shù)據(jù)記錄的地址。在索引檢索的時(shí)候点额,首先按照B+Tree搜索算法搜索索引舔株,如果指定的Key存在,則取出其 data 域的值还棱,然后以 data 域的值為地址讀取相應(yīng)的數(shù)據(jù)記錄载慈。這被稱為“非聚簇索引”。
- InnoDB: 其數(shù)據(jù)文件本身就是索引文件珍手。相比MyISAM办铡,索引文件和數(shù)據(jù)文件是分離的,其表數(shù)據(jù)文件本身就是按B+Tree組織的一個(gè)索引結(jié)構(gòu)琳要,樹(shù)的葉節(jié)點(diǎn)data域保存了完整的數(shù)據(jù)記錄寡具。這個(gè)索引的key是數(shù)據(jù)表的主鍵,因此InnoDB表數(shù)據(jù)文件本身就是主索引焙蹭。這被稱為“聚簇索引(或聚集索引)”添忘。而其余的索引都作為輔助索引(非聚集索引)惹恃,輔助索引的data域存儲(chǔ)相應(yīng)記錄主鍵的值而不是地址,這也是和MyISAM不同的地方九杂。在根據(jù)主索引搜索時(shí),直接找到key所在的節(jié)點(diǎn)即可取出數(shù)據(jù)梢薪;在根據(jù)輔助索引查找時(shí),則需要先取出主鍵的值,在走一遍主索引拼余。 因此,在設(shè)計(jì)表的時(shí)候亩歹,不建議使用過(guò)長(zhǎng)的字段作為主鍵匙监,也不建議使用非單調(diào)的字段作為主鍵,這樣會(huì)造成主索引頻繁分裂小作。 PS:整理自《Java工程師修煉之道》
4.3 對(duì)于大表的常見(jiàn)優(yōu)化手段說(shuō)一下
當(dāng)MySQL單表記錄數(shù)過(guò)大時(shí)亭姥,數(shù)據(jù)庫(kù)的CRUD性能會(huì)明顯下降,一些常見(jiàn)的優(yōu)化措施如下:
- 限定數(shù)據(jù)的范圍: 務(wù)必禁止不帶任何限制數(shù)據(jù)范圍條件的查詢語(yǔ)句顾稀。比如:我們當(dāng)用戶在查詢訂單歷史的時(shí)候达罗,我們可以控制在一個(gè)月的范圍內(nèi)。静秆;
- 讀/寫分離: 經(jīng)典的數(shù)據(jù)庫(kù)拆分方案粮揉,主庫(kù)負(fù)責(zé)寫,從庫(kù)負(fù)責(zé)讀抚笔;
- 緩存: 使用MySQL的緩存扶认,另外對(duì)重量級(jí)、更新少的數(shù)據(jù)可以考慮使用應(yīng)用級(jí)別的緩存殊橙;
- 垂直分區(qū):
- 根據(jù)數(shù)據(jù)庫(kù)里面數(shù)據(jù)表的相關(guān)性進(jìn)行拆分辐宾。 例如,用戶表中既有用戶的登錄信息又有用戶的基本信息蛀柴,可以將用戶表拆分成兩個(gè)單獨(dú)的表螃概,甚至放到單獨(dú)的庫(kù)做分庫(kù)。
- 簡(jiǎn)單來(lái)說(shuō)垂直拆分是指數(shù)據(jù)表列的拆分鸽疾,把一張列比較多的表拆分為多張表吊洼。 如下圖所示,這樣來(lái)說(shuō)大家應(yīng)該就更容易理解了制肮。
垂直拆分的優(yōu)點(diǎn): 可以使得行數(shù)據(jù)變小冒窍,在查詢時(shí)減少讀取的Block數(shù),減少I/O次數(shù)豺鼻。此外综液,垂直分區(qū)可以簡(jiǎn)化表的結(jié)構(gòu),易于維護(hù)儒飒。
垂直拆分的缺點(diǎn): 主鍵會(huì)出現(xiàn)冗余谬莹,需要管理冗余列,并會(huì)引起Join操作,可以通過(guò)在應(yīng)用層進(jìn)行Join來(lái)解決附帽。此外埠戳,垂直分區(qū)會(huì)讓事務(wù)變得更加復(fù)雜;
水平分區(qū):
保持?jǐn)?shù)據(jù)表結(jié)構(gòu)不變蕉扮,通過(guò)某種策略存儲(chǔ)數(shù)據(jù)分片整胃。這樣每一片數(shù)據(jù)分散到不同的表或者庫(kù)中,達(dá)到了分布式的目的喳钟。 水平拆分可以支撐非常大的數(shù)據(jù)量屁使。
水平拆分是指數(shù)據(jù)表行的拆分,表的行數(shù)超過(guò)200萬(wàn)行時(shí)奔则,就會(huì)變慢蛮寂,這時(shí)可以把一張的表的數(shù)據(jù)拆成多張表來(lái)存放。舉個(gè)例子:我們可以將用戶信息表拆分成多個(gè)用戶信息表应狱,這樣就可以避免單一表數(shù)據(jù)量過(guò)大對(duì)性能造成影響共郭。
- 水品拆分可以支持非常大的數(shù)據(jù)量。需要注意的一點(diǎn)是:分表僅僅是解決了單一表數(shù)據(jù)過(guò)大的問(wèn)題疾呻,但由于表的數(shù)據(jù)還是在同一臺(tái)機(jī)器上,其實(shí)對(duì)于提升MySQL并發(fā)能力沒(méi)有什么意義写半,所以 水品拆分最好分庫(kù) 岸蜗。
- 水平拆分能夠 支持非常大的數(shù)據(jù)量存儲(chǔ),應(yīng)用端改造也少叠蝇,但 分片事務(wù)難以解決 璃岳,跨界點(diǎn)Join性能較差,邏輯復(fù)雜悔捶×蹇叮《Java工程師修煉之道》的作者推薦 盡量不要對(duì)數(shù)據(jù)進(jìn)行分片,因?yàn)椴鸱謺?huì)帶來(lái)邏輯蜕该、部署犁柜、運(yùn)維的各種復(fù)雜度 ,一般的數(shù)據(jù)表在優(yōu)化得當(dāng)?shù)那闆r下支撐千萬(wàn)以下的數(shù)據(jù)量是沒(méi)有太大問(wèn)題的堂淡。如果實(shí)在要分片馋缅,盡量選擇客戶端分片架構(gòu),這樣可以減少一次和中間件的網(wǎng)絡(luò)I/O绢淀。
- 下面補(bǔ)充一下數(shù)據(jù)庫(kù)分片的兩種常見(jiàn)方案:
- 客戶端代理: 分片邏輯在應(yīng)用端萤悴,封裝在jar包中,通過(guò)修改或者封裝JDBC層來(lái)實(shí)現(xiàn)皆的。 當(dāng)當(dāng)網(wǎng)的 Sharding-JDBC 覆履、阿里的TDDL是兩種比較常用的實(shí)現(xiàn)。
- 中間件代理: 在應(yīng)用和數(shù)據(jù)中間加了一個(gè)代理層。分片邏輯統(tǒng)一維護(hù)在中間件服務(wù)中硝全。 我們現(xiàn)在談的 Mycat 怪嫌、360的Atlas、網(wǎng)易的DDB等等都是這種架構(gòu)的實(shí)現(xiàn)柳沙。
五 Redis
關(guān)于 redis 必知必會(huì)的11個(gè)問(wèn)題岩灭!后兩個(gè)問(wèn)題,暫未更新赂鲤!如有需要噪径,可以關(guān)注,私信回復(fù)“架構(gòu)資料”即可 領(lǐng)取
- redis 簡(jiǎn)介
- 為什么要用 redis /為什么要用緩存
- 為什么要用 redis 而不用 map/guava 做緩存?
- redis 和 memcached 的區(qū)別
- redis 常見(jiàn)數(shù)據(jù)結(jié)構(gòu)以及使用場(chǎng)景分析
- redis 設(shè)置過(guò)期時(shí)間
- redis 內(nèi)存淘汰機(jī)制
- redis 持久化機(jī)制(怎么保證 redis 掛掉之后再重啟數(shù)據(jù)可以進(jìn)行恢復(fù))
- 緩存雪崩和緩存穿透問(wèn)題解決方案
- 如何解決 Redis 的并發(fā)競(jìng)爭(zhēng) Key 問(wèn)題
- 如何保證緩存與數(shù)據(jù)庫(kù)雙寫時(shí)的數(shù)據(jù)一致性数初?
5.1 redis 簡(jiǎn)介
Redis 是一個(gè)開(kāi)源(BSD許可)的找爱,內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),它可以用作數(shù)據(jù)庫(kù)泡孩、緩存和消息中間件车摄。 它支持多種類型的數(shù)據(jù)結(jié)構(gòu),如 字符串(strings)仑鸥, 散列(hashes)吮播, 列表(lists), 集合(sets)眼俊, 有序集合(sorted sets) 與范圍查詢意狠, bitmaps, hyperloglogs 和 地理空間(geospatial) 索引半徑查詢疮胖。 Redis 內(nèi)置了 復(fù)制(replication)环戈,LUA腳本(Lua scripting), LRU驅(qū)動(dòng)事件(LRU eviction)澎灸,事務(wù)(transactions) 和不同級(jí)別的 磁盤持久化(persistence)院塞, 并通過(guò) Redis哨兵(Sentinel)和自動(dòng) 分區(qū)(Cluster)提供高可用性(high availability)。
5.2 為什么要用 redis /為什么要用緩存
主要從“高性能”和“高并發(fā)”這兩點(diǎn)來(lái)看待這個(gè)問(wèn)題性昭。
高性能:
假如用戶第一次訪問(wèn)數(shù)據(jù)庫(kù)中的某些數(shù)據(jù)拦止。這個(gè)過(guò)程會(huì)比較慢,因?yàn)槭菑挠脖P上讀取的巩梢。將該用戶訪問(wèn)的數(shù)據(jù)存在數(shù)緩存中创泄,這樣下一次再訪問(wèn)這些數(shù)據(jù)的時(shí)候就可以直接從緩存中獲取了。操作緩存就是直接操作內(nèi)存括蝠,所以速度相當(dāng)快鞠抑。如果數(shù)據(jù)庫(kù)中的對(duì)應(yīng)數(shù)據(jù)改變的之后,同步改變緩存中相應(yīng)的數(shù)據(jù)即可忌警!
高并發(fā):
直接操作緩存能夠承受的請(qǐng)求是遠(yuǎn)遠(yuǎn)大于直接訪問(wèn)數(shù)據(jù)庫(kù)的搁拙,所以我們可以考慮把數(shù)據(jù)庫(kù)中的部分?jǐn)?shù)據(jù)轉(zhuǎn)移到緩存中去秒梳,這樣用戶的一部分請(qǐng)求會(huì)直接到緩存這里而不用經(jīng)過(guò)數(shù)據(jù)庫(kù)。
5.3 為什么要用 redis 而不用 map/guava 做緩存?
緩存分為本地緩存和分布式緩存箕速。以java為例酪碘,使用自帶的map或者guava實(shí)現(xiàn)的是本地緩存,最主要的特點(diǎn)是輕量以及快速盐茎,生命周期隨著 jvm 的銷毀而結(jié)束兴垦,并且在多實(shí)例的情況下,每個(gè)實(shí)例都需要各自保存一份緩存字柠,緩存不具有一致性探越。
使用 redis 或 memcached 之類的稱為分布式緩存,在多實(shí)例的情況下窑业,各實(shí)例共用一份緩存數(shù)據(jù)钦幔,緩存具有一致性。缺點(diǎn)是需要保持 redis 或 memcached服務(wù)的高可用常柄,整個(gè)程序架構(gòu)上較為復(fù)雜鲤氢。
5.4 redis 和 memcached 的區(qū)別
對(duì)于 redis 和 memcached 我總結(jié)了下面四點(diǎn)。現(xiàn)在公司一般都是用 redis 來(lái)實(shí)現(xiàn)緩存西潘,而且 redis 自身也越來(lái)越強(qiáng)大了卷玉!
- redis支持更豐富的數(shù)據(jù)類型(支持更復(fù)雜的應(yīng)用場(chǎng)景):Redis不僅僅支持簡(jiǎn)單的k/v類型的數(shù)據(jù),同時(shí)還提供list秸架,set揍庄,zset,hash等數(shù)據(jù)結(jié)構(gòu)的存儲(chǔ)东抹。memcache支持簡(jiǎn)單的數(shù)據(jù)類型,String沃测。
- Redis支持?jǐn)?shù)據(jù)的持久化缭黔,可以將內(nèi)存中的數(shù)據(jù)保持在磁盤中,重啟的時(shí)候可以再次加載進(jìn)行使用,而Memecache把數(shù)據(jù)全部存在內(nèi)存之中蒂破。
- 集群模式:memcached沒(méi)有原生的集群模式馏谨,需要依靠客戶端來(lái)實(shí)現(xiàn)往集群中分片寫入數(shù)據(jù);但是redis目前是原生支持cluster模式的附迷,redis官方就是支持redis cluster集群模式的惧互,比memcached來(lái)說(shuō)要更好。
- Memcached是多線程喇伯,非阻塞IO復(fù)用的網(wǎng)絡(luò)模型喊儡;Redis使用單線程的多路 IO 復(fù)用模型。
來(lái)自網(wǎng)絡(luò)上的一張圖稻据,這里分享給大家艾猜!
5.5 redis 常見(jiàn)數(shù)據(jù)結(jié)構(gòu)以及使用場(chǎng)景分析
1. String
常用命令: set,get,decr,incr,mget 等。
String數(shù)據(jù)結(jié)構(gòu)是簡(jiǎn)單的key-value類型,value其實(shí)不僅可以是String匆赃,也可以是數(shù)字淤毛。 常規(guī)key-value緩存應(yīng)用; 常規(guī)計(jì)數(shù):微博數(shù)算柳,粉絲數(shù)等低淡。
2.Hash
常用命令: hget,hset,hgetall 等。
Hash 是一個(gè) string 類型的 field 和 value 的映射表瞬项,hash 特別適合用于存儲(chǔ)對(duì)象蔗蹋,后續(xù)操作的時(shí)候,你可以直接僅僅修改這個(gè)對(duì)象中的某個(gè)字段的值滥壕。 比如我們可以Hash數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)用戶信息纸颜,商品信息等等。比如下面我就用 hash 類型存放了我本人的一些信息:
<pre style="box-sizing: border-box; font-family: inherit; font-size: 16px; margin: 1em 0px; padding: 12px 10px; white-space: pre-wrap; border: 1px solid rgb(232, 232, 232); position: relative; line-height: 1.5; color: rgb(153, 153, 153); background: rgb(244, 245, 246); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">key=JavaUser293847
value={
“id”: 1,
“name”: “SnailClimb”,
“age”: 22,
“l(fā)ocation”: “Wuhan, Hubei”
}
復(fù)制代碼
</pre>
3.List
常用命令: lpush,rpush,lpop,rpop,lrange等
list就是鏈表绎橘,Redis list的應(yīng)用場(chǎng)景非常多胁孙,也是Redis最重要的數(shù)據(jù)結(jié)構(gòu)之一,比如微博的關(guān)注列表称鳞,粉絲列表涮较,消息列表等功能都可以用Redis的 list 結(jié)構(gòu)來(lái)實(shí)現(xiàn)。
Redis list 的實(shí)現(xiàn)為一個(gè)雙向鏈表冈止,即可以支持反向查找和遍歷狂票,更方便操作,不過(guò)帶來(lái)了部分額外的內(nèi)存開(kāi)銷熙暴。
另外可以通過(guò) lrange 命令闺属,就是從某個(gè)元素開(kāi)始讀取多少個(gè)元素,可以基于 list 實(shí)現(xiàn)分頁(yè)查詢周霉,這個(gè)很棒的一個(gè)功能掂器,基于 redis 實(shí)現(xiàn)簡(jiǎn)單的高性能分頁(yè),可以做類似微博那種下拉不斷分頁(yè)的東西(一頁(yè)一頁(yè)的往下走)俱箱,性能高国瓮。
4.Set
常用命令: sadd,spop,smembers,sunion 等
set對(duì)外提供的功能與list類似是一個(gè)列表的功能,特殊之處在于set是可以自動(dòng)排重的狞谱。
當(dāng)你需要存儲(chǔ)一個(gè)列表數(shù)據(jù)乃摹,又不希望出現(xiàn)重復(fù)數(shù)據(jù)時(shí),set是一個(gè)很好的選擇跟衅,并且set提供了判斷某個(gè)成員是否在一個(gè)set集合內(nèi)的重要接口孵睬,這個(gè)也是list所不能提供的∮虢铮可以基于 set 輕易實(shí)現(xiàn)交集肪康、并集荚恶、差集的操作。
比如:在微博應(yīng)用中磷支,可以將一個(gè)用戶所有的關(guān)注人存在一個(gè)集合中谒撼,將其所有粉絲存在一個(gè)集合。Redis可以非常方便的實(shí)現(xiàn)如共同關(guān)注雾狈、共同粉絲廓潜、共同喜好等功能。這個(gè)過(guò)程也就是求交集的過(guò)程善榛,具體命令如下:
<pre style="box-sizing: border-box; font-family: inherit; font-size: 16px; margin: 1em 0px; padding: 12px 10px; white-space: pre-wrap; border: 1px solid rgb(232, 232, 232); position: relative; line-height: 1.5; color: rgb(153, 153, 153); background: rgb(244, 245, 246); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">sinterstore key1 key2 key3 將交集存在key1內(nèi)
復(fù)制代碼
</pre>
5.Sorted Set
常用命令: zadd,zrange,zrem,zcard等
和set相比辩蛋,sorted set增加了一個(gè)權(quán)重參數(shù)score,使得集合中的元素能夠按score進(jìn)行有序排列移盆。
舉例: 在直播系統(tǒng)中悼院,實(shí)時(shí)排行信息包含直播間在線用戶列表,各種禮物排行榜咒循,彈幕消息(可以理解為按消息維度的消息排行榜)等信息据途,適合使用 Redis 中的 SortedSet 結(jié)構(gòu)進(jìn)行存儲(chǔ)。
5.6 redis 設(shè)置過(guò)期時(shí)間
Redis中有個(gè)設(shè)置時(shí)間過(guò)期的功能叙甸,即對(duì)存儲(chǔ)在 redis 數(shù)據(jù)庫(kù)中的值可以設(shè)置一個(gè)過(guò)期時(shí)間颖医。作為一個(gè)緩存數(shù)據(jù)庫(kù),這是非常實(shí)用的裆蒸。如我們一般項(xiàng)目中的token或者一些登錄信息熔萧,尤其是短信驗(yàn)證碼都是有時(shí)間限制的,按照傳統(tǒng)的數(shù)據(jù)庫(kù)處理方式僚祷,一般都是自己判斷過(guò)期佛致,這樣無(wú)疑會(huì)嚴(yán)重影響項(xiàng)目性能。
我們set key的時(shí)候辙谜,都可以給一個(gè)expire time晌杰,就是過(guò)期時(shí)間,通過(guò)過(guò)期時(shí)間我們可以指定這個(gè) key 可以存貨的時(shí)間筷弦。
如果假設(shè)你設(shè)置一個(gè)一批 key 只能存活1個(gè)小時(shí),那么接下來(lái)1小時(shí)后抑诸,redis是怎么對(duì)這批key進(jìn)行刪除的烂琴?
定期刪除+惰性刪除。
通過(guò)名字大概就能猜出這兩個(gè)刪除方式的意思了蜕乡。
- 定期刪除:redis默認(rèn)是每隔 100ms 就隨機(jī)抽取一些設(shè)置了過(guò)期時(shí)間的key奸绷,檢查其是否過(guò)期,如果過(guò)期就刪除层玲。注意這里是隨機(jī)抽取的号醉。為什么要隨機(jī)呢反症?你想一想假如 redis 存了幾十萬(wàn)個(gè) key ,每隔100ms就遍歷所有的設(shè)置過(guò)期時(shí)間的 key 的話畔派,就會(huì)給 CPU 帶來(lái)很大的負(fù)載铅碍!
- 惰性刪除 :定期刪除可能會(huì)導(dǎo)致很多過(guò)期 key 到了時(shí)間并沒(méi)有被刪除掉。所以就有了惰性刪除线椰。假如你的過(guò)期 key胞谈,靠定期刪除沒(méi)有被刪除掉,還停留在內(nèi)存里憨愉,除非你的系統(tǒng)去查一下那個(gè) key烦绳,才會(huì)被redis給刪除掉。這就是所謂的惰性刪除配紫,也是夠懶的哈径密!
但是僅僅通過(guò)設(shè)置過(guò)期時(shí)間還是有問(wèn)題的。我們想一下:如果定期刪除漏掉了很多過(guò)期 key躺孝,然后你也沒(méi)及時(shí)去查享扔,也就沒(méi)走惰性刪除,此時(shí)會(huì)怎么樣括细?如果大量過(guò)期key堆積在內(nèi)存里伪很,導(dǎo)致redis內(nèi)存塊耗盡了。怎么解決這個(gè)問(wèn)題呢奋单?
redis 內(nèi)存淘汰機(jī)制锉试。
5.7 redis 內(nèi)存淘汰機(jī)制(MySQL里有2000w數(shù)據(jù),Redis中只存20w的數(shù)據(jù)览濒,如何保證Redis中的數(shù)據(jù)都是熱點(diǎn)數(shù)據(jù)呆盖?)
redis 配置文件 redis.conf 中有相關(guān)注釋,我這里就不貼了贷笛,大家可以自行查閱或者通過(guò)這個(gè)網(wǎng)址查看: download.redis.io/redis-stabl…
redis 提供 6種數(shù)據(jù)淘汰策略:
- volatile-lru:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰
- volatile-ttl:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過(guò)期的數(shù)據(jù)淘汰
- volatile-random:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中任意選擇數(shù)據(jù)淘汰
- allkeys-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)应又,在鍵空間中,移除最近最少使用的key(這個(gè)是最常用的).
- allkeys-random:從數(shù)據(jù)集(server.db[i].dict)中任意選擇數(shù)據(jù)淘汰
- no-enviction:禁止驅(qū)逐數(shù)據(jù)乏苦,也就是說(shuō)當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí)株扛,新寫入操作會(huì)報(bào)錯(cuò)。這個(gè)應(yīng)該沒(méi)人使用吧汇荐!
備注: 關(guān)于 redis 設(shè)置過(guò)期時(shí)間以及內(nèi)存淘汰機(jī)制洞就,我這里只是簡(jiǎn)單的總結(jié)一下,后面會(huì)專門寫一篇文章來(lái)總結(jié)掀淘!
5.8 redis 持久化機(jī)制(怎么保證 redis 掛掉之后再重啟數(shù)據(jù)可以進(jìn)行恢復(fù))
很多時(shí)候我們需要持久化數(shù)據(jù)也就是將內(nèi)存中的數(shù)據(jù)寫入到硬盤里面旬蟋,大部分原因是為了之后重用數(shù)據(jù)(比如重啟機(jī)器、機(jī)器故障之后回復(fù)數(shù)據(jù))革娄,或者是為了防止系統(tǒng)故障而將數(shù)據(jù)備份到一個(gè)遠(yuǎn)程位置倾贰。
Redis不同于Memcached的很重一點(diǎn)就是冕碟,Redis支持持久化,而且支持兩種不同的持久化操作匆浙。Redis的一種持久化方式叫快照(snapshotting安寺,RDB),另一種方式是只追加文件(append-only file,AOF).這兩種方法各有千秋,下面我會(huì)詳細(xì)這兩種持久化方法是什么吞彤,怎么用我衬,如何選擇適合自己的持久化方法。
快照(snapshotting)持久化(RDB)
Redis可以通過(guò)創(chuàng)建快照來(lái)獲得存儲(chǔ)在內(nèi)存里面的數(shù)據(jù)在某個(gè)時(shí)間點(diǎn)上的副本饰恕。Redis創(chuàng)建快照之后挠羔,可以對(duì)快照進(jìn)行備份,可以將快照復(fù)制到其他服務(wù)器從而創(chuàng)建具有相同數(shù)據(jù)的服務(wù)器副本(Redis主從結(jié)構(gòu)埋嵌,主要用來(lái)提高Redis性能)破加,還可以將快照留在原地以便重啟服務(wù)器的時(shí)候使用。
快照持久化是Redis默認(rèn)采用的持久化方式雹嗦,在redis.conf配置文件中默認(rèn)有此下配置:
save 900 1 #在900秒(15分鐘)之后范舀,如果至少有1個(gè)key發(fā)生變化,Redis就會(huì)自動(dòng)觸發(fā)BGSAVE命令創(chuàng)建快照了罪。
save 300 10 #在300秒(5分鐘)之后锭环,如果至少有10個(gè)key發(fā)生變化,Redis就會(huì)自動(dòng)觸發(fā)BGSAVE命令創(chuàng)建快照泊藕。
save 60 10000 #在60秒(1分鐘)之后辅辩,如果至少有10000個(gè)key發(fā)生變化,Redis就會(huì)自動(dòng)觸發(fā)BGSAVE命令創(chuàng)建快照娃圆。
AOF(append-only file)持久化
與快照持久化相比玫锋,AOF持久化 的實(shí)時(shí)性更好,因此已成為主流的持久化方案讼呢。默認(rèn)情況下Redis沒(méi)有開(kāi)啟AOF(append only file)方式的持久化撩鹿,可以通過(guò)appendonly參數(shù)開(kāi)啟:
appendonly yes
開(kāi)啟AOF持久化后每執(zhí)行一條會(huì)更改Redis中的數(shù)據(jù)的命令,Redis就會(huì)將該命令寫入硬盤中的AOF文件悦屏。AOF文件的保存位置和RDB文件的位置相同节沦,都是通過(guò)dir參數(shù)設(shè)置的,默認(rèn)的文件名是appendonly.aof础爬。
在Redis的配置文件中存在三種不同的 AOF 持久化方式散劫,它們分別是:
appendfsync always #每次有數(shù)據(jù)修改發(fā)生時(shí)都會(huì)寫入AOF文件,這樣會(huì)嚴(yán)重降低Redis的速度
appendfsync everysec #每秒鐘同步一次,顯示地將多個(gè)寫命令同步到硬盤
appendfsync no #讓操作系統(tǒng)決定何時(shí)進(jìn)行同步
</pre>
為了兼顧數(shù)據(jù)和寫入性能幕帆,用戶可以考慮 appendfsync everysec選項(xiàng) ,讓Redis每秒同步一次AOF文件赖条,Redis性能幾乎沒(méi)受到任何影響失乾。而且這樣即使出現(xiàn)系統(tǒng)崩潰常熙,用戶最多只會(huì)丟失一秒之內(nèi)產(chǎn)生的數(shù)據(jù)。當(dāng)硬盤忙于執(zhí)行寫入操作的時(shí)候碱茁,Redis還會(huì)優(yōu)雅的放慢自己的速度以便適應(yīng)硬盤的最大寫入速度裸卫。
補(bǔ)充內(nèi)容:AOF 重寫
AOF重寫可以產(chǎn)生一個(gè)新的AOF文件,這個(gè)新的AOF文件和原有的AOF文件所保存的數(shù)據(jù)庫(kù)狀態(tài)一樣纽竣,但體積更小墓贿。
AOF重寫是一個(gè)有歧義的名字,該功能是通過(guò)讀取數(shù)據(jù)庫(kù)中的鍵值對(duì)來(lái)實(shí)現(xiàn)的蜓氨,程序無(wú)須對(duì)現(xiàn)有AOF文件進(jìn)行任伺讀入聋袋、分析或者寫人操作。
在執(zhí)行 BGREWRITEAOF 命令時(shí)穴吹,Redis 服務(wù)器會(huì)維護(hù)一個(gè) AOF 重寫緩沖區(qū)幽勒,該緩沖區(qū)會(huì)在子進(jìn)程創(chuàng)建新AOF文件期間,記錄服務(wù)器執(zhí)行的所有寫命令港令。當(dāng)子進(jìn)程完成創(chuàng)建新AOF文件的工作之后啥容,服務(wù)器會(huì)將重寫緩沖區(qū)中的所有內(nèi)容追加到新AOF文件的末尾,使得新舊兩個(gè)AOF文件所保存的數(shù)據(jù)庫(kù)狀態(tài)一致顷霹。最后咪惠,服務(wù)器用新的AOF文件替換舊的AOF文件,以此來(lái)完成AOF文件重寫操作
5.9 緩存雪崩和緩存穿透問(wèn)題解決方案
緩存雪崩
簡(jiǎn)介:緩存同一時(shí)間大面積的失效淋淀,所以遥昧,后面的請(qǐng)求都會(huì)落到數(shù)據(jù)庫(kù)上,造成數(shù)據(jù)庫(kù)短時(shí)間內(nèi)承受大量請(qǐng)求而崩掉绅喉。
解決辦法(中華石杉老師在他的視頻中提到過(guò)):
- 事前:盡量保證整個(gè) redis 集群的高可用性渠鸽,發(fā)現(xiàn)機(jī)器宕機(jī)盡快補(bǔ)上。選擇合適的內(nèi)存淘汰策略柴罐。
- 事中:本地ehcache緩存 + hystrix限流&降級(jí)徽缚,避免MySQL崩掉
- 事后:利用 redis 持久化機(jī)制保存的數(shù)據(jù)盡快恢復(fù)緩存
緩存穿透
簡(jiǎn)介:一般是黑客故意去請(qǐng)求緩存中不存在的數(shù)據(jù),導(dǎo)致所有的請(qǐng)求都落到數(shù)據(jù)庫(kù)上革屠,造成數(shù)據(jù)庫(kù)短時(shí)間內(nèi)承受大量請(qǐng)求而崩掉凿试。
解決辦法: 有很多種方法可以有效地解決緩存穿透問(wèn)題,最常見(jiàn)的則是采用布隆過(guò)濾器似芝,將所有可能存在的數(shù)據(jù)哈希到一個(gè)足夠大的bitmap中那婉,一個(gè)一定不存在的數(shù)據(jù)會(huì)被 這個(gè)bitmap攔截掉,從而避免了對(duì)底層存儲(chǔ)系統(tǒng)的查詢壓力党瓮。另外也有一個(gè)更為簡(jiǎn)單粗暴的方法(我們采用的就是這種)详炬,如果一個(gè)查詢返回的數(shù)據(jù)為空(不管是數(shù) 據(jù)不存在颈将,還是系統(tǒng)故障),我們?nèi)匀话堰@個(gè)空結(jié)果進(jìn)行緩存炊豪,但它的過(guò)期時(shí)間會(huì)很短荞下,最長(zhǎng)不超過(guò)五分鐘。
六 Java
6.1 Java 基礎(chǔ)知識(shí)
重載和重寫的區(qū)別
重載: 發(fā)生在同一個(gè)類中隐岛,方法名必須相同猫妙,參數(shù)類型不同、個(gè)數(shù)不同聚凹、順序不同割坠,方法返回值和訪問(wèn)修飾符可以不同,發(fā)生在編譯時(shí)妒牙。
重寫: 發(fā)生在父子類中彼哼,方法名、參數(shù)列表必須相同单旁,返回值范圍小于等于父類沪羔,拋出的異常范圍小于等于父類,訪問(wèn)修飾符范圍大于等于父類象浑;如果父類方法訪問(wèn)修飾符為 private 則子類就不能重寫該方法蔫饰。
String 和 StringBuffer、StringBuilder 的區(qū)別是什么愉豺?String 為什么是不可變的篓吁?
可變性
簡(jiǎn)單的來(lái)說(shuō):String 類中使用 final 關(guān)鍵字字符數(shù)組保存字符串,private?final?char?value[]蚪拦,所以 String 對(duì)象是不可變的杖剪。而StringBuilder 與 StringBuffer 都繼承自 AbstractStringBuilder 類,在 AbstractStringBuilder 中也是使用字符數(shù)組保存字符串char[]value 但是沒(méi)有用 final 關(guān)鍵字修飾驰贷,所以這兩種對(duì)象都是可變的盛嘿。
StringBuilder 與 StringBuffer 的構(gòu)造方法都是調(diào)用父類構(gòu)造方法也就是 AbstractStringBuilder 實(shí)現(xiàn)的,大家可以自行查閱源碼括袒。
AbstractStringBuilder.java
abstract class AbstractStringBuilder implements Appendable, CharSequence {
char[] value;
int count;
AbstractStringBuilder() {
}
AbstractStringBuilder(int capacity) {
value = new char[capacity];
}
線程安全性
String 中的對(duì)象是不可變的次兆,也就可以理解為常量,線程安全锹锰。AbstractStringBuilder 是 StringBuilder 與 StringBuffer 的公共父類芥炭,定義了一些字符串的基本操作,如 expandCapacity恃慧、append园蝠、insert、indexOf 等公共方法痢士。StringBuffer 對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖彪薛,所以是線程安全的。StringBuilder 并沒(méi)有對(duì)方法進(jìn)行加同步鎖,所以是非線程安全的陪汽。
性能
每次對(duì) String 類型進(jìn)行改變的時(shí)候训唱,都會(huì)生成一個(gè)新的 String 對(duì)象,然后將指針指向新的 String 對(duì)象挚冤。StringBuffer 每次都會(huì)對(duì) StringBuffer 對(duì)象本身進(jìn)行操作,而不是生成新的對(duì)象并改變對(duì)象引用赞庶。相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升训挡,但卻要冒多線程不安全的風(fēng)險(xiǎn)。
對(duì)于三者使用的總結(jié):
- 操作少量的數(shù)據(jù) = String
- 單線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) = StringBuilder
- 多線程操作字符串緩沖區(qū)下操作大量數(shù)據(jù) = StringBuffer
自動(dòng)裝箱與拆箱
裝箱:將基本類型用它們對(duì)應(yīng)的引用類型包裝起來(lái)歧强;
拆箱:將包裝類型轉(zhuǎn)換為基本數(shù)據(jù)類型澜薄;
== 與 equals
== : 它的作用是判斷兩個(gè)對(duì)象的地址是不是相等。即摊册,判斷兩個(gè)對(duì)象是不是同一個(gè)對(duì)象肤京。(基本數(shù)據(jù)類型==比較的是值,引用數(shù)據(jù)類型==比較的是內(nèi)存地址)
equals() : 它的作用也是判斷兩個(gè)對(duì)象是否相等茅特。但它一般有兩種使用情況:
- 情況1:類沒(méi)有覆蓋 equals() 方法忘分。則通過(guò) equals() 比較該類的兩個(gè)對(duì)象時(shí),等價(jià)于通過(guò)“==”比較這兩個(gè)對(duì)象白修。
- 情況2:類覆蓋了 equals() 方法妒峦。一般,我們都覆蓋 equals() 方法來(lái)兩個(gè)對(duì)象的內(nèi)容相等兵睛;若它們的內(nèi)容相等肯骇,則返回 true (即,認(rèn)為這兩個(gè)對(duì)象相等)祖很。
舉個(gè)例子:
public class test1 {
public static void main(String[] args) {
String a = new String("ab"); // a 為一個(gè)引用
String b = new String("ab"); // b為另一個(gè)引用,對(duì)象的內(nèi)容一樣
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 從常量池中查找
if (aa == bb) // true
System.out.println("aa==bb");
if (a == b) // false笛丙,非同一對(duì)象
System.out.println("a==b");
if (a.equals(b)) // true
System.out.println("aEQb");
if (42 == 42.0) { // true
System.out.println("true");
}
}
}
說(shuō)明:
- String 中的 equals 方法是被重寫過(guò)的,因?yàn)?object 的 equals 方法是比較的對(duì)象的內(nèi)存地址假颇,而 String 的 equals 方法比較的是對(duì)象的值胚鸯。
- 當(dāng)創(chuàng)建 String 類型的對(duì)象時(shí),虛擬機(jī)會(huì)在常量池中查找有沒(méi)有已經(jīng)存在的值和要?jiǎng)?chuàng)建的值相同的對(duì)象拆融,如果有就把它賦給當(dāng)前引用蠢琳。如果沒(méi)有就在常量池中重新創(chuàng)建一個(gè) String 對(duì)象。
關(guān)于 final 關(guān)鍵字的一些總結(jié)
final關(guān)鍵字主要用在三個(gè)地方:變量镜豹、方法傲须、類。
- 對(duì)于一個(gè)final變量趟脂,如果是基本數(shù)據(jù)類型的變量泰讽,則其數(shù)值一旦在初始化之后便不能更改;如果是引用類型的變量,則在對(duì)其初始化之后便不能再讓其指向另一個(gè)對(duì)象已卸。
- 當(dāng)用final修飾一個(gè)類時(shí)佛玄,表明這個(gè)類不能被繼承。final類中的所有成員方法都會(huì)被隱式地指定為final方法累澡。
- 使用final方法的原因有兩個(gè)梦抢。第一個(gè)原因是把方法鎖定,以防任何繼承類修改它的含義愧哟;第二個(gè)原因是效率奥吩。在早期的Java實(shí)現(xiàn)版本中,會(huì)將final方法轉(zhuǎn)為內(nèi)嵌調(diào)用蕊梧。但是如果方法過(guò)于龐大霞赫,可能看不到內(nèi)嵌調(diào)用帶來(lái)的任何性能提升(現(xiàn)在的Java版本已經(jīng)不需要使用final方法進(jìn)行這些優(yōu)化了)。類中所有的private方法都隱式地指定為fianl肥矢。
6.2 Java 集合框架
Arraylist 與 LinkedList 異同
- 1. 是否保證線程安全: ArrayList 和 LinkedList 都是不同步的端衰,也就是不保證線程安全;
- 2. 底層數(shù)據(jù)結(jié)構(gòu): Arraylist 底層使用的是Object數(shù)組甘改;LinkedList 底層使用的是雙向循環(huán)鏈表數(shù)據(jù)結(jié)構(gòu)旅东;
- 3. 插入和刪除是否受元素位置的影響: ① ArrayList 采用數(shù)組存儲(chǔ),所以插入和刪除元素的時(shí)間復(fù)雜度受元素位置的影響楼誓。 比如:執(zhí)行add(E e)方法的時(shí)候玉锌, ArrayList 會(huì)默認(rèn)在將指定的元素追加到此列表的末尾,這種情況時(shí)間復(fù)雜度就是O(1)疟羹。但是如果要在指定位置 i 插入和刪除元素的話(add(int index, E element))時(shí)間復(fù)雜度就為 O(n-i)主守。因?yàn)樵谶M(jìn)行上述操作的時(shí)候集合中第 i 和第 i 個(gè)元素之后的(n-i)個(gè)元素都要執(zhí)行向后位/向前移一位的操作。 ② LinkedList 采用鏈表存儲(chǔ)榄融,所以插入参淫,刪除元素時(shí)間復(fù)雜度不受元素位置的影響,都是近似 O(1)而數(shù)組為近似 O(n)愧杯。
- 4. 是否支持快速隨機(jī)訪問(wèn): LinkedList 不支持高效的隨機(jī)元素訪問(wèn)涎才,而ArrayList 實(shí)現(xiàn)了RandmoAccess 接口,所以有隨機(jī)訪問(wèn)功能力九∷M快速隨機(jī)訪問(wèn)就是通過(guò)元素的序號(hào)快速獲取元素對(duì)象(對(duì)應(yīng)于get(int index)方法)。
- 5. 內(nèi)存空間占用: ArrayList的空 間浪費(fèi)主要體現(xiàn)在在list列表的結(jié)尾會(huì)預(yù)留一定的容量空間跌前,而LinkedList的空間花費(fèi)則體現(xiàn)在它的每一個(gè)元素都需要消耗比ArrayList更多的空間(因?yàn)橐娣胖苯雍罄^和直接前驅(qū)以及數(shù)據(jù))棕兼。
補(bǔ)充:數(shù)據(jù)結(jié)構(gòu)基礎(chǔ)之雙向鏈表
雙向鏈表也叫雙鏈表,是鏈表的一種抵乓,它的每個(gè)數(shù)據(jù)結(jié)點(diǎn)中都有兩個(gè)指針伴挚,分別指向直接后繼和直接前驅(qū)靶衍。所以,從雙向鏈表中的任意一個(gè)結(jié)點(diǎn)開(kāi)始茎芋,都可以很方便地訪問(wèn)它的前驅(qū)結(jié)點(diǎn)和后繼結(jié)點(diǎn)颅眶。一般我們都構(gòu)造雙向循環(huán)鏈表,如下圖所示田弥,同時(shí)下圖也是LinkedList 底層使用的是雙向循環(huán)鏈表數(shù)據(jù)結(jié)構(gòu)涛酗。
ArrayList 與 Vector 區(qū)別
Vector類的所有方法都是同步的⊥迪茫可以由兩個(gè)線程安全地訪問(wèn)一個(gè)Vector對(duì)象煤杀、但是一個(gè)線程訪問(wèn)Vector的話代碼要在同步操作上耗費(fèi)大量的時(shí)間。
Arraylist不是同步的沪哺,所以在不需要保證線程安全時(shí)時(shí)建議使用Arraylist。
HashMap的底層實(shí)現(xiàn)
①JDK1.8之前
JDK1.8 之前 HashMap 底層是 數(shù)組和鏈表 結(jié)合在一起使用也就是 鏈表散列酌儒。HashMap 通過(guò) key 的 hashCode 經(jīng)過(guò)擾動(dòng)函數(shù)處理過(guò)后得到 hash 值辜妓,然后通過(guò) (n - 1) & hash 判斷當(dāng)前元素存放的位置(這里的 n 指的時(shí)數(shù)組的長(zhǎng)度),如果當(dāng)前位置存在元素的話忌怎,就判斷該元素與要存入的元素的 hash 值以及 key 是否相同籍滴,如果相同的話,直接覆蓋榴啸,不相同就通過(guò)拉鏈法解決沖突孽惰。
所謂擾動(dòng)函數(shù)指的就是 HashMap 的 hash 方法。使用 hash 方法也就是擾動(dòng)函數(shù)是為了防止一些實(shí)現(xiàn)比較差的 hashCode() 方法 換句話說(shuō)使用擾動(dòng)函數(shù)之后可以減少碰撞鸥印。
JDK 1.8 HashMap 的 hash 方法源碼:
JDK 1.8 的 hash方法 相比于 JDK 1.7 hash 方法更加簡(jiǎn)化勋功,但是原理不變。
static final int hash(Object key) {
int h;
// key.hashCode():返回散列值也就是hashcode
// ^ :按位異或
// >>>:無(wú)符號(hào)右移库说,忽略符號(hào)位狂鞋,空位都以0補(bǔ)齊
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
對(duì)比一下 JDK1.7的 HashMap 的 hash 方法源碼.
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
相比于 JDK1.8 的 hash 方法 ,JDK 1.7 的 hash 方法的性能會(huì)稍差一點(diǎn)點(diǎn)潜的,因?yàn)楫吘箶_動(dòng)了 4 次骚揍。
所謂 “拉鏈法” 就是:將鏈表和數(shù)組相結(jié)合。也就是說(shuō)創(chuàng)建一個(gè)鏈表數(shù)組啰挪,數(shù)組中每一格就是一個(gè)鏈表信不。若遇到哈希沖突,則將沖突的值加到鏈表中即可亡呵。
②JDK1.8之后
相比于之前的版本抽活, JDK1.8之后在解決哈希沖突時(shí)有了較大的變化,當(dāng)鏈表長(zhǎng)度大于閾值(默認(rèn)為8)時(shí)政己,將鏈表轉(zhuǎn)化為紅黑樹(shù)酌壕,以減少搜索時(shí)間掏愁。
TreeMap、TreeSet以及JDK1.8之后的HashMap底層都用到了紅黑樹(shù)卵牍。紅黑樹(shù)就是為了解決二叉查找樹(shù)的缺陷果港,因?yàn)槎娌檎覙?shù)在某些情況下會(huì)退化成一個(gè)線性結(jié)構(gòu)。
設(shè)計(jì)模式
設(shè)計(jì)模式比較常見(jiàn)的就是讓你手寫一個(gè)單例模式(注意單例模式的幾種不同的實(shí)現(xiàn)方法)或者讓你說(shuō)一下某個(gè)常見(jiàn)的設(shè)計(jì)模式在你的項(xiàng)目中是如何使用的糊昙,另外面試官還有可能問(wèn)你抽象工廠和工廠方法模式的區(qū)別辛掠、工廠模式的思想這樣的問(wèn)題。
建議把代理模式释牺、觀察者模式萝衩、(抽象)工廠模式好好看一下,這三個(gè)設(shè)計(jì)模式也很重要没咙。
七 數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu)比較常問(wèn)的就是:二叉樹(shù)猩谊、紅黑樹(shù)(很可能讓你手繪一個(gè)紅黑樹(shù)出來(lái)哦!)祭刚、二叉查找樹(shù)(BST)牌捷、平衡二叉樹(shù)(Self-balancing binary search tree)、B-樹(shù)涡驮,B+樹(shù)與B樹(shù)的優(yōu)缺點(diǎn)比較*暗甥、 LSM 樹(shù)這些知識(shí)點(diǎn)。
數(shù)據(jù)結(jié)構(gòu)很重要捉捅,而且學(xué)起來(lái)也相對(duì)要難一些撤防。建議學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)一定要循序漸進(jìn)的來(lái),一步一個(gè)腳印的走好棒口。一定要搞懂原理寄月,最好自己能用代碼實(shí)現(xiàn)一遍。
八 算法
常見(jiàn)的加密算法陌凳、排序算法都需要自己提前了解一下剥懒,排序算法最好自己能夠獨(dú)立手寫出來(lái)。
我覺(jué)得面試中最刺激合敦、最有壓力或者說(shuō)最有挑戰(zhàn)的一個(gè)環(huán)節(jié)就是手撕算法了初橘。面試中大部分算法題目都是來(lái)自于Leetcode、劍指offer上面充岛,建議大家可以每天擠出一點(diǎn)時(shí)間刷一下算法題保檐。
九 Spring
Spring一般是不可避免的,如果你的簡(jiǎn)歷上注明了你會(huì)Spring Boot或者Spring Cloud的話崔梗,那么面試官也可能會(huì)同時(shí)問(wèn)你這兩個(gè)技術(shù),比如他可能會(huì)問(wèn)你springboot和spring的區(qū)別夜只。 所以,一定要謹(jǐn)慎對(duì)待寫在簡(jiǎn)歷上的東西蒜魄,一定要對(duì)簡(jiǎn)歷上的東西非常熟悉扔亥。
另外场躯,AOP實(shí)現(xiàn)原理、動(dòng)態(tài)代理和靜態(tài)代理旅挤、Spring IOC的初始化過(guò)程踢关、IOC原理、自己怎么實(shí)現(xiàn)一個(gè)IOC容器粘茄? 這些東西都是經(jīng)常會(huì)被問(wèn)到的签舞。
9.1 Spring Bean 的作用域
9.2 Spring 事務(wù)中的隔離級(jí)別
TransactionDefinition 接口中定義了五個(gè)表示隔離級(jí)別的常量:
- TransactionDefinition.ISOLATION_DEFAULT: 使用后端數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別,Mysql 默認(rèn)采用的 REPEATABLE_READ隔離級(jí)別 Oracle 默認(rèn)采用的 READ_COMMITTED隔離級(jí)別.
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔離級(jí)別柒瓣,允許讀取尚未提交的數(shù)據(jù)變更儒搭,可能會(huì)導(dǎo)致臟讀、幻讀或不可重復(fù)讀
- TransactionDefinition.ISOLATION_READ_COMMITTED: 允許讀取并發(fā)事務(wù)已經(jīng)提交的數(shù)據(jù)芙贫,可以阻止臟讀搂鲫,但是幻讀或不可重復(fù)讀仍有可能發(fā)生
- TransactionDefinition.ISOLATION_REPEATABLE_READ: 對(duì)同一字段的多次讀取結(jié)果都是一致的,除非數(shù)據(jù)是被本身事務(wù)自己所修改磺平,可以阻止臟讀和不可重復(fù)讀默穴,但幻讀仍有可能發(fā)生。
- TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔離級(jí)別褪秀,完全服從ACID的隔離級(jí)別。所有的事務(wù)依次逐個(gè)執(zhí)行薛训,這樣事務(wù)之間就完全不可能產(chǎn)生干擾媒吗,也就是說(shuō),該級(jí)別可以防止臟讀乙埃、不可重復(fù)讀以及幻讀闸英。但是這將嚴(yán)重影響程序的性能。通常情況下也不會(huì)用到該級(jí)別介袜。
9.3 Spring 事務(wù)中的事務(wù)傳播行為
支持當(dāng)前事務(wù)的情況:
- TransactionDefinition.PROPAGATION_REQUIRED: 如果當(dāng)前存在事務(wù)甫何,則加入該事務(wù);如果當(dāng)前沒(méi)有事務(wù)遇伞,則創(chuàng)建一個(gè)新的事務(wù)辙喂。
- TransactionDefinition.PROPAGATION_SUPPORTS: 如果當(dāng)前存在事務(wù),則加入該事務(wù)鸠珠;如果當(dāng)前沒(méi)有事務(wù)巍耗,則以非事務(wù)的方式繼續(xù)運(yùn)行。
- TransactionDefinition.PROPAGATION_MANDATORY: 如果當(dāng)前存在事務(wù)渐排,則加入該事務(wù)炬太;如果當(dāng)前沒(méi)有事務(wù),則拋出異常驯耻。(mandatory:強(qiáng)制性)
不支持當(dāng)前事務(wù)的情況:
- TransactionDefinition.PROPAGATION_REQUIRES_NEW: 創(chuàng)建一個(gè)新的事務(wù)亲族,如果當(dāng)前存在事務(wù)炒考,則把當(dāng)前事務(wù)掛起。
- TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事務(wù)方式運(yùn)行霎迫,如果當(dāng)前存在事務(wù)斋枢,則把當(dāng)前事務(wù)掛起。
- TransactionDefinition.PROPAGATION_NEVER: 以非事務(wù)方式運(yùn)行女气,如果當(dāng)前存在事務(wù)杏慰,則拋出異常。
其他情況:
- TransactionDefinition.PROPAGATION_NESTED: 如果當(dāng)前存在事務(wù)炼鞠,則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來(lái)運(yùn)行缘滥;如果當(dāng)前沒(méi)有事務(wù),則該取值等價(jià)于TransactionDefinition.PROPAGATION_REQUIRED谒主。
9.4 AOP
AOP思想的實(shí)現(xiàn)一般都是基于 代理模式 朝扼,在JAVA中一般采用JDK動(dòng)態(tài)代理模式,但是我們都知道霎肯,JDK動(dòng)態(tài)代理模式只能代理接口而不能代理類擎颖。因此,Spring AOP 會(huì)這樣子來(lái)進(jìn)行切換观游,因?yàn)镾pring AOP 同時(shí)支持 CGLIB搂捧、ASPECTJ、JDK動(dòng)態(tài)代理懂缕。
- 如果目標(biāo)對(duì)象的實(shí)現(xiàn)類實(shí)現(xiàn)了接口允跑,Spring AOP 將會(huì)采用 JDK 動(dòng)態(tài)代理來(lái)生成 AOP 代理類;
- 如果目標(biāo)對(duì)象的實(shí)現(xiàn)類沒(méi)有實(shí)現(xiàn)接口搪柑,Spring AOP 將會(huì)采用 CGLIB 來(lái)生成 AOP 代理類——不過(guò)這個(gè)選擇過(guò)程對(duì)開(kāi)發(fā)者完全透明聋丝、開(kāi)發(fā)者也無(wú)需關(guān)心。
9.5 IOC
Spring IOC的初始化過(guò)程:
十 實(shí)際場(chǎng)景題
我覺(jué)得實(shí)際場(chǎng)景題就是對(duì)你的知識(shí)運(yùn)用能力以及思維能力的考察工碾。建議大家在平時(shí)養(yǎng)成多思考問(wèn)題的習(xí)慣弱睦,這樣面試的時(shí)候碰到這樣的問(wèn)題就不至于慌了。另外渊额,如果自己實(shí)在不會(huì)就給面試官委婉的說(shuō)一下况木,面試官可能會(huì)給你提醒一下。切忌不懂裝懂旬迹,亂答一氣焦读。 面試官可能會(huì)問(wèn)你類似這樣的問(wèn)題:①假設(shè)你要做一個(gè)銀行app,有可能碰到多個(gè)人同時(shí)向一個(gè)賬戶打錢的情況舱权,有可能碰到什么問(wèn)題矗晃,如何解決(鎖)②你是怎么保證你的代碼質(zhì)量和正確性的?③下單過(guò)程中是下訂單減庫(kù)存還是付款減庫(kù)存宴倍,分析一下兩者的優(yōu)劣张症;④同時(shí)給10萬(wàn)個(gè)人發(fā)工資仓技,怎么樣設(shè)計(jì)并發(fā)方案,能確保在1分鐘內(nèi)全部發(fā)完俗他。⑤如果讓你設(shè)計(jì)xxx系統(tǒng)的話脖捻,你會(huì)如何設(shè)計(jì)。
寫在最后
最后兆衅,再?gòu)?qiáng)調(diào)幾點(diǎn):
- 一定要謹(jǐn)慎對(duì)待寫在簡(jiǎn)歷上的東西地沮,一定要對(duì)簡(jiǎn)歷上的東西非常熟悉。因?yàn)橐话闱闆r下羡亩,面試官都是會(huì)根據(jù)你的簡(jiǎn)歷來(lái)問(wèn)的摩疑; 2. 能有一個(gè)上得了臺(tái)面的項(xiàng)目也非常重要,這很可能是面試官會(huì)大量發(fā)問(wèn)的地方畏铆,所以在面試之前好好回顧一下自己所做的項(xiàng)目雷袋;
- 和面試官聊基礎(chǔ)知識(shí)比如設(shè)計(jì)模式的使用、多線程的使用等等辞居,可以結(jié)合具體的項(xiàng)目場(chǎng)景或者是自己在平時(shí)是如何使用的楷怒;
- 注意自己開(kāi)源的Github項(xiàng)目,面試官可能會(huì)挖你的Github項(xiàng)目提問(wèn)瓦灶;
- 建議提前了解一下自己想要面試的公司的價(jià)值觀鸠删,判斷一下自己究竟是否適合這個(gè)公司。
另外贼陶,我個(gè)人覺(jué)得面試也像是一場(chǎng)全新的征程冶共,失敗和勝利都是平常之事。所以每界,勸各位不要因?yàn)槊嬖囀《倚摹适Ф分炯衣簟R膊灰驗(yàn)槊嬖囃ㄟ^(guò)而沾沾自喜眨层,等待你的將是更美好的未來(lái),繼續(xù)加油上荡!
初次之外趴樱,筆主也在這里給自己挖一個(gè)坑,關(guān)于 dubbo酪捡、zookeeper 等內(nèi)容我會(huì)在后續(xù)做一個(gè)系統(tǒng)總結(jié)叁征。保證大家看了之后,一定有收獲逛薇!
點(diǎn)此處https://shimo.im/docs/CxxT8QrghDRxrDC3獲绒嗵邸:Java高級(jí)架構(gòu)資料、源碼永罚、筆記啤呼、視頻 Dubbo卧秘、Redis、Netty官扣、zookeeper翅敌、Spring cloud、分布式惕蹄、高并發(fā)等架構(gòu)技術(shù)蚯涮。