
八月在即,馬上就是"金九銀十",又是跳槽招聘季。咱們這行公認(rèn)漲薪不如跳槽加的快。但不建議頻繁跳槽,還是要學(xué)會(huì)融合團(tuán)隊(duì),抓住每個(gè)機(jī)會(huì)提升技能。
蘇先生在這里給大家整理了一套各大互聯(lián)網(wǎng)公司面試都喜歡問的一些問題或者一些出場(chǎng)率很高的Java研發(fā)面試題,給在校招或者社招路上的你一臂之力。
目錄
- Spring
- Netty
- MySQL
- JVM
- Tomcat
- Mybatis
- Redis
- Kafka
- 讀者福利

一. Spring
1、什么是 Spring 框架?Spring 框架有哪些主要模塊?
Spring 框架是一個(gè)為 Java 應(yīng)用程序的開發(fā)提供了綜合、廣泛的基礎(chǔ)性支持的 Java 平臺(tái)。
Spring 幫助開發(fā)者解決了開發(fā)中基礎(chǔ)性的問題,使得開發(fā)人員可以專注于應(yīng)用程序的開發(fā)。
Spring 框架本身亦是按照設(shè)計(jì)模式精心打造,這使得我們可以在開發(fā)環(huán)境中安心的集成 Spring 框架,不必?fù)?dān)心 Spring 是如何在后臺(tái)進(jìn)行工作的。
Spring 框架至今已集成了 20 多個(gè)模塊。這些模塊主要被分如下圖所示的核心容器、數(shù)據(jù)訪問/集成,、Web、AOP(面向切面編程)、工具、消息和測(cè)試模塊。
2、什么是控制反轉(zhuǎn)(IOC)?什么是依賴注入?
控制反轉(zhuǎn)是應(yīng)用于軟件工程領(lǐng)域中的,在運(yùn)行時(shí)被裝配器對(duì)象來綁定耦合對(duì)象的一種編程技巧,對(duì)象之間耦合關(guān)系在編譯時(shí)通常是未知的。在傳統(tǒng)的編程方式中,業(yè) 務(wù)邏輯的流程是由應(yīng)用程序中的早已被設(shè)定好關(guān)聯(lián)關(guān)系的對(duì)象來決定的。在使用控制反轉(zhuǎn)的情況下,業(yè)務(wù)邏輯的流程是由對(duì)象關(guān)系 圖來決定的,該對(duì)象關(guān)系圖由裝配 器負(fù)責(zé)實(shí)例化,這種實(shí)現(xiàn)方式還可以將對(duì)象之間的關(guān)聯(lián)關(guān)系的定義抽象化。而綁定的過程是通過“依賴注入”實(shí)現(xiàn)的。
控制反轉(zhuǎn)是一種以給予應(yīng)用程序中目標(biāo)組件更多控制為目的設(shè)計(jì)范式,并在我們的實(shí)際工作中起到了有效的作用。
依賴注入是在編譯階段尚未知所需的功能是來自哪個(gè)的類的情況下,將其他對(duì)象所依賴的功能對(duì)象實(shí)例化的模式。這就需要一種機(jī)制用來激活相應(yīng)的組件以提供特定的功能,所以依賴注入是控制反轉(zhuǎn)的基礎(chǔ)。否則如果在組件不受框架控制的情況下,框架又怎么知道要?jiǎng)?chuàng)建哪個(gè)組件?
3、怎樣用注解的方式配置 Spring?
Spring 在 2.5 版本以后開始支持用注解的方式來配置依賴注入??梢杂米⒔獾姆绞絹硖娲?XML 方式的 bean 描述,可以將 bean 描述轉(zhuǎn)移到組件類的 內(nèi)部,只需要在相關(guān)類上、方法上或者字段聲明上使用注解即可。注解注入將會(huì)被容器在 XML 注入之前被處理,所以后者會(huì)覆蓋掉前者對(duì)于同一個(gè)屬性的處理結(jié)果。
注解裝配在 Spring 中是默認(rèn)關(guān)閉的。所以需要在 Spring 文件中配置一下才能使用基于注解的裝配模式。如果你想要在你的應(yīng)用程序中使用關(guān)于注解的方法的話,請(qǐng)參考如下的配置。
<beans>
<context:annotation-config/>
<!-- bean definitions go here -->
</beans>
在 <context:annotation-config/>標(biāo)簽配置完成以后,就可以用注解的方式在 Spring 中向?qū)傩?、方法和?gòu)造方法中自動(dòng)裝配變量。
下面是幾種比較重要的注解類型:
- @Required:該注解應(yīng)用于設(shè)值方法。
- @Autowired:該注解應(yīng)用于有值設(shè)值方法、非設(shè)值方法、構(gòu)造方法和變量。
- @Qualifier:該注解和@Autowired 注解搭配使用,用于消除特定 bean 自動(dòng)裝配的歧義。
- JSR-250 Annotations:Spring 支持基于 JSR-250 注解的以下注解,@Resource、@PostConstruct 和 @PreDestroy。

