JAVA基礎(chǔ)總結(jié)

1.String、StringBuilder、StringBuffer的區(qū)別是什么,String為什么是不可變的?

不可變性

String類的底層源碼中,通過(guò)final關(guān)鍵字修飾字符串?dāng)?shù)組,private final char value[],所以是不可變的。StringBuffer和StringBuilder類是集成自 AbstractStringBuilder 類, AbstractStringBuilder 類中的變量沒(méi)有用final關(guān)鍵字修飾,所以是可變的。

線程安全性

String是不可變的,是常量,所以是線程安全的。StringBuilder和StringBuffer都繼承自AbstractStringBuilder 類,StringBuffer對(duì)方法加了同步鎖,所以是線程安全的,而StringBuilder沒(méi)有加同步鎖,所以是線程不安全的。

性能

對(duì)String類型進(jìn)行改變是都會(huì)new一個(gè)新的string對(duì)象,并指向新的對(duì)象;

StringBuffer直接通過(guò)改變自身變量的值,StringBuilder相對(duì)能提升性能,但有線程不安全的情況。

2.== 與 equals

==用來(lái)判斷兩個(gè)對(duì)象是否相等,基礎(chǔ)數(shù)據(jù)類型比較的是值是否相等。

沒(méi)有重寫對(duì)象的equals方法時(shí),也是用來(lái)比較兩個(gè)對(duì)象是否相等,重寫equals方法可以比較內(nèi)容相等,返回true

3.try/catch/finally中finally是否一定執(zhí)行

在以下4種特殊情況下,finally塊不會(huì)被執(zhí)行:

1. 在finally語(yǔ)句塊中發(fā)生了異常。

2. 在前面的代碼中用了System.exit()退出程序。

3. 程序所在的線程死亡。

4. 關(guān)閉CPU。

4.接口和抽象類的區(qū)別?

1.抽象類中可以實(shí)現(xiàn)方法,抽象接口不能實(shí)現(xiàn)方法(jdk1.8以后可以實(shí)現(xiàn)方法);

2.接口中的變量默認(rèn)是final類型,而抽象類不是;

3.類只能繼承一個(gè)抽象類,而接口可以實(shí)現(xiàn)多個(gè);

4.類繼承接口需要實(shí)現(xiàn)所有方法,抽象類不需要;

5.接口不能用new實(shí)例化,可以聲明。必須引用一個(gè)實(shí)現(xiàn)該接口的對(duì)象抽象是對(duì)類的抽象,是一種模板設(shè)計(jì),接口是行為的抽象,是一種行為的規(guī)范。

5.Arraylist 與 LinkedList 異同

安全性

ArrayList與LinkedList都是線程不安全的。

數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)

ArryayList是基于Object數(shù)組,而LinkedList是基于雙向循環(huán)鏈表(JDK1.6之前為循環(huán)鏈表,之后取消了循環(huán))

插入刪除的影響

ArrayList采用數(shù)組存儲(chǔ),插入刪除受元素位置的影響;

LinkedList采用鏈表存儲(chǔ),插入刪除不收元素位置影響;

訪問(wèn)元素

LinkedList 不支持高效的隨機(jī)元素訪問(wèn),而 ArrayList 支持。快速隨機(jī)訪問(wèn)就是通過(guò)元素的序號(hào)快速獲取元素對(duì)象(對(duì)應(yīng)于get(int index)方法)。

實(shí)現(xiàn)了RandomAccess接口的list,優(yōu)先選擇普通for循環(huán) ,其次foreach,未實(shí)現(xiàn)RandomAccess接口的list, 優(yōu)先選擇iterator遍歷(foreach遍歷底層也是通過(guò)iterator實(shí)現(xiàn)的),大size的數(shù)據(jù),千萬(wàn)不要使用普通for循環(huán)

6.ArrayList 與 Vector 區(qū)別

Vector中所有方法都是同步的,在多線程操作中,同步操作會(huì)耗費(fèi)時(shí)間,而ArrayList是不需要同步的,在不需要考慮線程安全時(shí)可以使用。

7.HashMap的底層實(shí)現(xiàn)

待補(bǔ)充完善

8.HashSet 和 HashMap 區(qū)別

