http://www.lxweimin.com/p/a07d1d4004b0 源問題集合
Java基礎
1、List 和 Set 的區別
- List有序,元素可重復
- Set無序,元素不可重復
2、HashSet 是如何保證不重復的
- add之前先判斷hash值,和equals, 一樣就不存
3、HashMap 是線程安全的嗎,為什么不是線程安全的(最好畫圖說明多線程環境下不安全)?
- 不安全, put的時候resize和rehash可能導致死循環
- 遍歷時候不允許修改,ConcurrentModificationException, fast-fail, check modificationCount
4、HashMap 的擴容過程
- size > threshold
- table *= 2
- rehash
5、HashMap 1.7 與 1.8 的 區別,說明 1.8 做了哪些優化,如何優化的?
- 鏈表長度>8 -> 紅黑樹
- rehash算法進行改進
6、final finally finalize
- final, 類不能繼承, 方法不能重載, 變量不能改變
- fianlly 永遠會被執行
- finalize, GC的時候調用, 不應該依賴他, 因為不確定GC什么時候進行
7、強引用 、軟引用、 弱引用、虛引用
- 正常持有的引用
- 內存不夠時候釋放的引用
- GC時候一定釋放的引用
- 可能在對象回收時候收到一個通知, DirectBuffer里面用到
8、Java反射
JAVA反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。
要想解剖一個類,必須先要獲取到該類的字節碼文件對象。而解剖使用的就是Class類中的方法.所以先要獲取到每一個字節碼文件對應的Class類型的對象.
- Class
- Constructor
- Method
- Field
9、Arrays.sort 實現原理和 Collections.sort 實現原理
- Arrays.sort -> DualPivotQuicksort 雙基準快排(O(n log(n))),比傳統(one-pivot)快排要快
- Colelctions.sort 底層調用Arrays.sort
10、LinkedHashMap的應用
- 它繼承自HashMap,實現了Map<K,V>接口。其內部還維護了一個雙向鏈表,在每次插入數據,或者訪問、修改數據時,會增加節點、或調整鏈表的節點順序。以決定迭代時輸出的順序。
- 默認情況,遍歷時的順序是按照插入節點的順序。這也是其與HashMap最大的區別。
也可以在構造時傳入accessOrder參數,使得其遍歷順序按照訪問的順序輸出。 - accessOrder ,默認是false,則迭代時輸出的順序是插入節點的順序。若為true,則輸出的順序是按照訪問節點的順序。為true時,可以在這基礎之上構建一個LruCache.
- accessOrder=true的模式下,在afterNodeAccess()函數中,會將當前被訪問到的節點e,移動至內部的雙向鏈表的尾部。值得注意的是,afterNodeAccess()函數中,會修改modCount,因此當你正在accessOrder=true的模式下,迭代LinkedHashMap時,如果同時查詢訪問數據,也會導致fail-fast,因為迭代的順序已經改變。
- LinkedHashMap相對于HashMap的源碼比,是很簡單的。因為大樹底下好乘涼。它繼承了HashMap,僅重寫了幾個方法,以改變它迭代遍歷時的順序。這也是其與HashMap相比最大的不同。
在每次插入數據,或者訪問、修改數據時,會增加節點、或調整鏈表的節點順序。以決定迭代時輸出的順序。
11、cloneable接口實現原理
- 它的作用是使一個類的實例能夠將自身拷貝到另一個新的實例中,注意,這里所說的“拷貝”拷的是對象實例,而不是類的定義,進一步說,拷貝的是一個類的實例中各字段的值。
- 如果一個類不實現該接口就直接調用clone()方法的話,即便已將clone()方法重寫為public,那還是會拋出“不支持拷貝”異常。因此,要想使一個類具備拷貝實例的功能,那么除了要重寫Object類的clone()方法外,還必須要實現Cloneable接口。
- 淺拷貝: 對于對象成員變量,只是將引用進行復制,原來的引用修改以后,拷貝對象成員變量的值也會改變(Object.clone)
- 深拷貝: 新建對象,將成員變量的值賦值給新建對象中成員
12、異常分類以及處理機制
- Checked Exception (IOException, SQLException, InterruptedException)
- Unchecked Exception (NullPointerException,IndexOutOfBoundsException)
13、wait和sleep的區別
- Thread.sleep, 不會導致線程釋放鎖,但是也會釋放CPU
- Object wait, 會釋放當前的鎖, 只有其他線程執行notify/notifyAll的時候才可能重新獲取CPU時間片
14、數組在內存中如何分配
- 數組初始化后,該數組所占用的內存空間、長度都是不可變的
- 一維數組,二維數組(存放了數組的數組)
- 數組變量存在棧區,數組對象存在堆內存,只能通過引用來訪問堆內存中的數據
Java 并發
1、synchronized 的實現原理以及鎖優化?
對象頭和monitor是synchnorized的基礎。
無鎖->偏向鎖->輕量級鎖->重量級索
2、volatile 的實現原理?
java內存模型,讀寫屏障, happens before, L1 Cache
3、Java 的信號燈(Semaphore)?
控制訪問線程的個數
4、synchronized 在靜態方法和普通方法的區別?
- 普通同步方法,鎖是當前實例對象
- 靜態同步方法,鎖是當前類的class對象
- 同步方法塊,鎖是括號里面的對象
5、怎么實現所有線程在等待某個事件的發生才會去執行?
- 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, 版本號
7、synchronized 和 lock 有什么區別?
synchronized | Lock |
---|---|
關鍵字, jvm實現 | 類 |
jvm控制鎖的釋放 | 必須在finally釋放鎖,不然容易死鎖 |
假設A線程獲得鎖,B線程等待。如果A線程阻塞,B線程會一直等待 | 分情況而定,Lock有多個鎖獲取的方式,具體下面會說道,大致就是可以嘗試獲得鎖,線程可以不用一直等待 |
鎖狀態無法判斷 | 鎖狀態可以判斷 |
可重入 不可中斷 非公平 | 可重入 可判斷 可公平(兩者皆可) |
少量同步 | 大量同步 |
lock():獲取鎖,如果鎖被暫用則一直等待
unlock():釋放鎖
tryLock(): 注意返回類型是boolean,如果獲取鎖的時候鎖被占用就返回false,否則返回true
tryLock(long time, TimeUnit unit):比起tryLock()就是給了一個時間期限,保證等待參數時間
lockInterruptibly():用該鎖的獲得方式,如果線程在獲取鎖的階段進入了等待,那么可以中斷此線程,先去做別的事
8、Hashtable 是怎么加鎖的 ?
方法上面加鎖
9、HashMap 的并發問題?
10、ConcurrenHashMap 介紹?1.8 中為什么要用紅黑樹?
Node, 分bucket進行cas + sync, 提高性能
11、AQS
LCH
12、如何檢測死鎖?怎么預防死鎖?
jstack
- 加鎖順序
- 加鎖時間
- 死鎖檢測
- 無鎖實現,隊列,pipeline...
13、Java 內存模型?
本地內存- 主內存
14、如何保證多線程下 i++ 結果正確?
AtomicInteger
15、線程池的種類,區別和使用場景?
newCachedThreadPool
- 底層:返回ThreadPoolExecutor實例,corePoolSize為0;maximumPoolSize為Integer.MAX_VALUE;keepAliveTime為60L;unit為TimeUnit.SECONDS;workQueue為SynchronousQueue(同步隊列)
- 通俗:當有新任務到來,則插入到SynchronousQueue中,由于SynchronousQueue是同步隊列,因此會在池中尋找可用線程來執行,若有可以線程則執行,若沒有可用線程則創建一個線程來執行該任務;若池中線程空閑時間超過指定大小,則該線程會被銷毀。
- 適用:執行很多短期異步的小程序或者負載較輕的服務器
newFixedThreadPool
- 底層:返回ThreadPoolExecutor實例,接收參數為所設定線程數量nThread,corePoolSize為nThread,maximumPoolSize為nThread;keepAliveTime為0L(不限時);unit為:TimeUnit.MILLISECONDS;WorkQueue為:new LinkedBlockingQueue<Runnable>() 無解阻塞隊列
- 通俗:創建可容納固定數量線程的池子,每隔線程的存活時間是無限的,當池子滿了就不在添加線程了;如果池中的所有線程均在繁忙狀態,對于新任務會進入阻塞隊列中(無界的阻塞隊列)
- 適用:執行長期的任務,性能好很多
newSingleThreadExecutor:
- 底層:FinalizableDelegatedExecutorService包裝的ThreadPoolExecutor實例,corePoolSize為1;maximumPoolSize為1;keepAliveTime為0L;unit為:TimeUnit.MILLISECONDS;workQueue為:new LinkedBlockingQueue<Runnable>() 無解阻塞隊列
- 通俗:創建只有一個線程的線程池,且線程的存活時間是無限的;當該線程正繁忙時,對于新任務會進入阻塞隊列中(無界的阻塞隊列)
- 適用:一個任務一個任務執行的場景
NewScheduledThreadPool
- 底層:創建ScheduledThreadPoolExecutor實例,corePoolSize為傳遞來的參數,maximumPoolSize為Integer.MAX_VALUE;keepAliveTime為0;unit為:TimeUnit.NANOSECONDS;workQueue為:new DelayedWorkQueue() 一個按超時時間升序排序的隊列
- 通俗:創建一個固定大小的線程池,線程池內線程存活時間無限制,線程池可以支持定時及周期性任務執行,如果所有線程均處于繁忙狀態,對于新任務會進入DelayedWorkQueue隊列中,這是一種按照超時時間排序的隊列結構
- 適用:周期性執行任務的場景
16、分析線程池的實現原理和線程的調度過程?
- 線程池剛創建時,里面沒有一個線程。任務隊列是作為參數傳進來的。不過,就算隊列里面有任務,線程池也不會馬上執行它們。
- 當調用 execute() 方法添加一個任務時,線程池會做如下判斷:
- 如果正在運行的線程數量小于 corePoolSize,那么馬上創建線程運行這個任務;
- 如果正在運行的線程數量大于或等于 corePoolSize,那么將這個任務放入隊列;
- 如果這時候隊列滿了,而且正在運行的線程數量小于 maximumPoolSize,那么還是要創建非核心線程立刻運行這個任務;
- 如果隊列滿了,而且正在運行的線程數量大于或等于 maximumPoolSize,那么線程池會拋出異常RejectExecutionException。
- 當一個線程完成任務時,它會從隊列中取下一個任務來執行。
- 當一個線程無事可做,超過一定的時間(keepAliveTime)時,線程池會判斷,如果當前運行的線程數大于 corePoolSize,那么這個線程就被停掉。所以線程池的所有任務完成后,它最終會收縮到 corePoolSize 的大小。
17、線程池如何調優,最大數目如何確認?
18、ThreadLocal原理,用的時候需要注意什么?
其實在ThreadLocal類中有一個靜態內部類ThreadLocalMap(其類似于Map),用鍵值對的形式存儲每一個線程的變量副本,ThreadLocalMap中元素的key為當前ThreadLocal對象,而value對應線程的變量副本,每個線程可能存在多個ThreadLocal。
總之,為不同線程創建不同的ThreadLocalMap,用線程本身為區分點,每個線程之間其實沒有任何的聯系,說是說存放了變量的副本,其實可以理解為為每個線程單獨new了一個對象。
19、CountDownLatch 和 CyclicBarrier 的用法,以及相互之間的差別?
CountDownLatch.countDown
20、LockSupport工具
阻塞
- void park():阻塞當前線程,如果調用unpark方法或者當前線程被中斷,從能從park()方法中返回
- void park(Object blocker):功能同方法1,入參增加一個Object對象,用來記錄導致線程阻塞的阻塞對象,方便進行問題排查;
- void parkNanos(long nanos):阻塞當前線程,最長不超過nanos納秒,增加了超時返回的特性;
- void parkNanos(Object blocker, long nanos):功能同方法3,入參增加一個Object對象,用來記錄導致線程阻塞的阻塞對象,方便進行問題排查;
- void parkUntil(long deadline):阻塞當前線程,知道deadline;
- void parkUntil(Object blocker, long deadline):功能同方法5,入參增加一個Object對象,用來記錄導致線程阻塞的阻塞對象,方便進行問題排查;
喚醒
void unpark(Thread thread):喚醒處于阻塞狀態的指定線程
由synchronzed阻塞的線程加入到同步隊列,再次被喚醒的線程是隨機從同步隊列中選擇的,而LockSupport.unpark(thread)可以指定線程對象喚醒指定的線程。
21、Condition接口及其實現原理
- 使當前線程進入等待狀態直到被通知(signal)或中斷
- 當其他線程調用singal()或singalAll()方法時,該線程將被喚醒
- 當其他線程調用interrupt()方法中斷當前線程
- await()相當于synchronized等待喚醒機制中的wait()方法
*/
void await() throws InterruptedException;
//當前線程進入等待狀態,直到被喚醒,該方法不響應中斷要求
void awaitUninterruptibly();
//調用該方法,當前線程進入等待狀態,直到被喚醒或被中斷或超時
//其中nanosTimeout指的等待超時時間,單位納秒
long awaitNanos(long nanosTimeout) throws InterruptedException;
//同awaitNanos,但可以指明時間單位
boolean await(long time, TimeUnit unit) throws InterruptedException;
//調用該方法當前線程進入等待狀態,直到被喚醒、中斷或到達某個時
//間期限(deadline),如果沒到指定時間就被喚醒,返回true,其他情況返回false
boolean awaitUntil(Date deadline) throws InterruptedException;
//喚醒一個等待在Condition上的線程,該線程從等待方法返回前必須
//獲取與Condition相關聯的鎖,功能與notify()相同
void signal();
//喚醒所有等待在Condition上的線程,該線程從等待方法返回前必須
//獲取與Condition相關聯的鎖,功能與notifyAll()相同
void signalAll();
AQS的內部類ConditionObject
22、Fork/Join框架的理解
ForkJoinTask與一般任務的主要區別在于它需要實現compute方法,在這個方法里,首先需要判斷任務是否足夠小,如果足夠小就直接執行任務。如果不足夠小,就必須分割成兩個子任務,每個子任務在調用fork方法時,又會進入compute方法,看看當前子任務是否需要繼續分割成子任務,如果不需要繼續分割,則執行當前子任務并返回結果。使用join方法會等待子任務執行完并得到其結果。
23、分段鎖的原理,鎖力度減小的思考
ConcurrentHashMap
24、八種阻塞隊列以及各個阻塞隊列的特性
- ArrayBlockingQueue :一個由數組結構組成的有界阻塞隊列。
- LinkedBlockingQueue :一個由鏈表結構組成的有界阻塞隊列。
- PriorityBlockingQueue :一個支持優先級排序的無界阻塞隊列。
- DelayQueue:一個使用優先級隊列實現的無界阻塞隊列。
- SynchronousQueue:一個不存儲元素的阻塞隊列。
- LinkedTransferQueue:一個由鏈表結構組成的無界阻塞隊列。
- LinkedBlockingDeque:一個由鏈表結構組成的雙向阻塞隊列。
http://ifeve.com/java-blocking-queue/
Spring
1、BeanFactory 和 FactoryBean?
- BeanFactory: 工廠類,用來管理Bean的工廠, getBean, containsBean, isPrototype, getType ...方法
- FactoryBean: 一個bean, 根據該Bean的ID從BeanFactory中獲取的實際上是FactoryBean的getObject()返回的對象,而不是FactoryBean本身,如果要獲取FactoryBean對象,請在id前面加一個&符號來獲取。
2、Spring IOC 的理解,其初始化過程?
Inversion of Control,
- BeanDifinition的Resource定位, 它由ResourceLoader通過統一的Resource接口來完成,這個Resource對各種形式的BeanDifinition的使用都提供了統一的接口。
- BeanDifinition的載入, 把用戶定義好的Bean表示成Ioc容器內部的數據結構,而這個容器內部的數據結構就是BeanDifinition。
- BeanDifinition的注冊, 通過調用BeanDifinitionRegistry借口來實現的。這個注冊過程把載入過程中解析得到的BeanDifinition向Ioc容器進行注冊。在IOC容器內部將BeanDifinition注入到一個HashMap中去,Ioc容器就是通過這個HashMap來持有這些BeanDifinition數據的。
3、BeanFactory 和 ApplicationContext?
BeanFactory
BeanFactory -> HierarchicalBeanFactory -> ConfigurableBeanFactory,是一個主要的BeanFactory設計路徑。
- BeanFactory:基本規范,比如說getBean()這樣的方法。
- HierarchicalBeanFactory:管理雙親IoC容器規范,比如說getParentBeanFactory()這樣的方法。
- ConfigurableBeanFactory:對BeanFactory的配置功能,比如通過setParentBeanFactory()設置雙親IoC容器,通過addBeanPostProcessor()配置Bean后置處理器。
ApplicationContext
BeanFactory -> ListableBeanFactory 和 HierarchicalBeanFactory -> ApplicationContext -> ConfigurableApplicationContext
- ListableBeanFactory:細化了許多BeanFactory的功能,比如說getBeanDefinitionNames()。
- ApplicationContext:通過繼承MessageSource、ResourceLoader、ApplicationEventPublisher接口,添加了許多高級特性。
4、Spring Bean 的生命周期,如何被管理的?
5、Spring Bean 的加載過程是怎樣的?
6、如果要你實現Spring AOP,請問怎么實現?
7、如果要你實現Spring IOC,你會注意哪些問題?
https://www.cnblogs.com/fingerboy/p/5425813.html
8、Spring 是如何管理事務的,事務管理機制?
http://www.mamicode.com/info-detail-1248286.html
編程式事務和聲明式事務
Spring并不直接管理事務,而是提供了多種事務管理器,他們將事務管理的職責委托給Hibernate或者JTA等持久化機制所提供的相關平臺框架的事務來實現。
Spring事務管理器的接口是org.springframework.transaction.PlatformTransactionManager,通過這個接口,Spring為各個平臺如JDBC、Hibernate等都提供了對應的事務管理器,但是具體的實現就是各個平臺自己的事情了。此接口的內容如下:
事務屬性 TransactionDefinition:
- 傳播行為 int getPropagationBehavior()
- 隔離等級 int getIsolationLevel() //事務管理器根據它來控制另外一個事務可以看到本事務內的哪些數據
- 超時管理 int getTimeout(); //事務必須在多少秒內完成
- 是否只讀 boolean isReadOnly();
事務狀態 TransactionStatus
boolean isNewTransaction(); // 是否是新的事物
boolean hasSavepoint(); // 是否有恢復點
void setRollbackOnly(); // 設置為只回滾
boolean isRollbackOnly(); // 是否為只回滾
boolean isCompleted; // 是否已完成
9、Spring 的不同事務傳播行為有哪些,干什么用的?
傳播行為 | 含義 |
---|---|
PROPAGATION_REQUIRED | 表示當前方法必須運行在事務中。如果當前事務存在,方法將會在該事務中運行。否則,會啟動一個新的事務 |
PROPAGATION_SUPPORTS | 表示當前方法不需要事務上下文,但是如果存在當前事務的話,那么該方法會在這個事務中運行 |
PROPAGATION_MANDATORY | 表示該方法必須在事務中運行,如果當前事務不存在,則會拋出一個異常 |
PROPAGATION_REQUIRED_NEW | 表示當前方法必須運行在它自己的事務中。一個新的事務將被啟動。如果存在當前事務,在該方法執行期間,當前事務會被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager |
PROPAGATION_NOT_SUPPORTED | 表示該方法不應該運行在事務中。如果存在當前事務,在該方法運行期間,當前事務將被掛起。如果使用JTATransactionManager的話,則需要訪問TransactionManager |
PROPAGATION_NEVER | 表示當前方法不應該運行在事務上下文中。如果當前正有一個事務在運行,則會拋出異常 |
PROPAGATION_NESTED | 表示如果當前已經存在一個事務,那么該方法將會在嵌套事務中運行。嵌套的事務可以獨立于當前事務進行單獨地提交或回滾。如果當前事務不存在,那么其行為與PROPAGATION_REQUIRED一樣。注意各廠商對這種傳播行為的支持是有所差異的。可以參考資源管理器的文檔來確認它們是否支持嵌套事務 |
10、Spring 中用到了那些設計模式?
http://www.javainuse.com/spring/spring-design-patterns
11、Spring MVC 的工作原理?
https://www.cnblogs.com/xiaoxi/p/6164383.html
12、Spring 循環注入的原理?
http://jinnianshilongnian.iteye.com/blog/1415278
Spring容器循環依賴包括構造器循環依賴和setter循環依賴, 兩個或多個Bean相互之間的持有對方。
13、Spring AOP的理解,各個術語,他們是怎么相互工作的?
14、Spring 如何保證 Controller 并發的安全?
Controller單例,避免競爭
Netty
1、BIO、NIO和AIO
2、Netty 的各大組件
3、Netty的線程模型
4、TCP 粘包/拆包的原因及解決方法
5、了解哪幾種序列化協議?包括使用場景和如何去選擇
6、Netty的零拷貝實現
7、Netty的高性能表現在哪些方面
分布式相關
1、Dubbo的底層實現原理和機制
2、描述一個服務從發布到被消費的詳細過程
3、分布式系統怎么做服務治理
服務注冊,發現,服務升/降級,限流,動態擴展,超時控制,優先級調度,負載均衡,監控報警,
4、接口的冪等性的概念
- MVCC方案
- 去重表
- 悲觀鎖
- select + insert
- 狀態機冪等
- token機制,防止頁面重復提交
- 對外提供接口的api如何保證冪等,如銀聯提供的付款接口:需要接入商戶提交付款請求時附帶:source來源,seq序列號。source+seq在數據庫里面做唯一索引,防止多次付款,(并發時,只能處理一個請求)
4.1 消息中間件解決消息順序和重復問題
http://dbaplus.cn/news-21-1123-1.html
RocketMQ 特性:
1.順序消息:
RocketMQ通過輪詢所有隊列的方式來確定消息被發送到哪一個隊列, 在獲取到路由信息以后,會根據MessageQueueSelector實現的算法來選擇一個隊列,同一個OrderId獲取到的肯定是同一個隊列
2.重復消息:
- 消費端處理消息的業務邏輯保持冪等性
- 保證每條消息都有唯一編號且保證消息處理成功與去重表的日志同時出現
3.事務消息(現在已經不支持了)
大事務 = 小事務 + 異步
4.Producer如何發消息
Producer輪詢某topic下的所有隊列的方式來實現發送方的負載均衡
5.消息存儲
RocketMQ的消息存儲是由consume queue和commit log配合完成的。
- consume queue是消息的邏輯隊列,相當于字典的目錄,用來指定消息在物理文件commit log上的位置。
死信隊列(Dead Letter Queue)一般用于存放由于某種原因無法傳遞的消息,比如處理失敗或者已經過期的消息。
- CommitLog:消息存放的物理文件,每臺broker上的commitlog被本機所有的queue共享,不做任何區分。
3.消息實現
4.消息索引
6.消息訂閱
RocketMQ消息訂閱有兩種模式,一種是Push模式,即MQServer主動向消費端推送;另外一種是Pull模式,即消費端在需要時,主動到MQServer拉取。但在具體實現時,Push和Pull模式都是采用消費端主動拉取的方式。
7.其他特性
定時消息
消息的刷盤策略
主動同步策略:同步雙寫、異步復制
海量消息堆積能力
高效通信
https://yq.aliyun.com/articles/66101
5、消息中間件如何解決消息丟失問題
消息落地
6、Dubbo的服務請求失敗怎么處理
超時和重連機制
https://my.oschina.net/u/661116/blog/698566
7、重連機制會不會造成錯誤
可能會導致某個功能調用多次
8、對分布式事務的理解
8.1 強一致性
- 2PC
- 3PC
- Paxos
8.2 最終一致性
消息補償
9、如何實現負載均衡,有哪些算法可以實現?
- 隨機
- 輪訓
- 加權輪訓
- 最小連接數
- 源地址hash(根據客戶端的IP地址)
- 一致性hash
10、Zookeeper的用途,選舉的原理是什么?
http://blog.csdn.net/king866/article/details/53992653
分布式應用協調系統,完成統一命名服務、狀態同步服務、集群管理、分布式應用配置項的管理等工作。
選舉原理basic 和 fast paxos
11、數據的垂直拆分水平拆分。
12、zookeeper原理和適用場景
http://blog.csdn.net/king866/article/details/53992653
12.1 znode節點
有四種類型的znode:
- PERSISTENT-持久化目錄節點
客戶端與zookeeper斷開連接后,該節點依舊存在 - PERSISTENT_SEQUENTIAL-持久化順序編號目錄節點
客戶端與zookeeper斷開連接后,該節點依舊存在,只是Zookeeper給該節點名稱進行順序編號 - EPHEMERAL-臨時目錄節點
客戶端與zookeeper斷開連接后,該節點被刪除 - EPHEMERAL_SEQUENTIAL-臨時順序編號目錄節點
客戶端與zookeeper斷開連接后,該節點被刪除,只是Zookeeper給該節點名稱進行順序編號
12.2 NameService 命名服務
這個似乎最簡單,在zookeeper的文件系統里創建一個目錄,即有唯一的path。在我們使用tborg無法確定上游程序的部署機器時即可與下游程序約定好path,通過path即能互相探索發現
這個主要是作為分布式命名服務,通過調用zk的create node api,能夠很容易創建一個全局唯一的path,這個path就可以作為一個名稱。
12.3 configuration 配置管理
現在把這些配置全部放到zookeeper上去,保存在 Zookeeper 的某個目錄節點中,然后所有相關應用程序對這個目錄節點進行監聽,一旦配置信息發生變化,每個應用程序就會收到 Zookeeper 的通知,然后從 Zookeeper 獲取新的配置信息應用到系統中就好。
12.4 GroupMembers 集群管理
所謂集群管理無在乎兩點:是否有機器退出和加入、選舉master。
對于第一點,所有機器約定在父目錄GroupMembers下創建臨時目錄節點,然后監聽父目錄節點的子節點變化消息。一旦有機器掛掉,該機器與 zookeeper的連接斷開,其所創建的臨時目錄節點被刪除,所有其他機器都收到通知:某個兄弟目錄被刪除,于是,所有人都知道了。新機器加入也是類似,所有機器收到通知:新兄弟目錄加入,highcount又有了。
對于第二點,所有機器創建臨時順序編號目錄節點,通過master選舉算法選舉出來。
12.5 適用場景
- 數據發布與訂閱 - 將數據發布到zk節點上,供訂閱者動態獲取數據,實現配置信息的集中式管理和動態更新。
- 分布通知/協調 - watcher注冊與異步通知機制,能夠很好的實現分布式環境下不同系統之間的通知與協調,實現對數據變更的實時處理。使用方法通常是不同系統都對 ZK上同一個znode進行注冊,監聽znode的變化(包括znode本身內容及子節點的),其中一個系統update了znode,那么另一個系統能 夠收到通知,并作出相應處理。
- 分布式鎖 - ZooKeeper為我們保證了數據的強一致性,即用戶只要完全相信每時每刻,zk集群中任意節點(一個zk server)上的相同znode的數據是一定是相同的。鎖服務可以分為兩類,一個是保持獨占,另一個是控制時序。
- 集群管理 - 集群機器監控; Master選舉
13、zookeeper watch機制
http://blog.csdn.net/king866/article/details/53992653
Client可以在某個ZNode上設置一個Watcher,來Watch該ZNode上的變化。如果該ZNode上有相應的變化,就會觸發這個Watcher,把相應的事件通知給設置Watcher的Client。需要注意的是,ZooKeeper中的Watcher是一次性的,即觸發一次就會被取消,如果想繼續Watch的話,需要客戶端重新設置Watcher
- 注冊只能確保一次消費, 無論是服務端還是客戶端,一旦一個 Watcher 被觸發,ZooKeeper 都會將其從相應的存儲中移除。因此,開發人員在 Watcher 的使用上要記住的一點是需要反復注冊。這樣的設計有效地減輕了服務端的壓力。如果注冊一個 Watcher 之后一直有效,那么針對那些更新非常頻繁的節點,服務端會不斷地向客戶端發送事件通知,這無論對于網絡還是服務端性能的影響都非常大
- 客戶端串行執行,客戶端 Watcher 回調的過程是一個串行同步的過程,這為我們保證了順序,同時,需要開發人員注意的一點是,千萬不要因為一個 Watcher 的處理邏輯影響了整個客戶端的 Watcher 回調。
- 輕量級設計,WatchedEvent 是 ZooKeeper 整個 Watcher 通知機制的最小通知單元,這個數據結構中只包含三部分的內容:通知狀態、事件類型和節點路徑。也就是說,Watcher 通知非常簡單,只會告訴客戶端發生了事件,而不會說明事件的具體內容。
14、redis/zk節點宕機如何處理
重新選舉
15、分布式集群下如何做到唯一序列號
- 數據庫自增長
- UUID (包括變種)
- Redis生成ID, 原子操作, INCR 和 INCRBY
16、如何做一個分布式鎖
https://yq.aliyun.com/articles/60663
- 數據庫
- redis
- zookeeper
17、用過哪些MQ,怎么用的,和其他mq比較有什么優缺點,MQ的連接是線程安全的嗎
18、MQ系統的數據如何保證不丟失
持久化
19、列舉出你能想到的數據庫分庫分表策略;分庫分表后,如何解決全表查詢的問題
http://blog.csdn.net/xlgen157387/article/details/53976153
冗余和數據字典
20、zookeeper的選舉策略
paxos
21、全局ID
數據庫
1、mysql分頁有什么優化
- 如果只使用LIMIT選擇部分行, MySQL大多數情況會全表掃描,有時會用到索引?
- 如果把LIMIT row_count和ORDER BY 結合使用, MySQLY一旦找到需要的行數就會停止排序,而不會將所有數據進行排序,如果排序過程使用到索引速度會非常快。如果必須用到文件排序(外部排序),那么在獲得row_count對應的結果之前,所有滿足query條件(這里不考慮LIMIT)的行會被選中,文件中的數據在進行外部排序之前應該已經有序。得到row_count的結果以后, MySQL不會對剩余數據進行排序。
這帶來的結果就是帶不帶LIMIT的ORDER BY可能按照不同的順序返回結果。 - 如果把LIMIT row_count 和 DISTINCT 結合使用, MySQL會在找到不重復的row_count行后立即停止。
- 在某些情況下, GROUP BY 可以通過按順序讀取索引(或對索引進行排序)來解析,然后計算結果直到索引發生變化。這種情況下,LIMIT row_count 不會計算任何非必需的GROUP BY的值。
- 一旦MySQL將需要行數的結果發給客戶端,它會終止查詢,除非使用SQL_CALC_FOUND_ROWS, 然后使用 SELECT FOUND_ROWS()來獲取行數。具體參考 2.14章節。
- LIMIT 0快速返回一個空集合,可以用來檢查查詢語句是否正確。(后面復雜,懶得翻譯了...)
- 如果服務器使用臨時表來解析查詢,則它使用LIMIT row_count來計算需要多少空間。
- 如果沒有用到索引,但是LIMIT語句存在,優化器可能可以做到避免(文件)歸并排序而使用內存中的文件排序。具體請參照In-Memory filesort Algorithm
2、悲觀鎖、樂觀鎖
悲觀鎖: 行級鎖或者表級鎖
樂觀鎖: 版本號
3、組合索引,最左原則
4、mysql 的表鎖、行鎖
不同的mysql引擎默認鎖級別不同:
- innoDB 行鎖, 支持事務,默認可重復讀
- MyISAM 表鎖, 不支持事務
5、mysql 性能優化
話題太大,回頭說...
6、mysql的索引分類:B+,hash;什么情況用什么索引
hash: 只在= 和 <> 時使用,速度快
B+樹: 正常手動創建的索引底層都是B+樹。
7、事務的特性和隔離級別
緩存
1、Redis用過哪些數據數據,以及Redis底層怎么實現
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緩存穿透,緩存雪崩
緩存穿透是指查詢一個一定不存在的數據:
- 所有可能的數據hash到一個bitmap
- 如果查詢為空,進行緩存,但是要設置過期時間
緩存雪崩:
- 緩存失效時間盡量隨機分散
- 二級緩存, 時間比一級緩存時間長
3、如何使用Redis來實現分布式鎖
4、Redis的并發競爭問題如何解決
5、Redis持久化的幾種方式,優缺點是什么,怎么實現的
RDB - redis data base
RDB是在某個時間點將數據寫入一個臨時文件,持久化結束后,用這個臨時文件替換上次持久化的文件,達到數據恢復
- 優點:使用單獨子進程來進行持久化,主進程不會進行任何IO操作,保證了redis的高性能,并且有數據快照,回復數據比較簡單
- 缺點: RDB是間隔一段時間進行持久化,如果持久化之間redis發生故障,會發生數據丟失
- snapshot觸發的時機,是有“間隔時間”和“變更次數”共同決定,同時符合2個條件才會觸發snapshot
AOF - Append only File
將“操作 + 數據”以格式化指令的方式追加到操作日志文件的尾部,在append操作返回后(已經寫入到文件或者即將寫入),才進行實際的數據變更
- 優點:可以保持更高的數據完整性,如果設置追加file的時間是1s,如果redis發生故障,最多會丟失1s的數據;且如果日志寫入不完整支持redis-check-aof來進行日志修復;AOF文件沒被rewrite之前(文件過大時會對命令進行合并重寫),可以刪除其中的某些命令(比如誤操作的flushall)。
- 缺點:AOF文件比RDB文件大,且恢復速度慢。
6、Redis的緩存失效策略
1、如果數據呈現冪律分布,也就是一部分數據訪問頻率高,一部分數據訪問頻率低,則使用allkeys-lru
2、如果數據呈現平等分布,也就是所有的數據訪問頻率都相同,則使用allkeys-random
Redis采用的是定期刪除策略和懶漢式的策略互相配合。
懶漢式刪除策略
含義:key過期的時候不刪除,每次通過key獲取值的時候去檢查是否過期,若過期,則刪除,返回null。
- 優點:刪除操作只發生在通過key取值的時候發生,而且只刪除當前key,所以對CPU時間的占用是比較少的,而且此時的刪除是已經到了非做不可的地步(如果此時還不刪除的話,我們就會獲取到了已經過期的key了)
- 缺點:若大量的key在超出超時時間后,很久一段時間內,都沒有被獲取過,那么可能發生內存泄露(無用的垃圾占用了大量的內存)
定期刪除策略
- 含義:每隔一段時間執行一次刪除過期key操作
- 優點:
- 通過限制刪除操作的時長和頻率,來減少刪除操作對CPU時間的占用--處理"定時刪除"的缺點
- 定期刪除過期key--處理"懶漢式刪除"的缺點
- 缺點:
- 在內存友好方面,不如"定時刪除"(會造成一定的內存占用,但是沒有懶漢式那么占用內存)
- 在CPU時間友好方面,不如"懶漢式刪除"(會定期的去進行比較和刪除操作,cpu方面不如懶漢式,但是比定時好)
- 難點:合理設置刪除操作的執行時長(每次刪除執行多長時間)和執行頻率(每隔多長時間做一次刪除)(這個要根據服務器運行情況來定了),每次執行時間太長,或者執行頻率太高對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的數據淘汰策略
- volatile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
- volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
- volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰
- allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
- allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
- no-enviction(驅逐):禁止驅逐數據