二. Netty
1、Netty 的特點(diǎn)?
一個(gè)高性能、異步事件驅(qū)動(dòng)的 NIO 框架,它提供了對(duì) TCP、UDP 和文件傳輸?shù)闹С质褂酶咝У?socket 底層,對(duì) epoll 空輪詢引起的 cpu 占用飆升在內(nèi)部進(jìn)行了處理,避免了直接使用 NIO 的陷阱,簡(jiǎn)化了 NIO 的處理方式。
采用多種 decoder/encoder 支持,對(duì) TCP 粘包/分包進(jìn)行自動(dòng)化處理可使用接受/處理線程池,提高連接效率,對(duì)重連、心跳檢測(cè)的簡(jiǎn)單支持可配置 IO 線程數(shù)、TCP 參數(shù), TCP 接收和發(fā)送緩沖區(qū)使用直接內(nèi)存代替堆內(nèi)存,通過內(nèi)存池的方式循環(huán)利用 ByteBuf通過引用計(jì)數(shù)器及時(shí)申請(qǐng)釋放不再引用的對(duì)象,降低了 GC 頻率使用單線程串行化的方式,高效的 Reactor 線程模型大量使用了 volitale、使用了 CAS 和原子類、線程安全類的使用、讀寫鎖的使用
2、Netty 的線程模型?
Netty 通過 Reactor 模型基于多路復(fù)用器接收并處理用戶請(qǐng)求,內(nèi)部實(shí)現(xiàn)了兩個(gè)線程池,boss 線程池和 work 線程池,其中 boss 線程池的線程負(fù)責(zé)處理請(qǐng)求的 accept 事件,當(dāng)接收到 accept 事件的請(qǐng)求時(shí),把對(duì)應(yīng)的 socket 封裝到一個(gè) NioSocketChannel 中,并交給 work線程池,其中 work 線程池負(fù)責(zé)請(qǐng)求的 read 和 write 事件,由對(duì)應(yīng)的 Handler 處理。
單線程模型:所有 I/O 操作都由一個(gè)線程完成,即多路復(fù)用、事件分發(fā)和處理都是在一個(gè)Reactor 線程上完成的。既要接收客戶端的連接請(qǐng)求,向服務(wù)端發(fā)起連接,又要發(fā)送/讀取請(qǐng)求或應(yīng)答/響應(yīng)消息。一個(gè) NIO 線程同時(shí)處理成百上千的鏈路,性能上無法支撐,速度慢,若線程進(jìn)入死循環(huán),整個(gè)程序不可用,對(duì)于高負(fù)載、大并發(fā)的應(yīng)用場(chǎng)景不合適。
多線程模型:有一個(gè) NIO 線程(Acceptor) 只負(fù)責(zé)監(jiān)聽服務(wù)端,接收客戶端的 TCP 連接請(qǐng)求;NIO 線程池負(fù)責(zé)網(wǎng)絡(luò) IO 的操作,即消息的讀取、解碼、編碼和發(fā)送;1 個(gè) NIO 線程可以同時(shí)處理 N 條鏈路,但是 1 個(gè)鏈路只對(duì)應(yīng) 1 個(gè) NIO 線程,這是為了防止發(fā)生并發(fā)操作問題。但在并發(fā)百萬客戶端連接或需要安全認(rèn)證時(shí),一個(gè) Acceptor 線程可能會(huì)存在性能不足問題。
主從多線程模型:Acceptor 線程用于綁定監(jiān)聽端口,接收客戶端連接,將 SocketChannel從主線程池的 Reactor 線程的多路復(fù)用器上移除,重新注冊(cè)到 Sub 線程池的線程上,用于 處理 I/O 的讀寫等操作,從而保證 mainReactor 只負(fù)責(zé)接入認(rèn)證、握手等操作;
3、BIO、NIO 和 AIO 的區(qū)別?
BIO:一個(gè)連接一個(gè)線程,客戶端有連接請(qǐng)求時(shí)服務(wù)器端就需要啟動(dòng)一個(gè)線程進(jìn)行處理。線程開銷大。
偽異步 IO:將請(qǐng)求連接放入線程池,一對(duì)多,但線程還是很寶貴的資源。
NIO:一個(gè)請(qǐng)求一個(gè)線程,但客戶端發(fā)送的連接請(qǐng)求都會(huì)注冊(cè)到多路復(fù)用器上,多路復(fù)用器輪詢到連接有 I/O 請(qǐng)求時(shí)才啟動(dòng)一個(gè)線程進(jìn)行處理。
AIO:一個(gè)有效請(qǐng)求一個(gè)線程,客戶端的 I/O 請(qǐng)求都是由 OS 先完成了再通知服務(wù)器應(yīng)用去啟動(dòng)線程進(jìn)行處理,BIO 是面向流的,NIO 是面向緩沖區(qū)的;BIO 的各種流是阻塞的。而 NIO 是非阻塞的;BIO的 Stream 是單向的,而 NIO 的 channel 是雙向的。
NIO 的特點(diǎn):事件驅(qū)動(dòng)模型、單線程處理多任務(wù)、非阻塞 I/O,I/O 讀寫不再阻塞,而是返回 0、基于 block 的傳輸比基于流的傳輸更高效、更高級(jí)的 IO 函數(shù) zero-copy、IO 多路復(fù)用大大提高了 Java 網(wǎng)絡(luò)應(yīng)用的可伸縮性和實(shí)用性?;?Reactor 線程模型。
在 Reactor 模式中,事件分發(fā)器等待某個(gè)事件或者可應(yīng)用或個(gè)操作的狀態(tài)發(fā)生,事件分發(fā)器就把這個(gè)事件傳給事先注冊(cè)的事件處理函數(shù)或者回調(diào)函數(shù),由后者來做實(shí)際的讀寫操作。如在 Reactor 中實(shí)現(xiàn)讀:注冊(cè)讀就緒事件和相應(yīng)的事件處理器、事件分發(fā)器等待事件、事件到來,激活分發(fā)器,分發(fā)器調(diào)用事件對(duì)應(yīng)的處理器、事件處理器完成實(shí)際的讀操作,處理讀到的數(shù)據(jù),注冊(cè)新的事件,然后返還控制權(quán)。