HashMap實(shí)現(xiàn)Map接口,用來(lái)存儲(chǔ)鍵值對(duì),調(diào)用put方法添加元素,使用Key計(jì)算Hashcode,而HashSet實(shí)現(xiàn)Set接口,用來(lái)存儲(chǔ)對(duì)象,調(diào)用add方法添加對(duì)象,使用對(duì)象計(jì)算hashcode,根據(jù)equals方法判斷對(duì)象相等,執(zhí)行效率的話,HashMap優(yōu)與HashSet。

9.ConcurrentHashMap 和 Hashtable 的區(qū)別

ConcurrentHashMap 和 HashTable 的區(qū)別主要體現(xiàn)在實(shí)現(xiàn)線程安全的方式上不同。ConcurrentHashMap使用的是分段鎖,HashTable使用的是同一把鎖,因而在多線程并發(fā)中效率很低。

10.多線程實(shí)現(xiàn)方式

1.繼承Thread類,2.實(shí)現(xiàn)Runnable接口,3.基于線程池實(shí)現(xiàn)

11.線程有哪些基本狀態(tài)

線程基本狀態(tài)

12.樂(lè)觀鎖和悲觀鎖

悲觀鎖,總是假設(shè)最壞的情況,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖(共享資源每次只給一個(gè)線程使用,其它線程阻塞,用完后再把資源轉(zhuǎn)讓給其它線程),樂(lè)觀鎖,總是假設(shè)最好的情況,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒(méi)有去更新這個(gè)數(shù)據(jù),可以使用版本號(hào)機(jī)制和CAS算法實(shí)現(xiàn)。樂(lè)觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量。

使用場(chǎng)景

樂(lè)觀鎖適用于寫比較少的情況,多寫的情況使用悲觀鎖。

樂(lè)觀鎖的實(shí)現(xiàn)方式

樂(lè)觀鎖一般會(huì)使用版本號(hào)機(jī)制或CAS算法實(shí)現(xiàn)。

樂(lè)觀鎖的缺點(diǎn)

1.ABA問(wèn)題;2.循環(huán)時(shí)間長(zhǎng),開銷大;3.只能保證一個(gè)共享變量的原子操作

13.CAS算法

compare and swap(比較與交換),是一種有名的無(wú)鎖算法。無(wú)鎖編程,即不使用鎖的情況下實(shí)現(xiàn)多線程之間的變量同步,也就是在沒(méi)有線程被阻塞的情況下實(shí)現(xiàn)變量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。CAS算法涉及到三個(gè)操作數(shù)

需要讀寫的內(nèi)存值 V

進(jìn)行比較的值 A

擬寫入的新值 B

當(dāng)且僅當(dāng) V 的值等于 A時(shí),CAS通過(guò)原子方式用新值B來(lái)更新V的值,否則不會(huì)執(zhí)行任何操作(比較和替換是一個(gè)原子操作)。一般情況下是一個(gè)自旋操作,即不斷的重試

14.可重入鎖和非可重入鎖的區(qū)別?

?廣義上的可重入鎖指的是可重復(fù)可遞歸調(diào)用的鎖,在外層使用鎖之后,在內(nèi)層仍然可以使用,并且不發(fā)生死鎖(前提得是同一個(gè)對(duì)象或者class),這樣的鎖就叫做可重入鎖。

15.談?wù)?synchronized和ReenTrantLock 的區(qū)別

1.兩者都為可重入鎖;2.synchronized是依賴于jvm,ReenTrantLock是依賴于API;3.ReenTrantLock 比 synchronized 增加了一些高級(jí)功能,主要有三點(diǎn):1等待可中斷;2可實(shí)現(xiàn)公平鎖;3可實(shí)現(xiàn)選擇性通知(鎖可以綁定多個(gè)條件)

16.synchronized 關(guān)鍵字和 volatile 關(guān)鍵字的區(qū)別

volatile關(guān)鍵字是線程同步的輕量級(jí)實(shí)現(xiàn),但是volatile關(guān)鍵字只能用于變量而synchronized關(guān)鍵字可以修飾方法以及代碼塊。synchronized關(guān)鍵字在JavaSE1.6之后進(jìn)行了主要包括為了減少獲得鎖和釋放鎖帶來(lái)的性能消耗而引入的偏向鎖和輕量級(jí)鎖以及其它各種優(yōu)化之后執(zhí)行效率有了顯著提升,實(shí)際開發(fā)中使synchronized 關(guān)鍵字的場(chǎng)景還是更多一些。

多線程訪問(wèn)volatile關(guān)鍵字不會(huì)發(fā)生阻塞,而synchronized關(guān)鍵字可能會(huì)發(fā)生阻塞

