http://www.itdecent.cn/p/a07d1d4004b0 源問題集合
Java基礎(chǔ)
1、List 和 Set 的區(qū)別
- List有序,元素可重復(fù)
- Set無序,元素不可重復(fù)
2、HashSet 是如何保證不重復(fù)的
- add之前先判斷hash值,和equals, 一樣就不存
3、HashMap 是線程安全的嗎,為什么不是線程安全的(最好畫圖說明多線程環(huán)境下不安全)?
- 不安全, put的時(shí)候resize和rehash可能導(dǎo)致死循環(huán)
- 遍歷時(shí)候不允許修改,ConcurrentModificationException, fast-fail, check modificationCount
4、HashMap 的擴(kuò)容過程
- size > threshold
- table *= 2
- rehash
5、HashMap 1.7 與 1.8 的 區(qū)別,說明 1.8 做了哪些優(yōu)化,如何優(yōu)化的?
- 鏈表長(zhǎng)度>8 -> 紅黑樹
- rehash算法進(jìn)行改進(jìn)
6、final finally finalize
- final, 類不能繼承, 方法不能重載, 變量不能改變
- fianlly 永遠(yuǎn)會(huì)被執(zhí)行
- finalize, GC的時(shí)候調(diào)用, 不應(yīng)該依賴他, 因?yàn)椴淮_定GC什么時(shí)候進(jìn)行
7、強(qiáng)引用 、軟引用、 弱引用、虛引用
- 正常持有的引用
- 內(nèi)存不夠時(shí)候釋放的引用
- GC時(shí)候一定釋放的引用
- 可能在對(duì)象回收時(shí)候收到一個(gè)通知, DirectBuffer里面用到
8、Java反射
JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為java語言的反射機(jī)制。
要想解剖一個(gè)類,必須先要獲取到該類的字節(jié)碼文件對(duì)象。而解剖使用的就是Class類中的方法.所以先要獲取到每一個(gè)字節(jié)碼文件對(duì)應(yīng)的Class類型的對(duì)象.
- Class
- Constructor
- Method
- Field
9、Arrays.sort 實(shí)現(xiàn)原理和 Collections.sort 實(shí)現(xiàn)原理
- Arrays.sort -> DualPivotQuicksort 雙基準(zhǔn)快排(O(n log(n))),比傳統(tǒng)(one-pivot)快排要快
- Colelctions.sort 底層調(diào)用Arrays.sort
10、LinkedHashMap的應(yīng)用
- 它繼承自HashMap,實(shí)現(xiàn)了Map<K,V>接口。其內(nèi)部還維護(hù)了一個(gè)雙向鏈表,在每次插入數(shù)據(jù),或者訪問、修改數(shù)據(jù)時(shí),會(huì)增加節(jié)點(diǎn)、或調(diào)整鏈表的節(jié)點(diǎn)順序。以決定迭代時(shí)輸出的順序。
- 默認(rèn)情況,遍歷時(shí)的順序是按照插入節(jié)點(diǎn)的順序。這也是其與HashMap最大的區(qū)別。
也可以在構(gòu)造時(shí)傳入accessOrder參數(shù),使得其遍歷順序按照訪問的順序輸出。 - accessOrder ,默認(rèn)是false,則迭代時(shí)輸出的順序是插入節(jié)點(diǎn)的順序。若為true,則輸出的順序是按照訪問節(jié)點(diǎn)的順序。為true時(shí),可以在這基礎(chǔ)之上構(gòu)建一個(gè)LruCache.
- accessOrder=true的模式下,在afterNodeAccess()函數(shù)中,會(huì)將當(dāng)前被訪問到的節(jié)點(diǎn)e,移動(dòng)至內(nèi)部的雙向鏈表的尾部。值得注意的是,afterNodeAccess()函數(shù)中,會(huì)修改modCount,因此當(dāng)你正在accessOrder=true的模式下,迭代LinkedHashMap時(shí),如果同時(shí)查詢?cè)L問數(shù)據(jù),也會(huì)導(dǎo)致fail-fast,因?yàn)榈捻樞蛞呀?jīng)改變。
- LinkedHashMap相對(duì)于HashMap的源碼比,是很簡(jiǎn)單的。因?yàn)榇髽涞紫潞贸藳?。它繼承了HashMap,僅重寫了幾個(gè)方法,以改變它迭代遍歷時(shí)的順序。這也是其與HashMap相比最大的不同。
在每次插入數(shù)據(jù),或者訪問、修改數(shù)據(jù)時(shí),會(huì)增加節(jié)點(diǎn)、或調(diào)整鏈表的節(jié)點(diǎn)順序。以決定迭代時(shí)輸出的順序。
11、cloneable接口實(shí)現(xiàn)原理
- 它的作用是使一個(gè)類的實(shí)例能夠?qū)⒆陨砜截惖搅硪粋€(gè)新的實(shí)例中,注意,這里所說的“拷貝”拷的是對(duì)象實(shí)例,而不是類的定義,進(jìn)一步說,拷貝的是一個(gè)類的實(shí)例中各字段的值。
- 如果一個(gè)類不實(shí)現(xiàn)該接口就直接調(diào)用clone()方法的話,即便已將clone()方法重寫為public,那還是會(huì)拋出“不支持拷貝”異常。因此,要想使一個(gè)類具備拷貝實(shí)例的功能,那么除了要重寫Object類的clone()方法外,還必須要實(shí)現(xiàn)Cloneable接口。
- 淺拷貝: 對(duì)于對(duì)象成員變量,只是將引用進(jìn)行復(fù)制,原來的引用修改以后,拷貝對(duì)象成員變量的值也會(huì)改變(Object.clone)
- 深拷貝: 新建對(duì)象,將成員變量的值賦值給新建對(duì)象中成員
12、異常分類以及處理機(jī)制
- Checked Exception (IOException, SQLException, InterruptedException)
- Unchecked Exception (NullPointerException,IndexOutOfBoundsException)
13、wait和sleep的區(qū)別
- Thread.sleep, 不會(huì)導(dǎo)致線程釋放鎖,但是也會(huì)釋放CPU
- Object wait, 會(huì)釋放當(dāng)前的鎖, 只有其他線程執(zhí)行notify/notifyAll的時(shí)候才可能重新獲取CPU時(shí)間片
14、數(shù)組在內(nèi)存中如何分配
- 數(shù)組初始化后,該數(shù)組所占用的內(nèi)存空間、長(zhǎng)度都是不可變的
- 一維數(shù)組,二維數(shù)組(存放了數(shù)組的數(shù)組)
- 數(shù)組變量存在棧區(qū),數(shù)組對(duì)象存在堆內(nèi)存,只能通過引用來訪問堆內(nèi)存中的數(shù)據(jù)
Java 并發(fā)
1、synchronized 的實(shí)現(xiàn)原理以及鎖優(yōu)化?
對(duì)象頭和monitor是synchnorized的基礎(chǔ)。
無鎖->偏向鎖->輕量級(jí)鎖->重量級(jí)索
2、volatile 的實(shí)現(xiàn)原理?
java內(nèi)存模型,讀寫屏障, happens before, L1 Cache
3、Java 的信號(hào)燈(Semaphore)?
控制訪問線程的個(gè)數(shù)
4、synchronized 在靜態(tài)方法和普通方法的區(qū)別?
- 普通同步方法,鎖是當(dāng)前實(shí)例對(duì)象
- 靜態(tài)同步方法,鎖是當(dāng)前類的class對(duì)象
- 同步方法塊,鎖是括號(hào)里面的對(duì)象
5、怎么實(shí)現(xiàn)所有線程在等待某個(gè)事件的發(fā)生才會(huì)去執(zhí)行?
- join
- CountDownLatch - A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
- CyclicBarrier - A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other
- BlockingQueue
6、CAS?CAS 有什么缺陷,如何解決?
Compare and Swap, ABA, 版本號(hào)
7、synchronized 和 lock 有什么區(qū)別?
| synchronized | Lock |
|---|---|
| 關(guān)鍵字, jvm實(shí)現(xiàn) | 類 |
| jvm控制鎖的釋放 | 必須在finally釋放鎖,不然容易死鎖 |
| 假設(shè)A線程獲得鎖,B線程等待。如果A線程阻塞,B線程會(huì)一直等待 | 分情況而定,Lock有多個(gè)鎖獲取的方式,具體下面會(huì)說道,大致就是可以嘗試獲得鎖,線程可以不用一直等待 |
| 鎖狀態(tài)無法判斷 | 鎖狀態(tài)可以判斷 |
| 可重入 不可中斷 非公平 | 可重入 可判斷 可公平(兩者皆可) |
| 少量同步 | 大量同步 |
lock():獲取鎖,如果鎖被暫用則一直等待
unlock():釋放鎖
tryLock(): 注意返回類型是boolean,如果獲取鎖的時(shí)候鎖被占用就返回false,否則返回true
tryLock(long time, TimeUnit unit):比起tryLock()就是給了一個(gè)時(shí)間期限,保證等待參數(shù)時(shí)間
lockInterruptibly():用該鎖的獲得方式,如果線程在獲取鎖的階段進(jìn)入了等待,那么可以中斷此線程,先去做別的事
8、Hashtable 是怎么加鎖的 ?
方法上面加鎖
9、HashMap 的并發(fā)問題?
10、ConcurrenHashMap 介紹?1.8 中為什么要用紅黑樹?
Node, 分bucket進(jìn)行cas + sync, 提高性能
11、AQS
LCH
12、如何檢測(cè)死鎖?怎么預(yù)防死鎖?
jstack
- 加鎖順序
- 加鎖時(shí)間
- 死鎖檢測(cè)
- 無鎖實(shí)現(xiàn),隊(duì)列,pipeline...
13、Java 內(nèi)存模型?
本地內(nèi)存- 主內(nèi)存
14、如何保證多線程下 i++ 結(jié)果正確?
AtomicInteger
15、線程池的種類,區(qū)別和使用場(chǎng)景?
newCachedThreadPool
- 底層:返回ThreadPoolExecutor實(shí)例,corePoolSize為0;maximumPoolSize為Integer.MAX_VALUE;keepAliveTime為60L;unit為TimeUnit.SECONDS;workQueue為SynchronousQueue(同步隊(duì)列)
- 通俗:當(dāng)有新任務(wù)到來,則插入到SynchronousQueue中,由于SynchronousQueue是同步隊(duì)列,因此會(huì)在池中尋找可用線程來執(zhí)行,若有可以線程則執(zhí)行,若沒有可用線程則創(chuàng)建一個(gè)線程來執(zhí)行該任務(wù);若池中線程空閑時(shí)間超過指定大小,則該線程會(huì)被銷毀。
- 適用:執(zhí)行很多短期異步的小程序或者負(fù)載較輕的服務(wù)器
newFixedThreadPool
- 底層:返回ThreadPoolExecutor實(shí)例,接收參數(shù)為所設(shè)定線程數(shù)量nThread,corePoolSize為nThread,maximumPoolSize為nThread;keepAliveTime為0L(不限時(shí));unit為:TimeUnit.MILLISECONDS;WorkQueue為:new LinkedBlockingQueue<Runnable>() 無解阻塞隊(duì)列
- 通俗:創(chuàng)建可容納固定數(shù)量線程的池子,每隔線程的存活時(shí)間是無限的,當(dāng)池子滿了就不在添加線程了;如果池中的所有線程均在繁忙狀態(tài),對(duì)于新任務(wù)會(huì)進(jìn)入阻塞隊(duì)列中(無界的阻塞隊(duì)列)
- 適用:執(zhí)行長(zhǎng)期的任務(wù),性能好很多
newSingleThreadExecutor:
- 底層:FinalizableDelegatedExecutorService包裝的ThreadPoolExecutor實(shí)例,corePoolSize為1;maximumPoolSize為1;keepAliveTime為0L;unit為:TimeUnit.MILLISECONDS;workQueue為:new LinkedBlockingQueue<Runnable>() 無解阻塞隊(duì)列
- 通俗:創(chuàng)建只有一個(gè)線程的線程池,且線程的存活時(shí)間是無限的;當(dāng)該線程正繁忙時(shí),對(duì)于新任務(wù)會(huì)進(jìn)入阻塞隊(duì)列中(無界的阻塞隊(duì)列)
- 適用:一個(gè)任務(wù)一個(gè)任務(wù)執(zhí)行的場(chǎng)景
NewScheduledThreadPool
- 底層:創(chuàng)建ScheduledThreadPoolExecutor實(shí)例,corePoolSize為傳遞來的參數(shù),maximumPoolSize為Integer.MAX_VALUE;keepAliveTime為0;unit為:TimeUnit.NANOSECONDS;workQueue為:new DelayedWorkQueue() 一個(gè)按超時(shí)時(shí)間升序排序的隊(duì)列
- 通俗:創(chuàng)建一個(gè)固定大小的線程池,線程池內(nèi)線程存活時(shí)間無限制,線程池可以支持定時(shí)及周期性任務(wù)執(zhí)行,如果所有線程均處于繁忙狀態(tài),對(duì)于新任務(wù)會(huì)進(jìn)入DelayedWorkQueue隊(duì)列中,這是一種按照超時(shí)時(shí)間排序的隊(duì)列結(jié)構(gòu)
- 適用:周期性執(zhí)行任務(wù)的場(chǎng)景
16、分析線程池的實(shí)現(xiàn)原理和線程的調(diào)度過程?
- 線程池剛創(chuàng)建時(shí),里面沒有一個(gè)線程。任務(wù)隊(duì)列是作為參數(shù)傳進(jìn)來的。不過,就算隊(duì)列里面有任務(wù),線程池也不會(huì)馬上執(zhí)行它們。
- 當(dāng)調(diào)用 execute() 方法添加一個(gè)任務(wù)時(shí),線程池會(huì)做如下判斷:
- 如果正在運(yùn)行的線程數(shù)量小于 corePoolSize,那么馬上創(chuàng)建線程運(yùn)行這個(gè)任務(wù);
- 如果正在運(yùn)行的線程數(shù)量大于或等于 corePoolSize,那么將這個(gè)任務(wù)放入隊(duì)列;
- 如果這時(shí)候隊(duì)列滿了,而且正在運(yùn)行的線程數(shù)量小于 maximumPoolSize,那么還是要?jiǎng)?chuàng)建非核心線程立刻運(yùn)行這個(gè)任務(wù);
- 如果隊(duì)列滿了,而且正在運(yùn)行的線程數(shù)量大于或等于 maximumPoolSize,那么線程池會(huì)拋出異常RejectExecutionException。
- 當(dāng)一個(gè)線程完成任務(wù)時(shí),它會(huì)從隊(duì)列中取下一個(gè)任務(wù)來執(zhí)行。
- 當(dāng)一個(gè)線程無事可做,超過一定的時(shí)間(keepAliveTime)時(shí),線程池會(huì)判斷,如果當(dāng)前運(yùn)行的線程數(shù)大于 corePoolSize,那么這個(gè)線程就被停掉。所以線程池的所有任務(wù)完成后,它最終會(huì)收縮到 corePoolSize 的大小。
17、線程池如何調(diào)優(yōu),最大數(shù)目如何確認(rèn)?
18、ThreadLocal原理,用的時(shí)候需要注意什么?
其實(shí)在ThreadLocal類中有一個(gè)靜態(tài)內(nèi)部類ThreadLocalMap(其類似于Map),用鍵值對(duì)的形式存儲(chǔ)每一個(gè)線程的變量副本,ThreadLocalMap中元素的key為當(dāng)前ThreadLocal對(duì)象,而value對(duì)應(yīng)線程的變量副本,每個(gè)線程可能存在多個(gè)ThreadLocal。
總之,為不同線程創(chuàng)建不同的ThreadLocalMap,用線程本身為區(qū)分點(diǎn),每個(gè)線程之間其實(shí)沒有任何的聯(lián)系,說是說存放了變量的副本,其實(shí)可以理解為為每個(gè)線程單獨(dú)new了一個(gè)對(duì)象。
19、CountDownLatch 和 CyclicBarrier 的用法,以及相互之間的差別?
CountDownLatch.countDown
20、LockSupport工具
阻塞
- void park():阻塞當(dāng)前線程,如果調(diào)用unpark方法或者當(dāng)前線程被中斷,從能從park()方法中返回
- void park(Object blocker):功能同方法1,入?yún)⒃黾右粋€(gè)Object對(duì)象,用來記錄導(dǎo)致線程阻塞的阻塞對(duì)象,方便進(jìn)行問題排查;
- void parkNanos(long nanos):阻塞當(dāng)前線程,最長(zhǎng)不超過nanos納秒,增加了超時(shí)返回的特性;
- void parkNanos(Object blocker, long nanos):功能同方法3,入?yún)⒃黾右粋€(gè)Object對(duì)象,用來記錄導(dǎo)致線程阻塞的阻塞對(duì)象,方便進(jìn)行問題排查;
- void parkUntil(long deadline):阻塞當(dāng)前線程,知道deadline;
- void parkUntil(Object blocker, long deadline):功能同方法5,入?yún)⒃黾右粋€(gè)Object對(duì)象,用來記錄導(dǎo)致線程阻塞的阻塞對(duì)象,方便進(jìn)行問題排查;
喚醒
void unpark(Thread thread):喚醒處于阻塞狀態(tài)的指定線程
由synchronzed阻塞的線程加入到同步隊(duì)列,再次被喚醒的線程是隨機(jī)從同步隊(duì)列中選擇的,而LockSupport.unpark(thread)可以指定線程對(duì)象喚醒指定的線程。
21、Condition接口及其實(shí)現(xiàn)原理
- 使當(dāng)前線程進(jìn)入等待狀態(tài)直到被通知(signal)或中斷
- 當(dāng)其他線程調(diào)用singal()或singalAll()方法時(shí),該線程將被喚醒
- 當(dāng)其他線程調(diào)用interrupt()方法中斷當(dāng)前線程
- await()相當(dāng)于synchronized等待喚醒機(jī)制中的wait()方法
*/
void await() throws InterruptedException;
//當(dāng)前線程進(jìn)入等待狀態(tài),直到被喚醒,該方法不響應(yīng)中斷要求
void awaitUninterruptibly();
//調(diào)用該方法,當(dāng)前線程進(jìn)入等待狀態(tài),直到被喚醒或被中斷或超時(shí)
//其中nanosTimeout指的等待超時(shí)時(shí)間,單位納秒
long awaitNanos(long nanosTimeout) throws InterruptedException;
//同awaitNanos,但可以指明時(shí)間單位
boolean await(long time, TimeUnit unit) throws InterruptedException;
//調(diào)用該方法當(dāng)前線程進(jìn)入等待狀態(tài),直到被喚醒、中斷或到達(dá)某個(gè)時(shí)
//間期限(deadline),如果沒到指定時(shí)間就被喚醒,返回true,其他情況返回false
boolean awaitUntil(Date deadline) throws InterruptedException;
//喚醒一個(gè)等待在Condition上的線程,該線程從等待方法返回前必須
//獲取與Condition相關(guān)聯(lián)的鎖,功能與notify()相同
void signal();
//喚醒所有等待在Condition上的線程,該線程從等待方法返回前必須
//獲取與Condition相關(guān)聯(lián)的鎖,功能與notifyAll()相同
void signalAll();
AQS的內(nèi)部類ConditionObject
22、Fork/Join框架的理解
ForkJoinTask與一般任務(wù)的主要區(qū)別在于它需要實(shí)現(xiàn)compute方法,在這個(gè)方法里,首先需要判斷任務(wù)是否足夠小,如果足夠小就直接執(zhí)行任務(wù)。如果不足夠小,就必須分割成兩個(gè)子任務(wù),每個(gè)子任務(wù)在調(diào)用fork方法時(shí),又會(huì)進(jìn)入compute方法,看看當(dāng)前子任務(wù)是否需要繼續(xù)分割成子任務(wù),如果不需要繼續(xù)分割,則執(zhí)行當(dāng)前子任務(wù)并返回結(jié)果。使用join方法會(huì)等待子任務(wù)執(zhí)行完并得到其結(jié)果。
23、分段鎖的原理,鎖力度減小的思考
ConcurrentHashMap
24、八種阻塞隊(duì)列以及各個(gè)阻塞隊(duì)列的特性
- ArrayBlockingQueue :一個(gè)由數(shù)組結(jié)構(gòu)組成的有界阻塞隊(duì)列。
- LinkedBlockingQueue :一個(gè)由鏈表結(jié)構(gòu)組成的有界阻塞隊(duì)列。
- PriorityBlockingQueue :一個(gè)支持優(yōu)先級(jí)排序的無界阻塞隊(duì)列。
- DelayQueue:一個(gè)使用優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn)的無界阻塞隊(duì)列。
- SynchronousQueue:一個(gè)不存儲(chǔ)元素的阻塞隊(duì)列。
- LinkedTransferQueue:一個(gè)由鏈表結(jié)構(gòu)組成的無界阻塞隊(duì)列。
- LinkedBlockingDeque:一個(gè)由鏈表結(jié)構(gòu)組成的雙向阻塞隊(duì)列。
http://ifeve.com/java-blocking-queue/
Spring
1、BeanFactory 和 FactoryBean?
- BeanFactory: 工廠類,用來管理Bean的工廠, getBean, containsBean, isPrototype, getType ...方法
- FactoryBean: 一個(gè)bean, 根據(jù)該Bean的ID從BeanFactory中獲取的實(shí)際上是FactoryBean的getObject()返回的對(duì)象,而不是FactoryBean本身,如果要獲取FactoryBean對(duì)象,請(qǐng)?jiān)趇d前面加一個(gè)&符號(hào)來獲取。
2、Spring IOC 的理解,其初始化過程?
Inversion of Control,
- BeanDifinition的Resource定位, 它由ResourceLoader通過統(tǒng)一的Resource接口來完成,這個(gè)Resource對(duì)各種形式的BeanDifinition的使用都提供了統(tǒng)一的接口。
- BeanDifinition的載入, 把用戶定義好的Bean表示成Ioc容器內(nèi)部的數(shù)據(jù)結(jié)構(gòu),而這個(gè)容器內(nèi)部的數(shù)據(jù)結(jié)構(gòu)就是BeanDifinition。
- BeanDifinition的注冊(cè), 通過調(diào)用BeanDifinitionRegistry借口來實(shí)現(xiàn)的。這個(gè)注冊(cè)過程把載入過程中解析得到的BeanDifinition向Ioc容器進(jìn)行注冊(cè)。在IOC容器內(nèi)部將BeanDifinition注入到一個(gè)HashMap中去,Ioc容器就是通過這個(gè)HashMap來持有這些BeanDifinition數(shù)據(jù)的。
3、BeanFactory 和 ApplicationContext?
BeanFactory
BeanFactory -> HierarchicalBeanFactory -> ConfigurableBeanFactory,是一個(gè)主要的BeanFactory設(shè)計(jì)路徑。
- BeanFactory:基本規(guī)范,比如說getBean()這樣的方法。
- HierarchicalBeanFactory:管理雙親IoC容器規(guī)范,比如說getParentBeanFactory()這樣的方法。
- ConfigurableBeanFactory:對(duì)BeanFactory的配置功能,比如通過setParentBeanFactory()設(shè)置雙親IoC容器,通過addBeanPostProcessor()配置Bean后置處理器。
ApplicationContext
BeanFactory -> ListableBeanFactory 和 HierarchicalBeanFactory -> ApplicationContext -> ConfigurableApplicationContext
- ListableBeanFactory:細(xì)化了許多BeanFactory的功能,比如說getBeanDefinitionNames()。
- ApplicationContext:通過繼承MessageSource、ResourceLoader、ApplicationEventPublisher接口,添加了許多高級(jí)特性。
4、Spring Bean 的生命周期,如何被管理的?