三. MySQL
1、有哪些數(shù)據(jù)庫(kù)優(yōu)化方面的經(jīng)驗(yàn)?
①. 用 PreparedStatement, 一般來說比 Statement 性能高:一個(gè) sql 發(fā)給服務(wù)器去執(zhí)行,涉及步驟:語法檢查、語義分析, 編譯,緩存。
②. 有外鍵約束會(huì)影響插入和刪除性能,如果程序能夠保證數(shù)據(jù)的完整性, 那在設(shè)計(jì)數(shù)據(jù)庫(kù)時(shí)就去掉外鍵。
③. 表中允許適當(dāng)冗余,譬如,主題帖的回復(fù)數(shù)量和最后回復(fù)時(shí)間等
④. UNION ALL 要比 UNION 快很多,所以,如果可以確認(rèn)合并的兩個(gè)結(jié) 果集中不包含重復(fù)數(shù)據(jù)且不需要排序時(shí)的話,那么就使用 UNION ALL。 >>UNION 和 UNION ALL 關(guān)鍵字都是將兩個(gè)結(jié)果集合并為一 個(gè),但這兩者從使用和效率上來說都有所不同。 >1. 對(duì)重復(fù)結(jié)果的處 理:UNION 在進(jìn)行表鏈接后會(huì)篩選掉重復(fù)的記錄,Union All 不會(huì)去除 重復(fù)記錄。 >2. 對(duì)排序的處理:Union 將會(huì)按照字段的順序進(jìn)行排 序;UNION ALL 只是簡(jiǎn)單的將兩個(gè)結(jié)果合并后就返回。
2、mysql 中 myisam 與 innodb 的區(qū)別?
①. 事務(wù)支持 > 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))型表。
②. InnoDB 支持行級(jí)鎖,而 MyISAM 支持表級(jí)鎖. >> 用戶在操作 myisam 表時(shí),select,update,delete,insert 語句都會(huì)給表自動(dòng) 加鎖,如果加鎖以后的表滿足 insert 并發(fā)的情況下,可以在表的尾部插入新的數(shù)據(jù)。
③. InnoDB 支持 MVCC, 而 MyISAM 不支持
④. InnoDB 支持外鍵,而 MyISAM 不支持
⑤. 表主鍵 > MyISAM:允許沒有任何索引和主鍵的表存在,索引都是保 存行的地址。 > InnoDB:如果沒有設(shè)定主鍵或者非空唯一索引,就會(huì) 自動(dòng)生成一個(gè) 6 字節(jié)的主鍵(用戶不可見),數(shù)據(jù)是主索引的一部分,附 加索引保存的是主索引的值。
⑥. InnoDB 不支持全文索引,而 MyISAM 支持。
⑦. 可移植性、備份及恢復(fù) > MyISAM:數(shù)據(jù)是以文件的形式存儲(chǔ),所以 在跨平臺(tái)的數(shù)據(jù)轉(zhuǎn)移中會(huì)很方便。在備份和恢復(fù)時(shí)可單獨(dú)針對(duì)某個(gè)表進(jìn) 行操作。 > InnoDB:免費(fèi)的方案可以是拷貝數(shù)據(jù)文件、備份 binlog,或者用 mysqldump,在數(shù)據(jù)量達(dá)到幾十 G 的時(shí)候就相對(duì)痛 苦了
⑧. 存儲(chǔ)結(jié)構(gòu) > MyISAM:每個(gè) MyISAM 在磁盤上存儲(chǔ)成三個(gè)文件。第一 個(gè)文件的名字以表的名字開始,擴(kuò)展名指出文件類型。.frm 文件存儲(chǔ)表 定義。數(shù)據(jù)文件的擴(kuò)展名為.MYD (MYData)。索引文件的擴(kuò)展名 是.MYI (MYIndex)。 > InnoDB:所有的表都保存在同一個(gè)數(shù)據(jù)文件 中(也可能是多個(gè)文件,或者是獨(dú)立的表空間文件),InnoDB 表的大 小只受限于操作系統(tǒng)文件的大小,一般為 2GB。
3、MySQL 中 InnoDB 引擎的行鎖是通過加在什么上完成(或稱實(shí)現(xiàn)) 的?
InnoDB 行鎖是通過給索引上的索引項(xiàng)加鎖來實(shí)現(xiàn)的,這一點(diǎn) MySQL 與 Oracle 不同,后者是通過在數(shù)據(jù)塊中對(duì)相應(yīng)數(shù)據(jù)行加鎖來實(shí)現(xiàn)的。InnoDB 這 種行鎖實(shí)現(xiàn)特點(diǎn)意味著:只有通過索引條件檢索數(shù)據(jù),InnoDB 才使用行級(jí) 鎖,否則,InnoDB 將使用表鎖!