volatile關(guān)鍵字能保證數(shù)據(jù)的可見性,但不能保證數(shù)據(jù)的原子性。synchronized關(guān)鍵字兩者都能保證。

volatile關(guān)鍵字主要用于解決變量在多個(gè)線程之間的可見性,而 synchronized關(guān)鍵字解決的是多個(gè)線程之間訪問(wèn)資源的同步性。

17.為什么使用線程池?

線程池提供了一種限制和管理資源(包括執(zhí)行一個(gè)任務(wù))。 每個(gè)線程池還維護(hù)一些基本統(tǒng)計(jì)信息,例如已完成任務(wù)的數(shù)量。為了降低資源消耗、提高響應(yīng)速度、提高線程的可管理性

18.實(shí)現(xiàn)Runnable接口和Callable接口的區(qū)別

兩者的區(qū)別在于 Runnable 接口不會(huì)返回結(jié)果但是 Callable 接口可以返回結(jié)果。

19.如何創(chuàng)建線程池

1.通過(guò)構(gòu)造方法創(chuàng)建,通過(guò) ThreadPoolExecutor創(chuàng)建

2.通過(guò)Executor 框架的工具類Executors來(lái)實(shí)現(xiàn),可創(chuàng)建三種類型的ThreadPoolExecutor,F(xiàn)ixedThreadPool(固定數(shù)量的線程池)、SingleThreadExecutor(單線程)、CachedThreadPool(可擴(kuò)展的線程池)

20.AQS 原理

待補(bǔ)充

21.?Java 內(nèi)存區(qū)域

JAVA內(nèi)存區(qū)域在JDK1.8之前分為:堆、方法區(qū)、直接內(nèi)存、程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧

JDK1.8之后將方法區(qū)刪掉,引用直接內(nèi)存。

線程私有的:程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧

線程共享的:堆、方法區(qū)、直接內(nèi)存 (非運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分)

程序技術(shù)器的作用有兩個(gè):1.字節(jié)碼通過(guò)改變程序計(jì)數(shù)器的位置來(lái)依次讀取指令;2.用于記錄當(dāng)前程序運(yùn)行的位置,以便線程切換時(shí)知道程序運(yùn)行到哪一步。

JAVA虛擬機(jī)棧用于存放局部變量,局部變量表主要存放了基礎(chǔ)數(shù)據(jù)類型和引用類型,虛擬機(jī)棧會(huì)拋出兩種異常StackOverFlowError和OutOfMemoryError

本地方法棧虛擬機(jī)使用到的 Native 方法服務(wù)

堆,線程共享區(qū)域,用于存放對(duì)象實(shí)例,幾乎所有的對(duì)象和數(shù)組都在這里分配內(nèi)存。

方法區(qū),線程共享區(qū),存儲(chǔ)已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)

22.JAVA對(duì)象的創(chuàng)建

類加載檢查-->分配內(nèi)存-->初始化零值-->設(shè)置對(duì)象頭-->執(zhí)行int方法

類加載檢查:發(fā)起new指令創(chuàng)建對(duì)象時(shí),先檢查當(dāng)前類是否已經(jīng)被加載過(guò),如果沒(méi)有,先進(jìn)行類加載過(guò)程。

分配內(nèi)存:類加載檢查完成后,虛擬機(jī)在堆中為類分配相應(yīng)的內(nèi)存。分配方式有兩種:指針碰撞和空閑列表。選在以上方式中的哪一種,由JAVA堆是否規(guī)整來(lái)決定,而Java 堆內(nèi)存是否規(guī)整,取決于 GC 收集器的算法是"標(biāo)記-清除",還是"標(biāo)記-整理"(也稱作"標(biāo)記-壓縮")。內(nèi)存分配并發(fā)問(wèn)題通過(guò)cas+失敗重試解決

初始化零值:虛擬機(jī)將分配到的內(nèi)存空間初始化為零值(不包括對(duì)象頭)。為了保證對(duì)象實(shí)例可以不賦初始值被引用。

設(shè)置對(duì)象頭:虛擬機(jī)要對(duì)對(duì)象進(jìn)行必要的設(shè)置,將類的信息存放在對(duì)象頭。如元數(shù)據(jù)信息、對(duì)象的哈希碼、對(duì)象的 GC 分代年齡等信息。

執(zhí)行int方法:對(duì)象實(shí)例創(chuàng)建完畢后,執(zhí)行int方法為對(duì)象按照開發(fā)者初始化值