5、Spring Bean 的加載過程是怎樣的?
6、如果要你實(shí)現(xiàn)Spring AOP,請(qǐng)問怎么實(shí)現(xiàn)?
7、如果要你實(shí)現(xiàn)Spring IOC,你會(huì)注意哪些問題?
https://www.cnblogs.com/fingerboy/p/5425813.html
8、Spring 是如何管理事務(wù)的,事務(wù)管理機(jī)制?
http://www.mamicode.com/info-detail-1248286.html
編程式事務(wù)和聲明式事務(wù)
Spring并不直接管理事務(wù),而是提供了多種事務(wù)管理器,他們將事務(wù)管理的職責(zé)委托給Hibernate或者JTA等持久化機(jī)制所提供的相關(guān)平臺(tái)框架的事務(wù)來實(shí)現(xiàn)。
Spring事務(wù)管理器的接口是org.springframework.transaction.PlatformTransactionManager,通過這個(gè)接口,Spring為各個(gè)平臺(tái)如JDBC、Hibernate等都提供了對(duì)應(yīng)的事務(wù)管理器,但是具體的實(shí)現(xiàn)就是各個(gè)平臺(tái)自己的事情了。此接口的內(nèi)容如下:
事務(wù)屬性 TransactionDefinition:
- 傳播行為 int getPropagationBehavior()
- 隔離等級(jí) int getIsolationLevel() //事務(wù)管理器根據(jù)它來控制另外一個(gè)事務(wù)可以看到本事務(wù)內(nèi)的哪些數(shù)據(jù)
- 超時(shí)管理 int getTimeout(); //事務(wù)必須在多少秒內(nèi)完成
- 是否只讀 boolean isReadOnly();
事務(wù)狀態(tài) TransactionStatus
boolean isNewTransaction(); // 是否是新的事物
boolean hasSavepoint(); // 是否有恢復(fù)點(diǎn)
void setRollbackOnly(); // 設(shè)置為只回滾
boolean isRollbackOnly(); // 是否為只回滾
boolean isCompleted; // 是否已完成
9、Spring 的不同事務(wù)傳播行為有哪些,干什么用的?
| 傳播行為 | 含義 |
|---|---|
| PROPAGATION_REQUIRED | 表示當(dāng)前方法必須運(yùn)行在事務(wù)中。如果當(dāng)前事務(wù)存在,方法將會(huì)在該事務(wù)中運(yùn)行。否則,會(huì)啟動(dòng)一個(gè)新的事務(wù) |
| PROPAGATION_SUPPORTS | 表示當(dāng)前方法不需要事務(wù)上下文,但是如果存在當(dāng)前事務(wù)的話,那么該方法會(huì)在這個(gè)事務(wù)中運(yùn)行 |
| PROPAGATION_MANDATORY | 表示該方法必須在事務(wù)中運(yùn)行,如果當(dāng)前事務(wù)不存在,則會(huì)拋出一個(gè)異常 |
| PROPAGATION_REQUIRED_NEW | 表示當(dāng)前方法必須運(yùn)行在它自己的事務(wù)中。一個(gè)新的事務(wù)將被啟動(dòng)。如果存在當(dāng)前事務(wù),在該方法執(zhí)行期間,當(dāng)前事務(wù)會(huì)被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager |
| PROPAGATION_NOT_SUPPORTED | 表示該方法不應(yīng)該運(yùn)行在事務(wù)中。如果存在當(dāng)前事務(wù),在該方法運(yùn)行期間,當(dāng)前事務(wù)將被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager |
| PROPAGATION_NEVER | 表示當(dāng)前方法不應(yīng)該運(yùn)行在事務(wù)上下文中。如果當(dāng)前正有一個(gè)事務(wù)在運(yùn)行,則會(huì)拋出異常 |
| PROPAGATION_NESTED | 表示如果當(dāng)前已經(jīng)存在一個(gè)事務(wù),那么該方法將會(huì)在嵌套事務(wù)中運(yùn)行。嵌套的事務(wù)可以獨(dú)立于當(dāng)前事務(wù)進(jìn)行單獨(dú)地提交或回滾。如果當(dāng)前事務(wù)不存在,那么其行為與PROPAGATION_REQUIRED一樣。注意各廠商對(duì)這種傳播行為的支持是有所差異的??梢詤⒖假Y源管理器的文檔來確認(rèn)它們是否支持嵌套事務(wù) |
10、Spring 中用到了那些設(shè)計(jì)模式?
http://www.javainuse.com/spring/spring-design-patterns
11、Spring MVC 的工作原理?
https://www.cnblogs.com/xiaoxi/p/6164383.html