四. JVM
1、內(nèi)存模型以及分區(qū),需要詳細(xì)到每個(gè)區(qū)放什么。
JVM 分為堆區(qū)和棧區(qū),還有方法區(qū),初始化的對(duì)象放在堆里面,引用放在棧里面,class 類信息常量池(static 常量和 static 變量)等放在方法區(qū)new:
- 方法區(qū):主要是存儲(chǔ)類信息,常量池(static 常量和 static 變量),編譯后的代碼(字節(jié)碼)等數(shù)據(jù)
- 堆:初始化的對(duì)象,成員變量 (那種非 static 的變量),所有的對(duì)象實(shí)例和數(shù)組都要在堆上分配
- 棧:棧的結(jié)構(gòu)是棧幀組成的,調(diào)用一個(gè)方法就壓入一幀,幀上面存儲(chǔ)局部變量表,操作數(shù)棧,方法出口等信息,局部變量表存放的是 8 大基礎(chǔ)類型加上一個(gè)應(yīng)用類型,所以還是一個(gè)指向地址的指針
- 本地方法棧:主要為 Native 方法服務(wù)
- 程序計(jì)數(shù)器:記錄當(dāng)前線程執(zhí)行的行號(hào)
2、堆里面的分區(qū):Eden,survival (from+ to),老年代,各自的特點(diǎn)。
堆里面分為新生代和老生代(java8 取消了永久代,采用了 Metaspace),新生代包 含 Eden+Survivor 區(qū),survivor 區(qū)里面分為 from 和 to 區(qū),內(nèi)存回收時(shí),如果用的是復(fù) 制算法,從 from 復(fù)制到 to,當(dāng)經(jīng)過一次或者多次 GC 之后,存活下來的對(duì)象會(huì)被移動(dòng) 到老年區(qū),當(dāng) JVM 內(nèi)存不夠用的時(shí)候,會(huì)觸發(fā) Full GC,清理 JVM 老年區(qū) 當(dāng)新生區(qū)滿了之后會(huì)觸發(fā) YGC,先把存活的對(duì)象放到其中一個(gè) Survice 區(qū),然后進(jìn)行垃圾清理。因?yàn)槿绻麅H僅清理需要?jiǎng)h除的對(duì)象,這樣會(huì)導(dǎo)致內(nèi)存碎 片,因此一般會(huì)把 Eden 進(jìn)行完全的清理,然后整理內(nèi)存。那么下次 GC 的時(shí)候, 就會(huì)使用下一個(gè) Survive,這樣循環(huán)使用。如果有特別大的對(duì)象,新生代放不下, 就會(huì)使用老年代的擔(dān)保,直接放到老年代里面。因?yàn)?JVM 認(rèn)為,一般大對(duì)象的存 活時(shí)間一般比較久遠(yuǎn)。
3、簡(jiǎn)述 java 垃圾回收機(jī)制?
在 java 中,程序員是不需要顯示的去釋放一個(gè)對(duì)象的內(nèi)存的,而是由虛擬機(jī)自行執(zhí)行。在JVM 中,有一個(gè)垃圾回收線程,它是低優(yōu)先級(jí)的,在正常情況下是不會(huì)執(zhí)行的,只有在虛擬機(jī)空閑或者當(dāng)前堆內(nèi)存不足時(shí),才會(huì)觸發(fā)執(zhí)行,掃面那些沒有被任何引用的對(duì)象,并將它們添加到要回收的集合中,進(jìn)行回收。