23.JAVA對(duì)象內(nèi)存布局

在 Hotspot 虛擬機(jī)中,分為 3 塊區(qū)域:對(duì)象頭實(shí)例數(shù)據(jù)對(duì)齊填充

24.判斷對(duì)象是否死亡


是否死亡

25.如何判斷一個(gè)類是無(wú)用的類

滿足三個(gè)條件:1.該類中的所有引用已經(jīng)被回收;2.加載該類的classloader已經(jīng)被回收;3.該類沒(méi)有在任何一個(gè)地方被引用,無(wú)法在任何地方通過(guò)反射訪問(wèn)該類的方法。

滿足這個(gè)三個(gè)條件也不一定會(huì)被回收

26.垃圾收集算法

1.標(biāo)記-清除:將可回收對(duì)象進(jìn)行標(biāo)記,在標(biāo)記完成后統(tǒng)一回收對(duì)象,會(huì)有兩種問(wèn)題:效率問(wèn)題和空間問(wèn)題(標(biāo)記清除后會(huì)產(chǎn)生大量不連續(xù)的碎片)

2.復(fù)制算法:將內(nèi)存分半大小相同兩塊,將存活對(duì)象復(fù)制到另一塊內(nèi)存。然后把剩余的空間全部清理掉。

3.標(biāo)記-整理:將可回收對(duì)象標(biāo)記,將存活對(duì)象向一端移動(dòng),最后將端點(diǎn)邊界外的內(nèi)存全部清理

4.分代收集:新生代對(duì)象每次都會(huì)有大量對(duì)象死去,所以可以選擇復(fù)制算法,只需要復(fù)制很少的內(nèi)存就可以清除掉;老年代對(duì)象,沒(méi)有額外的空間對(duì)它進(jìn)行分配擔(dān)保,所以我們必須選擇“標(biāo)記-清除”或“標(biāo)記-整理”算法進(jìn)行垃圾收集

27.垃圾收集器


垃圾收集器

1.Serial收集器:

是單線程收集器,在收集時(shí)會(huì)暫停所有正在工作的線程,直到完成收集工作,與其他單線程收集器相比簡(jiǎn)單高效;

2.ParNew收集器:

其實(shí)就是 Serial 收集器的多線程版本,除了使用多線程進(jìn)行垃圾收集外,其余行為(控制參數(shù)、收集算法、回收策略等等)和 Serial 收集器完全一樣。除了 Serial 收集器外,只有它能與 CMS 收集器(真正意義上的并發(fā)收集器,后面會(huì)介紹到)配合工作。

3.Parallel Scavenge 收集器:與ParNew收集器

4.Serial Old 收集器:

Serial 收集器的老年代版本,它主要有兩大用途:一種用途是在 JDK1.5 以及以前的版本中與 Parallel Scavenge 收集器搭配使用,另一種用途是作為 CMS 收集器的后備方案

5.CMS 收集器:

CMS(Concurrent Mark Sweep)收集器是一種以獲取最短回收停頓時(shí)間為目標(biāo)的收集器。它而非常符合在注重用戶體驗(yàn)的應(yīng)用上使用。

主要四個(gè)階段:初始標(biāo)記、并發(fā)標(biāo)記、重新標(biāo)記、并發(fā)清除

優(yōu)點(diǎn):并發(fā)收集、低停頓

缺點(diǎn):對(duì) CPU 資源敏感;無(wú)法處理浮動(dòng)垃圾;它使用的回收算法-“標(biāo)記-清除”算法會(huì)導(dǎo)致收集結(jié)束時(shí)會(huì)有大量空間碎片產(chǎn)生。

6.G1收集器:

G1 (Garbage-First) 是一款面向服務(wù)器的垃圾收集器,主要針對(duì)配備多顆處理器及大容量?jī)?nèi)存的機(jī)器. 以極高概率滿足 GC 停頓時(shí)間要求的同時(shí),還具備高吞吐量性能特征.

優(yōu)點(diǎn):

并行與并發(fā):可利用系統(tǒng)中的多核來(lái)縮短系統(tǒng)停頓時(shí)間,G1 收集器仍然可以通過(guò)并發(fā)的方式讓 java 程序繼續(xù)執(zhí)行。

分代收集:但是還是保留了分代收集的概念。