12、Spring 循環(huán)注入的原理?
http://jinnianshilongnian.iteye.com/blog/1415278
Spring容器循環(huán)依賴包括構(gòu)造器循環(huán)依賴和setter循環(huán)依賴, 兩個(gè)或多個(gè)Bean相互之間的持有對(duì)方。
13、Spring AOP的理解,各個(gè)術(shù)語,他們是怎么相互工作的?
14、Spring 如何保證 Controller 并發(fā)的安全?
Controller單例,避免競(jìng)爭(zhēng)
Netty
1、BIO、NIO和AIO
2、Netty 的各大組件
3、Netty的線程模型
4、TCP 粘包/拆包的原因及解決方法
5、了解哪幾種序列化協(xié)議?包括使用場(chǎng)景和如何去選擇
6、Netty的零拷貝實(shí)現(xiàn)
7、Netty的高性能表現(xiàn)在哪些方面
分布式相關(guān)
1、Dubbo的底層實(shí)現(xiàn)原理和機(jī)制
2、描述一個(gè)服務(wù)從發(fā)布到被消費(fèi)的詳細(xì)過程
3、分布式系統(tǒng)怎么做服務(wù)治理
服務(wù)注冊(cè),發(fā)現(xiàn),服務(wù)升/降級(jí),限流,動(dòng)態(tài)擴(kuò)展,超時(shí)控制,優(yōu)先級(jí)調(diào)度,負(fù)載均衡,監(jiān)控報(bào)警,
4、接口的冪等性的概念
- MVCC方案
- 去重表
- 悲觀鎖
- select + insert
- 狀態(tài)機(jī)冪等
- token機(jī)制,防止頁面重復(fù)提交
- 對(duì)外提供接口的api如何保證冪等,如銀聯(lián)提供的付款接口:需要接入商戶提交付款請(qǐng)求時(shí)附帶:source來源,seq序列號(hào)。source+seq在數(shù)據(jù)庫(kù)里面做唯一索引,防止多次付款,(并發(fā)時(shí),只能處理一個(gè)請(qǐng)求)
4.1 消息中間件解決消息順序和重復(fù)問題
http://dbaplus.cn/news-21-1123-1.html
RocketMQ 特性:
1.順序消息:
RocketMQ通過輪詢所有隊(duì)列的方式來確定消息被發(fā)送到哪一個(gè)隊(duì)列, 在獲取到路由信息以后,會(huì)根據(jù)MessageQueueSelector實(shí)現(xiàn)的算法來選擇一個(gè)隊(duì)列,同一個(gè)OrderId獲取到的肯定是同一個(gè)隊(duì)列
2.重復(fù)消息:
- 消費(fèi)端處理消息的業(yè)務(wù)邏輯保持冪等性
- 保證每條消息都有唯一編號(hào)且保證消息處理成功與去重表的日志同時(shí)出現(xiàn)
3.事務(wù)消息(現(xiàn)在已經(jīng)不支持了)
大事務(wù) = 小事務(wù) + 異步
4.Producer如何發(fā)消息
Producer輪詢某topic下的所有隊(duì)列的方式來實(shí)現(xiàn)發(fā)送方的負(fù)載均衡
5.消息存儲(chǔ)
RocketMQ的消息存儲(chǔ)是由consume queue和commit log配合完成的。
- consume queue是消息的邏輯隊(duì)列,相當(dāng)于字典的目錄,用來指定消息在物理文件commit log上的位置。
死信隊(duì)列(Dead Letter Queue)一般用于存放由于某種原因無法傳遞的消息,比如處理失敗或者已經(jīng)過期的消息。
- CommitLog:消息存放的物理文件,每臺(tái)broker上的commitlog被本機(jī)所有的queue共享,不做任何區(qū)分。
3.消息實(shí)現(xiàn)
4.消息索引
6.消息訂閱
RocketMQ消息訂閱有兩種模式,一種是Push模式,即MQServer主動(dòng)向消費(fèi)端推送;另外一種是Pull模式,即消費(fèi)端在需要時(shí),主動(dòng)到MQServer拉取。但在具體實(shí)現(xiàn)時(shí),Push和Pull模式都是采用消費(fèi)端主動(dòng)拉取的方式。
7.其他特性
定時(shí)消息
消息的刷盤策略
主動(dòng)同步策略:同步雙寫、異步復(fù)制
海量消息堆積能力
高效通信
https://yq.aliyun.com/articles/66101
5、消息中間件如何解決消息丟失問題
消息落地
6、Dubbo的服務(wù)請(qǐng)求失敗怎么處理
超時(shí)和重連機(jī)制
https://my.oschina.net/u/661116/blog/698566
7、重連機(jī)制會(huì)不會(huì)造成錯(cuò)誤
可能會(huì)導(dǎo)致某個(gè)功能調(diào)用多次
8、對(duì)分布式事務(wù)的理解
8.1 強(qiáng)一致性
- 2PC
- 3PC
- Paxos
8.2 最終一致性
消息補(bǔ)償
9、如何實(shí)現(xiàn)負(fù)載均衡,有哪些算法可以實(shí)現(xiàn)?
- 隨機(jī)
- 輪訓(xùn)
- 加權(quán)輪訓(xùn)
- 最小連接數(shù)
- 源地址hash(根據(jù)客戶端的IP地址)
- 一致性hash
10、Zookeeper的用途,選舉的原理是什么?
http://blog.csdn.net/king866/article/details/53992653
分布式應(yīng)用協(xié)調(diào)系統(tǒng),完成統(tǒng)一命名服務(wù)、狀態(tài)同步服務(wù)、集群管理、分布式應(yīng)用配置項(xiàng)的管理等工作。
選舉原理basic 和 fast paxos
11、數(shù)據(jù)的垂直拆分水平拆分。
12、zookeeper原理和適用場(chǎng)景
http://blog.csdn.net/king866/article/details/53992653
12.1 znode節(jié)點(diǎn)
有四種類型的znode:
- PERSISTENT-持久化目錄節(jié)點(diǎn)
客戶端與zookeeper斷開連接后,該節(jié)點(diǎn)依舊存在 - PERSISTENT_SEQUENTIAL-持久化順序編號(hào)目錄節(jié)點(diǎn)
客戶端與zookeeper斷開連接后,該節(jié)點(diǎn)依舊存在,只是Zookeeper給該節(jié)點(diǎn)名稱進(jìn)行順序編號(hào) - EPHEMERAL-臨時(shí)目錄節(jié)點(diǎn)
客戶端與zookeeper斷開連接后,該節(jié)點(diǎn)被刪除 - EPHEMERAL_SEQUENTIAL-臨時(shí)順序編號(hào)目錄節(jié)點(diǎn)
客戶端與zookeeper斷開連接后,該節(jié)點(diǎn)被刪除,只是Zookeeper給該節(jié)點(diǎn)名稱進(jìn)行順序編號(hào)
12.2 NameService 命名服務(wù)
這個(gè)似乎最簡(jiǎn)單,在zookeeper的文件系統(tǒng)里創(chuàng)建一個(gè)目錄,即有唯一的path。在我們使用tborg無法確定上游程序的部署機(jī)器時(shí)即可與下游程序約定好path,通過path即能互相探索發(fā)現(xiàn)
這個(gè)主要是作為分布式命名服務(wù),通過調(diào)用zk的create node api,能夠很容易創(chuàng)建一個(gè)全局唯一的path,這個(gè)path就可以作為一個(gè)名稱。
12.3 configuration 配置管理
現(xiàn)在把這些配置全部放到zookeeper上去,保存在 Zookeeper 的某個(gè)目錄節(jié)點(diǎn)中,然后所有相關(guān)應(yīng)用程序?qū)@個(gè)目錄節(jié)點(diǎn)進(jìn)行監(jiān)聽,一旦配置信息發(fā)生變化,每個(gè)應(yīng)用程序就會(huì)收到 Zookeeper 的通知,然后從 Zookeeper 獲取新的配置信息應(yīng)用到系統(tǒng)中就好。
12.4 GroupMembers 集群管理
所謂集群管理無在乎兩點(diǎn):是否有機(jī)器退出和加入、選舉master。
對(duì)于第一點(diǎn),所有機(jī)器約定在父目錄GroupMembers下創(chuàng)建臨時(shí)目錄節(jié)點(diǎn),然后監(jiān)聽父目錄節(jié)點(diǎn)的子節(jié)點(diǎn)變化消息。一旦有機(jī)器掛掉,該機(jī)器與 zookeeper的連接斷開,其所創(chuàng)建的臨時(shí)目錄節(jié)點(diǎn)被刪除,所有其他機(jī)器都收到通知:某個(gè)兄弟目錄被刪除,于是,所有人都知道了。新機(jī)器加入也是類似,所有機(jī)器收到通知:新兄弟目錄加入,highcount又有了。
對(duì)于第二點(diǎn),所有機(jī)器創(chuàng)建臨時(shí)順序編號(hào)目錄節(jié)點(diǎn),通過master選舉算法選舉出來。
12.5 適用場(chǎng)景
- 數(shù)據(jù)發(fā)布與訂閱 - 將數(shù)據(jù)發(fā)布到zk節(jié)點(diǎn)上,供訂閱者動(dòng)態(tài)獲取數(shù)據(jù),實(shí)現(xiàn)配置信息的集中式管理和動(dòng)態(tài)更新。
- 分布通知/協(xié)調(diào) - watcher注冊(cè)與異步通知機(jī)制,能夠很好的實(shí)現(xiàn)分布式環(huán)境下不同系統(tǒng)之間的通知與協(xié)調(diào),實(shí)現(xiàn)對(duì)數(shù)據(jù)變更的實(shí)時(shí)處理。使用方法通常是不同系統(tǒng)都對(duì) ZK上同一個(gè)znode進(jìn)行注冊(cè),監(jiān)聽znode的變化(包括znode本身內(nèi)容及子節(jié)點(diǎn)的),其中一個(gè)系統(tǒng)update了znode,那么另一個(gè)系統(tǒng)能 夠收到通知,并作出相應(yīng)處理。
- 分布式鎖 - ZooKeeper為我們保證了數(shù)據(jù)的強(qiáng)一致性,即用戶只要完全相信每時(shí)每刻,zk集群中任意節(jié)點(diǎn)(一個(gè)zk server)上的相同znode的數(shù)據(jù)是一定是相同的。鎖服務(wù)可以分為兩類,一個(gè)是保持獨(dú)占,另一個(gè)是控制時(shí)序。
- 集群管理 - 集群機(jī)器監(jiān)控; Master選舉
13、zookeeper watch機(jī)制
http://blog.csdn.net/king866/article/details/53992653
Client可以在某個(gè)ZNode上設(shè)置一個(gè)Watcher,來Watch該ZNode上的變化。如果該ZNode上有相應(yīng)的變化,就會(huì)觸發(fā)這個(gè)Watcher,把相應(yīng)的事件通知給設(shè)置Watcher的Client。需要注意的是,ZooKeeper中的Watcher是一次性的,即觸發(fā)一次就會(huì)被取消,如果想繼續(xù)Watch的話,需要客戶端重新設(shè)置Watcher
- 注冊(cè)只能確保一次消費(fèi), 無論是服務(wù)端還是客戶端,一旦一個(gè) Watcher 被觸發(fā),ZooKeeper 都會(huì)將其從相應(yīng)的存儲(chǔ)中移除。因此,開發(fā)人員在 Watcher 的使用上要記住的一點(diǎn)是需要反復(fù)注冊(cè)。這樣的設(shè)計(jì)有效地減輕了服務(wù)端的壓力。如果注冊(cè)一個(gè) Watcher 之后一直有效,那么針對(duì)那些更新非常頻繁的節(jié)點(diǎn),服務(wù)端會(huì)不斷地向客戶端發(fā)送事件通知,這無論對(duì)于網(wǎng)絡(luò)還是服務(wù)端性能的影響都非常大
- 客戶端串行執(zhí)行,客戶端 Watcher 回調(diào)的過程是一個(gè)串行同步的過程,這為我們保證了順序,同時(shí),需要開發(fā)人員注意的一點(diǎn)是,千萬不要因?yàn)橐粋€(gè) Watcher 的處理邏輯影響了整個(gè)客戶端的 Watcher 回調(diào)。
- 輕量級(jí)設(shè)計(jì),WatchedEvent 是 ZooKeeper 整個(gè) Watcher 通知機(jī)制的最小通知單元,這個(gè)數(shù)據(jù)結(jié)構(gòu)中只包含三部分的內(nèi)容:通知狀態(tài)、事件類型和節(jié)點(diǎn)路徑。也就是說,Watcher 通知非常簡(jiǎn)單,只會(huì)告訴客戶端發(fā)生了事件,而不會(huì)說明事件的具體內(nèi)容。
14、redis/zk節(jié)點(diǎn)宕機(jī)如何處理
重新選舉
15、分布式集群下如何做到唯一序列號(hào)
- 數(shù)據(jù)庫(kù)自增長(zhǎng)
- UUID (包括變種)
- Redis生成ID, 原子操作, INCR 和 INCRBY
16、如何做一個(gè)分布式鎖
https://yq.aliyun.com/articles/60663
- 數(shù)據(jù)庫(kù)
- redis
- zookeeper
17、用過哪些MQ,怎么用的,和其他mq比較有什么優(yōu)缺點(diǎn),MQ的連接是線程安全的嗎
18、MQ系統(tǒng)的數(shù)據(jù)如何保證不丟失
持久化
19、列舉出你能想到的數(shù)據(jù)庫(kù)分庫(kù)分表策略;分庫(kù)分表后,如何解決全表查詢的問題
http://blog.csdn.net/xlgen157387/article/details/53976153
冗余和數(shù)據(jù)字典
20、zookeeper的選舉策略
paxos
21、全局ID
數(shù)據(jù)庫(kù)
1、mysql分頁有什么優(yōu)化
- 如果只使用LIMIT選擇部分行, MySQL大多數(shù)情況會(huì)全表掃描,有時(shí)會(huì)用到索引?
- 如果把LIMIT row_count和ORDER BY 結(jié)合使用, MySQLY一旦找到需要的行數(shù)就會(huì)停止排序,而不會(huì)將所有數(shù)據(jù)進(jìn)行排序,如果排序過程使用到索引速度會(huì)非常快。如果必須用到文件排序(外部排序),那么在獲得row_count對(duì)應(yīng)的結(jié)果之前,所有滿足query條件(這里不考慮LIMIT)的行會(huì)被選中,文件中的數(shù)據(jù)在進(jìn)行外部排序之前應(yīng)該已經(jīng)有序。得到row_count的結(jié)果以后, MySQL不會(huì)對(duì)剩余數(shù)據(jù)進(jìn)行排序。
這帶來的結(jié)果就是帶不帶LIMIT的ORDER BY可能按照不同的順序返回結(jié)果。 - 如果把LIMIT row_count 和 DISTINCT 結(jié)合使用, MySQL會(huì)在找到不重復(fù)的row_count行后立即停止。
- 在某些情況下, GROUP BY 可以通過按順序讀取索引(或?qū)λ饕M(jìn)行排序)來解析,然后計(jì)算結(jié)果直到索引發(fā)生變化。這種情況下,LIMIT row_count 不會(huì)計(jì)算任何非必需的GROUP BY的值。
- 一旦MySQL將需要行數(shù)的結(jié)果發(fā)給客戶端,它會(huì)終止查詢,除非使用SQL_CALC_FOUND_ROWS, 然后使用 SELECT FOUND_ROWS()來獲取行數(shù)。具體參考 2.14章節(jié)。
- LIMIT 0快速返回一個(gè)空集合,可以用來檢查查詢語句是否正確。(后面復(fù)雜,懶得翻譯了...)
- 如果服務(wù)器使用臨時(shí)表來解析查詢,則它使用LIMIT row_count來計(jì)算需要多少空間。
- 如果沒有用到索引,但是LIMIT語句存在,優(yōu)化器可能可以做到避免(文件)歸并排序而使用內(nèi)存中的文件排序。具體請(qǐng)參照In-Memory filesort Algorithm
2、悲觀鎖、樂觀鎖
悲觀鎖: 行級(jí)鎖或者表級(jí)鎖
樂觀鎖: 版本號(hào)
3、組合索引,最左原則
4、mysql 的表鎖、行鎖
不同的mysql引擎默認(rèn)鎖級(jí)別不同:
- innoDB 行鎖, 支持事務(wù),默認(rèn)可重復(fù)讀
- MyISAM 表鎖, 不支持事務(wù)
5、mysql 性能優(yōu)化
話題太大,回頭說...
6、mysql的索引分類:B+,hash;什么情況用什么索引
hash: 只在= 和 <> 時(shí)使用,速度快
B+樹: 正常手動(dòng)創(chuàng)建的索引底層都是B+樹。
7、事務(wù)的特性和隔離級(jí)別
緩存
1、Redis用過哪些數(shù)據(jù)數(shù)據(jù),以及Redis底層怎么實(shí)現(xiàn)
http://www.runoob.com/redis/redis-tutorial.html
String
- SET name "test"
- GET name
Hash
- HMSET
- HGET key
- HGETALL key
List
- LPUSH
- LINSERT KEY_NAME BEFORE EXISTING_VALUE NEW_VALUE
Set
- SADD
- SDROP
ZSet
- ZADD
- ZRANGE
HyperLogLog
- PFADD
- PFCOUNT
http://www.cnblogs.com/jaycekon/p/6227442.html
2、Redis緩存穿透,緩存雪崩
緩存穿透是指查詢一個(gè)一定不存在的數(shù)據(jù):
- 所有可能的數(shù)據(jù)hash到一個(gè)bitmap
- 如果查詢?yōu)榭?進(jìn)行緩存,但是要設(shè)置過期時(shí)間
緩存雪崩:
- 緩存失效時(shí)間盡量隨機(jī)分散
- 二級(jí)緩存, 時(shí)間比一級(jí)緩存時(shí)間長(zhǎng)
3、如何使用Redis來實(shí)現(xiàn)分布式鎖
4、Redis的并發(fā)競(jìng)爭(zhēng)問題如何解決
5、Redis持久化的幾種方式,優(yōu)缺點(diǎn)是什么,怎么實(shí)現(xiàn)的
RDB - redis data base
RDB是在某個(gè)時(shí)間點(diǎn)將數(shù)據(jù)寫入一個(gè)臨時(shí)文件,持久化結(jié)束后,用這個(gè)臨時(shí)文件替換上次持久化的文件,達(dá)到數(shù)據(jù)恢復(fù)
- 優(yōu)點(diǎn):使用單獨(dú)子進(jìn)程來進(jìn)行持久化,主進(jìn)程不會(huì)進(jìn)行任何IO操作,保證了redis的高性能,并且有數(shù)據(jù)快照,回復(fù)數(shù)據(jù)比較簡(jiǎn)單
- 缺點(diǎn): RDB是間隔一段時(shí)間進(jìn)行持久化,如果持久化之間redis發(fā)生故障,會(huì)發(fā)生數(shù)據(jù)丟失
- snapshot觸發(fā)的時(shí)機(jī),是有“間隔時(shí)間”和“變更次數(shù)”共同決定,同時(shí)符合2個(gè)條件才會(huì)觸發(fā)snapshot
AOF - Append only File
將“操作 + 數(shù)據(jù)”以格式化指令的方式追加到操作日志文件的尾部,在append操作返回后(已經(jīng)寫入到文件或者即將寫入),才進(jìn)行實(shí)際的數(shù)據(jù)變更
- 優(yōu)點(diǎn):可以保持更高的數(shù)據(jù)完整性,如果設(shè)置追加file的時(shí)間是1s,如果redis發(fā)生故障,最多會(huì)丟失1s的數(shù)據(jù);且如果日志寫入不完整支持redis-check-aof來進(jìn)行日志修復(fù);AOF文件沒被rewrite之前(文件過大時(shí)會(huì)對(duì)命令進(jìn)行合并重寫),可以刪除其中的某些命令(比如誤操作的flushall)。
- 缺點(diǎn):AOF文件比RDB文件大,且恢復(fù)速度慢。
6、Redis的緩存失效策略
1、如果數(shù)據(jù)呈現(xiàn)冪律分布,也就是一部分?jǐn)?shù)據(jù)訪問頻率高,一部分?jǐn)?shù)據(jù)訪問頻率低,則使用allkeys-lru
2、如果數(shù)據(jù)呈現(xiàn)平等分布,也就是所有的數(shù)據(jù)訪問頻率都相同,則使用allkeys-random
Redis采用的是定期刪除策略和懶漢式的策略互相配合。
懶漢式刪除策略
含義:key過期的時(shí)候不刪除,每次通過key獲取值的時(shí)候去檢查是否過期,若過期,則刪除,返回null。
- 優(yōu)點(diǎn):刪除操作只發(fā)生在通過key取值的時(shí)候發(fā)生,而且只刪除當(dāng)前key,所以對(duì)CPU時(shí)間的占用是比較少的,而且此時(shí)的刪除是已經(jīng)到了非做不可的地步(如果此時(shí)還不刪除的話,我們就會(huì)獲取到了已經(jīng)過期的key了)
- 缺點(diǎn):若大量的key在超出超時(shí)時(shí)間后,很久一段時(shí)間內(nèi),都沒有被獲取過,那么可能發(fā)生內(nèi)存泄露(無用的垃圾占用了大量的內(nèi)存)
定期刪除策略
- 含義:每隔一段時(shí)間執(zhí)行一次刪除過期key操作
- 優(yōu)點(diǎn):
- 通過限制刪除操作的時(shí)長(zhǎng)和頻率,來減少刪除操作對(duì)CPU時(shí)間的占用--處理"定時(shí)刪除"的缺點(diǎn)
- 定期刪除過期key--處理"懶漢式刪除"的缺點(diǎn)
- 缺點(diǎn):
- 在內(nèi)存友好方面,不如"定時(shí)刪除"(會(huì)造成一定的內(nèi)存占用,但是沒有懶漢式那么占用內(nèi)存)
- 在CPU時(shí)間友好方面,不如"懶漢式刪除"(會(huì)定期的去進(jìn)行比較和刪除操作,cpu方面不如懶漢式,但是比定時(shí)好)
- 難點(diǎn):合理設(shè)置刪除操作的執(zhí)行時(shí)長(zhǎng)(每次刪除執(zhí)行多長(zhǎng)時(shí)間)和執(zhí)行頻率(每隔多長(zhǎng)時(shí)間做一次刪除)(這個(gè)要根據(jù)服務(wù)器運(yùn)行情況來定了),每次執(zhí)行時(shí)間太長(zhǎng),或者執(zhí)行頻率太高對(duì)cpu都是一種壓力。
7、Redis集群,高可用,原理
http://blog.csdn.net/yinwenjie/article/details/53672232
http://rdc.hundsun.com/portal/article/669.html
8、Redis緩存分片
http://wiki.jikexueyuan.com/project/redis-guide/partitioning.html
9、Redis的數(shù)據(jù)淘汰策略
- volatile-lru:從已設(shè)置過期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選最近最少使用的數(shù)據(jù)淘汰
- volatile-ttl:從已設(shè)置過期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中挑選將要過期的數(shù)據(jù)淘汰
- volatile-random:從已設(shè)置過期時(shí)間的數(shù)據(jù)集(server.db[i].expires)中任意選擇數(shù)據(jù)淘汰
- allkeys-lru:從數(shù)據(jù)集(server.db[i].dict)中挑選最近最少使用的數(shù)據(jù)淘汰
- allkeys-random:從數(shù)據(jù)集(server.db[i].dict)中任意選擇數(shù)據(jù)淘汰
- no-enviction(驅(qū)逐):禁止驅(qū)逐數(shù)據(jù)