五. Tomcat
1、Tomcat 的缺省端口是多少,怎么修改?
- 找到 Tomcat 目錄下的 conf 文件夾
- 進(jìn)入 conf 文件夾里面找到 server.xml 文件
- 打開 server.xml 文件
- 在 server.xml 文件里面找到下列信息<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" uriEncoding="utf-8"/> port="8080"改成你想要的端口
2、Tomcat 有幾種部署方式?
- 直接把 Web 項(xiàng)目放在 webapps 下,Tomcat 會(huì)自動(dòng)將其部署
- 在 server.xml 文件上配置<Context>節(jié)點(diǎn),設(shè)置相關(guān)的屬性即可
- 通過 Catalina 來進(jìn)行配置:進(jìn)入到 conf\Catalina\localhost 文件下,創(chuàng)建一個(gè) xml 文件,該文件的名字就是站點(diǎn)的名字。
3、tomcat 容器是如何創(chuàng)建 servlet 類實(shí)例?用到了什么原理?
當(dāng)容器啟動(dòng)時(shí),會(huì)讀取在 webapps 目錄下所有的 web 應(yīng)用中的 web.xml 文 件,然后對(duì) xml 文件進(jìn)行解析,并讀取 servlet 注冊(cè)信息。然后,將每個(gè)應(yīng)用中注冊(cè)的 servlet 類都進(jìn)行加載, 并通過反射的方式實(shí)例化。(有時(shí)候也是在第一次請(qǐng)求時(shí)實(shí)例化)在 servlet 注冊(cè)時(shí)加上如果為正數(shù),則在 一開始就實(shí)例化,如果不寫或?yàn)樨?fù)數(shù),則第一次請(qǐng)求實(shí)例化。