空間整合:G1 從整體來(lái)看是基于“標(biāo)記整理”算法實(shí)現(xiàn)的收集器;從局部上來(lái)看是基于“復(fù)制”算法實(shí)現(xiàn)的。

可預(yù)測(cè)的停頓:可預(yù)測(cè)收集時(shí)間

28.計(jì)算機(jī)網(wǎng)絡(luò)分層

TCP/IP四層:應(yīng)用層、網(wǎng)絡(luò)層、傳輸層、網(wǎng)絡(luò)接口層

TCP/IP五層:應(yīng)用層、網(wǎng)絡(luò)層、傳輸層、數(shù)據(jù)鏈路層、物理層

OSI7層:應(yīng)用層、會(huì)話層、表示層、網(wǎng)絡(luò)層、傳輸層、數(shù)據(jù)鏈路層、物理層

29.?TCP、UDP 協(xié)議的區(qū)別

UDP傳輸時(shí)不需要建立連接,遠(yuǎn)程主機(jī)在收到報(bào)文后不需要給出任何確認(rèn)。不提供可靠交付,在即時(shí)通訊中有用到。

TCP提供面向連接的服務(wù),傳輸數(shù)據(jù)前需要先建立連接,數(shù)據(jù)傳輸完畢要釋放連接,TCP可提供可靠的傳輸服務(wù)(TCP可靠性體現(xiàn)在傳輸數(shù)據(jù)前會(huì)先進(jìn)行三次握手來(lái)建立連接,有確認(rèn)、窗口、重傳、擁塞控制機(jī)制,在數(shù)據(jù)傳完后,還會(huì)斷開連接用來(lái)節(jié)約系統(tǒng)資源),同時(shí)也會(huì)帶來(lái)很多資源開銷。TCP 一般用于文件傳輸、發(fā)送和接收郵件、遠(yuǎn)程登錄等場(chǎng)景。

30.在瀏覽器中輸入url地址 ->> 顯示主頁(yè)的過(guò)程

DNS解析-->建立連接-->發(fā)送HTTP請(qǐng)求-->服務(wù)器處理HTTP請(qǐng)求返回-->瀏覽器解析返回?cái)?shù)據(jù)-->關(guān)閉連接

31.各種協(xié)議與HTTP協(xié)議之間的關(guān)系


用到的協(xié)議

32.TCP 三次握手和四次揮手

客戶端–發(fā)送帶有 SYN 標(biāo)志的數(shù)據(jù)包–一次握手–服務(wù)端?

服務(wù)端–發(fā)送帶有 SYN/ACK 標(biāo)志的數(shù)據(jù)包–二次握手–客戶端?

客戶端–發(fā)送帶有帶有 ACK 標(biāo)志的數(shù)據(jù)包–三次握手–服務(wù)端

為什么進(jìn)行三次握手呢?

三次握手為了建立可靠的通信,為了確認(rèn)客戶端和服務(wù)端都發(fā)送接收正常。

第一次握手確認(rèn)了server接收正常,第二次握手確認(rèn)了server端接收正常、client端發(fā)送、接收正常,第三次握手確認(rèn)了server端發(fā)送正常、接收正常,client端發(fā)送正常、接收正常

為什么四次揮手?

客戶端-發(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

33.MySQL 常見的兩種存儲(chǔ)引擎:MyISAM與InnoDB的理解

1.count運(yùn)算上,Mylsam緩存有數(shù)據(jù)行數(shù),執(zhí)行效率上比InnoDB快;

2.事務(wù)控制和崩潰后安全恢復(fù):MyISAM 強(qiáng)調(diào)的是性能,執(zhí)行速度比InnoDB快,不支持事務(wù)控制,InnoDB支持事務(wù)的控制、回滾、崩潰后的安全恢復(fù);

3.MyISAM不支持外鍵,而InnoDB支持。

MyISAM更適合讀密集的表,而InnoDB更適合寫密集的的表。在數(shù)據(jù)庫(kù)主從分離下,一般選用MyISAM作為主庫(kù)存儲(chǔ)引擎,需要事務(wù)支持,并發(fā)量寫入很大時(shí)選擇InnoDB,大量數(shù)據(jù)讀取時(shí)選用MyISAM

34.數(shù)據(jù)庫(kù)索引思維導(dǎo)圖


思維導(dǎo)圖

35.MySql存儲(chǔ)結(jié)構(gòu)

MySQL的基本存儲(chǔ)結(jié)構(gòu)是頁(yè)(記錄都存在頁(yè)里邊):各個(gè)數(shù)據(jù)頁(yè)可以組成一個(gè)雙向鏈表,每個(gè)數(shù)據(jù)頁(yè)中的記錄又可以組成一個(gè)單向鏈表。查找數(shù)據(jù)的過(guò)程簡(jiǎn)單來(lái)說(shuō),1. 定位到記錄所在的頁(yè):需要遍歷雙向鏈表,找到所在的頁(yè);2. 從所在的頁(yè)內(nèi)中查找相應(yīng)的記錄:由于不是根據(jù)主鍵查詢,只能遍歷所在頁(yè)的單鏈表了。

為什么使用索引以后會(huì)提高查詢效率?索引相當(dāng)于把無(wú)序的數(shù)據(jù)變成相對(duì)有序。

36.當(dāng)MySQL單表記錄數(shù)過(guò)大時(shí),數(shù)據(jù)庫(kù)的CRUD性能會(huì)明顯下降,常見的優(yōu)化措施

1.限定數(shù)據(jù)范圍,查詢必須附帶查詢條件;

2.讀寫分離,主庫(kù)負(fù)責(zé)寫入數(shù)據(jù),從庫(kù)負(fù)責(zé)讀數(shù)據(jù);

3.垂直分區(qū),簡(jiǎn)單來(lái)說(shuō)就是講一張表按照相關(guān)性進(jìn)行拆分,將一張表拆成多個(gè)表;

4.水平分區(qū),保持?jǐn)?shù)據(jù)表結(jié)構(gòu)不變,將數(shù)據(jù)分為多個(gè)表存儲(chǔ),水平拆分支持大數(shù)據(jù)量的存儲(chǔ)。在實(shí)際使用中藥進(jìn)行分庫(kù)分表,水平拆分支持非常大的數(shù)據(jù)量。

在實(shí)際使用中,盡量不對(duì)數(shù)據(jù)庫(kù)進(jìn)行分片,因?yàn)椴鸱謺?huì)帶來(lái)邏輯、部署、運(yùn)維的各種復(fù)雜度。

數(shù)據(jù)庫(kù)分片的兩種常見方案:

1.客戶端代理: 分片邏輯在應(yīng)用端,封裝在jar包中,通過(guò)修改或者封裝JDBC層來(lái)實(shí)現(xiàn)。

2.中間件代理:在應(yīng)用和數(shù)據(jù)中間加了一個(gè)代理層。分片邏輯統(tǒng)一維護(hù)在中間件服務(wù)中。

36.事務(wù)的特性

原子性: 事務(wù)是最小的執(zhí)行單位,不允許分割。事務(wù)的原子性確保動(dòng)作要么全部完成,要么完全不起作用;

一致性: 執(zhí)行事務(wù)前后,數(shù)據(jù)保持一致,多個(gè)事務(wù)對(duì)同一個(gè)數(shù)據(jù)讀取的結(jié)果是相同的;

隔離性: 并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),一個(gè)用戶的事務(wù)不被其他事務(wù)所干擾,各并發(fā)事務(wù)之間數(shù)據(jù)庫(kù)是獨(dú)立的;

持久性: 一個(gè)事務(wù)被提交之后。它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變是持久的,即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響。

37.并發(fā)事務(wù)帶來(lái)的問(wèn)題

臟讀:當(dāng)一個(gè)事務(wù)正在訪問(wèn)數(shù)據(jù)庫(kù)對(duì)數(shù)據(jù)進(jìn)行了修改,還沒(méi)有提交,另一個(gè)事務(wù)訪問(wèn)的數(shù)據(jù)是還沒(méi)有提交的數(shù)據(jù),事務(wù)讀到的這個(gè)數(shù)據(jù)是“臟數(shù)據(jù)”,依據(jù)“臟數(shù)據(jù)”所做的操作可能是不正確的

丟失修改:事務(wù)讀取一條數(shù)據(jù)時(shí)修改,另一個(gè)事務(wù)也讀取到數(shù)據(jù)并進(jìn)行修改,事務(wù)一的修改將丟失。

不可重復(fù)讀:在一個(gè)事務(wù)內(nèi)多次讀取數(shù)據(jù),在這個(gè)事務(wù)還沒(méi)有結(jié)束的時(shí)候,另一個(gè)事務(wù)修改了同一條數(shù)據(jù)并提交,可能會(huì)兩次讀取數(shù)據(jù)不一致的情況