六. MyBatis
1、講下 MyBatis 的緩存
MyBatis 的緩存分為一級(jí)緩存和二級(jí)緩存,一級(jí)緩存放在 session 里面,默認(rèn)就有,二級(jí)緩存放在它的命名空間里,默認(rèn)是不打開的,使用二級(jí)緩存屬性類需要實(shí)現(xiàn) Serializable 序列化接口(可用來保存對(duì)象的狀態(tài)),可在它的映射文件中配置<cache/>
2、Mybatis 是如何進(jìn)行分頁(yè)的?分頁(yè)插件的原理是什么?
- Mybatis 使用 RowBounds 對(duì)象進(jìn)行分頁(yè),也可以直接編寫 sql 實(shí)現(xiàn)分頁(yè),也可以使用Mybatis 的分頁(yè)插件。
- 分頁(yè)插件的原理:實(shí)現(xiàn) Mybatis 提供的接口,實(shí)現(xiàn)自定義插件,在插件的攔截方法內(nèi)攔截待執(zhí)行的 sql,然后重寫 sql。舉例:select * from student,攔截 sql 后重寫為:select t.* from (select * from student)tlimit 0,10
3、簡(jiǎn)述 Mybatis 的插件運(yùn)行原理,以及如何編寫一個(gè)插件?
- Mybatis 僅可以編寫針對(duì) ParameterHandler、ResultSetHandler、StatementHandler、Executor 這 4 種接口的插件,Mybatis 通過動(dòng)態(tài)代理,為需要攔截的接口生成代理對(duì)象以實(shí)現(xiàn)接口方法攔截功能,每當(dāng)執(zhí)行這 4 種接口對(duì)象的方法時(shí),就會(huì)進(jìn)入攔截方法,具體就是InvocationHandler 的 invoke()方法,當(dāng)然,只會(huì)攔截那些你指定需要攔截的方法。
- 實(shí)現(xiàn) Mybatis 的 Interceptor 接口并復(fù)寫 intercept()方法,然后在給插件編寫注解,指定要攔截哪一個(gè)接口的哪些方法即可,記住,別忘了在配置文件中配置你編寫的插件。

七. Redis
1、Redis 有哪幾種數(shù)據(jù)淘汰策略?
- noeviction:返回錯(cuò)誤當(dāng)內(nèi)存限制達(dá)到,并且客戶端嘗試執(zhí)行會(huì)讓更多內(nèi)存被使用的命令。
- allkeys-lru: 嘗試回收最少使用的鍵(LRU),使得新添加的數(shù)據(jù)有空間存放。
- volatile-lru: 嘗試回收最少使用的鍵(LRU),但僅限于在過期集合的鍵,使得新添加的數(shù)據(jù)有空間存放。
- allkeys-random: 回收隨機(jī)的鍵使得新添加的數(shù)據(jù)有空間存放。
- volatile-random: 回收隨機(jī)的鍵使得新添加的數(shù)據(jù)有空間存放,但僅限于在過期集合的鍵。
- volatile-ttl: 回收在過期集合的鍵,并且優(yōu)先回收存活時(shí)間(TTL)較短的鍵,使得新添加的數(shù)據(jù)有空間存放。
2、為什么 Redis 需要把所有數(shù)據(jù)放到內(nèi)存中?
Redis 為了達(dá)到最快的讀寫速度將數(shù)據(jù)都讀到內(nèi)存中,并通過異步的方式將數(shù)據(jù)寫入磁盤。
所以 redis 具有快速和數(shù)據(jù)持久化的特征,如果不將數(shù)據(jù)放在內(nèi)存中,磁盤 I/O 速度為嚴(yán)重影響 redis 的性能。
在內(nèi)存越來越便宜的今天,redis 將會(huì)越來越受歡迎, 如果設(shè)置了最大使用的內(nèi)存,則數(shù)據(jù)已有記錄數(shù)達(dá)到內(nèi)存限值后不能繼續(xù)插入新值。
3、Redis 如何做內(nèi)存優(yōu)化?
盡可能使用散列表(hashes),散列表(是說散列表里面存儲(chǔ)的數(shù)少)使用的內(nèi)存非常小,所以你應(yīng)該盡可能的將你的數(shù)據(jù)模型抽象到一個(gè)散列表里面。
比如你的 web 系統(tǒng)中有一個(gè)用戶對(duì)象,不要為這個(gè)用戶的名稱,姓氏,郵箱,密碼設(shè)置單獨(dú)的 key,而是應(yīng)該把這個(gè)用戶的所有信息存儲(chǔ)到一張散列表里面。

八. Kafka
1、Kafka 的設(shè)計(jì)是什么樣的呢?
Kafka 將消息以 topic 為單位進(jìn)行歸納
將向 Kafka topic 發(fā)布消息的程序成為 producers.
將預(yù)訂 topics 并消費(fèi)消息的程序成為 consumer.
Kafka 以集群的方式運(yùn)行,可以由一個(gè)或多個(gè)服務(wù)組成,每個(gè)服務(wù)叫做一個(gè) broker.
producers 通過網(wǎng)絡(luò)將消息發(fā)送到 Kafka 集群,集群向消費(fèi)者提供消息
2、數(shù)據(jù)傳輸?shù)氖挛锒x有哪三種?
數(shù)據(jù)傳輸?shù)氖聞?wù)定義通常有以下三種級(jí)別:
- 最多一次: 消息不會(huì)被重復(fù)發(fā)送,最多被傳輸一次,但也有可能一次不傳輸
- 最少一次: 消息不會(huì)被漏發(fā)送,最少被傳輸一次,但也有可能被重復(fù)傳輸.
- 精確的一次(Exactly once): 不會(huì)漏傳輸也不會(huì)重復(fù)傳輸,每個(gè)消息都傳輸被一次而且僅僅被傳輸一次,這是大家所期望的
3、Kafka 高效文件存儲(chǔ)設(shè)計(jì)特點(diǎn):
- Kafka 把 topic 中一個(gè) parition 大文件分成多個(gè)小文件段,通過多個(gè)小文件段,就容易定期清除或刪除已經(jīng)消費(fèi)完文件,減少磁盤占用。
- 通過索引信息可以快速定位 message 和確定 response 的最大大小。
- 通過 index 元數(shù)據(jù)全部映射到 memory,可以避免 segment file 的 IO 磁盤操作。
- 通過索引文件稀疏存儲(chǔ),可以大幅降低 index 文件元數(shù)據(jù)占用空間大小。