幻讀:幻讀與不可重復(fù)讀類似。在一個(gè)事務(wù)讀取多條數(shù)據(jù)的時(shí)候,另一個(gè)事務(wù)插入了幾條數(shù)據(jù),再隨后的查詢中多出了幾條數(shù)據(jù)。不可重復(fù)讀的重點(diǎn)是修改,幻讀的重點(diǎn)在于新增或者刪除。

38.事務(wù)隔離級(jí)別

READ-UNCOMMITTED(讀取未提交)、READ-COMMITTED(讀取已提交)、REPEATABLE-READ(可重復(fù)讀)、SERIALIZABLE(可串行化)

39.為什么要用 redis /為什么要用緩存

主要是用于高性能和高并發(fā)。

高性能:用戶訪問(wèn)服務(wù)器直接讀數(shù)據(jù)庫(kù)中的數(shù)據(jù)是從硬盤中讀取的,比較慢,將該用戶訪問(wèn)的數(shù)據(jù)存到緩存中就可以直接從緩存中獲取了,相當(dāng)于直接從內(nèi)存中獲取,如果數(shù)據(jù)庫(kù)中的數(shù)據(jù)改變改變相應(yīng)的緩存數(shù)據(jù)即可。

高并發(fā):直接操作緩存能夠承受的請(qǐng)求是遠(yuǎn)遠(yuǎn)大于直接操作數(shù)據(jù)庫(kù)的,可以把數(shù)據(jù)庫(kù)中的部分?jǐn)?shù)據(jù)放到緩存中,用戶的請(qǐng)求只需要經(jīng)過(guò)緩存就可以了。

40.為什么要用 redis 而不用 map/guava 做緩存?

緩存分為本地緩存和分布式緩存,Map和guava是通過(guò)本地緩存,隨著jvm的銷毀而結(jié)束,在多實(shí)例的情況下,每個(gè)實(shí)例保存一套緩存。不具有一致性。使用redis做分布式緩存,多個(gè)實(shí)例可共享一個(gè)緩存具有一致性。redis緩存缺點(diǎn)需要保持高可用性,架構(gòu)也比較復(fù)雜

41.redis 和 memcached 的區(qū)別

1.redis支持更豐富的數(shù)據(jù)類型,redis支持String、list、set、zset、hash等,memcached 僅支持String類型。

2.redis的數(shù)據(jù)支持持久化,可存儲(chǔ)到本地硬盤,memcached將數(shù)據(jù)存儲(chǔ)在內(nèi)存中;

3.redis支持集群部署,memcached不支持

4.memcached是多線程,非阻塞IO復(fù)用模型,redis是單線程多路IO復(fù)用模型

42.redis中的過(guò)期時(shí)間

redis中過(guò)期時(shí)間可以通過(guò)expire time設(shè)置,時(shí)間到期后會(huì)通過(guò)兩種方式刪除,定期刪除和惰性刪除。

redis 內(nèi)存淘汰機(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-eviction:禁止驅(qū)逐數(shù)據(jù),也就是說(shuō)當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時(shí),新寫入操作會(huì)報(bào)錯(cuò)

43.redis 持久化機(jī)制

Redis的一種持久化方式叫快照(snapshotting,RDB),Redis可以通過(guò)創(chuàng)建快照來(lái)獲得存儲(chǔ)在內(nèi)存里面的數(shù)據(jù)在某個(gè)時(shí)間點(diǎn)上的副本。可以將快照復(fù)制到其他服務(wù)器從而創(chuàng)建具有相同數(shù)據(jù)的服務(wù)器副本。

另一種方式是只追加文件(append-only file,AOF),與快照持久化相比,AOF持久化 的實(shí)時(shí)性更好,因此已成為主流的持久化方案。為了兼顧數(shù)據(jù)和寫入性能,用戶可以考慮 appendfsync everysec選項(xiàng) ,讓Redis每秒同步一次AOF文件,Redis性能幾乎沒(méi)受到任何影響。

44.redis事務(wù)

Redis 通過(guò) MULTI、EXEC、WATCH 等命令來(lái)實(shí)現(xiàn)事務(wù)(transaction)功能。事務(wù)提供了一種將多個(gè)命令請(qǐng)求打包,然后一次性、按順序地執(zhí)行多個(gè)命令的機(jī)制,并且在事務(wù)執(zhí)行期間,服務(wù)器不會(huì)中斷事務(wù)而改去執(zhí)行其他客戶端的命令請(qǐng)求,它會(huì)將事務(wù)中的所有命令都執(zhí)行完畢,然后才去處理其他客戶端的命令請(qǐng)求。

45.緩存雪崩和緩存穿透問(wèn)題解決方案(擴(kuò)展)

緩存雪崩:緩存同一時(shí)間大面積失效,會(huì)導(dǎo)致請(qǐng)求全部落到數(shù)據(jù)庫(kù)上,造成數(shù)據(jù)庫(kù)無(wú)法短時(shí)間處理大量請(qǐng)求而崩掉。

事前:盡量保證redis的高可用,發(fā)現(xiàn)宕機(jī)立即補(bǔ)上,選擇合適的內(nèi)存淘汰策略

事中:本地ehcache緩存+hystrix限流&降級(jí)避免mysql崩掉

事后:依靠redis的持久化機(jī)制盡可能恢復(fù)數(shù)據(jù)

緩存穿透:一般是黑客故意去請(qǐng)求緩存中不存在的數(shù)據(jù),導(dǎo)致所有的請(qǐng)求都落到數(shù)據(jù)庫(kù)上,造成數(shù)據(jù)庫(kù)短時(shí)間內(nèi)承受大量請(qǐng)求而崩掉。

46.如何解決 Redis 的并發(fā)競(jìng)爭(zhēng) Key 問(wèn)題

使用分布式鎖

redis實(shí)現(xiàn):加鎖時(shí)通過(guò)jedis.set(String key, String value, String nxxx, String expx, int time)方法為數(shù)據(jù)設(shè)置一個(gè)唯一key,和不存在時(shí)新增,存在時(shí)什么都不做,并設(shè)置一個(gè)過(guò)期時(shí)間。

解鎖時(shí)通過(guò)首先獲取鎖對(duì)應(yīng)的value值,檢查是否與requestId相等,如果相等則刪除鎖(解鎖)

使用緩存實(shí)現(xiàn)分布式鎖的缺點(diǎn)

通過(guò)超時(shí)時(shí)間來(lái)控制鎖的失效時(shí)間并不是十分的靠譜。

zookeeper實(shí)現(xiàn):每個(gè)客戶端對(duì)某個(gè)方法加鎖時(shí),在zookeeper上的與該方法對(duì)應(yīng)的指定節(jié)點(diǎn)的目錄下,生成一個(gè)唯一的瞬時(shí)有序節(jié)點(diǎn)。 判斷是否獲取鎖的方式很簡(jiǎn)單,只需要判斷有序節(jié)點(diǎn)中序號(hào)最小的一個(gè)。 當(dāng)釋放鎖的時(shí)候,只需將這個(gè)瞬時(shí)節(jié)點(diǎn)刪除即可。同時(shí),其可以避免服務(wù)宕機(jī)導(dǎo)致的鎖無(wú)法釋放,而產(chǎn)生的死鎖問(wèn)題。完成業(yè)務(wù)流程后,刪除對(duì)應(yīng)的子節(jié)點(diǎn)釋放鎖。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 九種基本數(shù)據(jù)類型的大小,以及他們的封裝類。(1)九種基本數(shù)據(jù)類型和封裝類 (2)自動(dòng)裝箱和自動(dòng)拆箱 什么是自動(dòng)裝箱...
    關(guān)瑋琳l(shuí)inSir閱讀 1,913評(píng)論 0 47
  • 多線程 1、進(jìn)程和線程 進(jìn)程:正在進(jìn)行的成序。每一個(gè)進(jìn)程執(zhí)行都有一個(gè)執(zhí)行順序,該順序是一個(gè)執(zhí)行路徑,或者叫一個(gè)控制...
    有_味閱讀 304評(píng)論 1 1
  • Java8張圖 11、字符串不變性 12、equals()方法、hashCode()方法的區(qū)別 13、...
    Miley_MOJIE閱讀 3,728評(píng)論 0 11
  • 本系列出于AWeiLoveAndroid的分享,在此感謝,再結(jié)合自身經(jīng)驗(yàn)查漏補(bǔ)缺,完善答案。以成系統(tǒng)。 Java基...
    濟(jì)公大將閱讀 1,537評(píng)論 1 6
  • 一 當(dāng)蘇亦蘭走出民政大廳的那一刻,渾身感到從未有過(guò)的輕松。她終于解脫了,十五年的...
    張薛正華閱讀 652評(píng)論 0 3