1. 程式人生 > >2018年Java面試題整理(持續整理中)

2018年Java面試題整理(持續整理中)

一.基礎知識:


1)集合類:List和Set比較,各自的子類比較(ArrayList,Vector,LinkedList;HashSet,TreeSet)

List:元素是有順序的,元素可以重複因為每個元素有自己的角標(索引)
  |-- ArrayList:底層是陣列結構,特點是:查詢很快,增刪稍微慢點,執行緒不同步:A執行緒將元素放在索引0位置,CPU排程執行緒A停止,B執行,也將元素放在索引0位置,當A和B同時執行的時候Size就程式設計了2.
  |-- LinkedList:底層使用的是連結串列資料結構,特點是:增刪很快,查詢慢。執行緒不安全,執行緒安全問題是由多個執行緒同時寫或同時讀寫同一個資源造成的。
  |--Vector:底層是陣列資料結構,執行緒同步,Vector的方法前面加了synchronized關鍵字,被ArrayList代替了,現在用的只有他的列舉。

Set:元素是無序的,且不可以重複(存入和取出的順序不一定一致),執行緒不同步。set底層是使用Map實現的,故可以通過ConcurrentHashMap的方式變通實現執行緒安全的Set。
|--HashSet:底層是雜湊表資料結構。根據hashCode和equals方法來確定元素的唯一性。
hashCode和equals:作用一樣,都是用來比較兩個物件是否相等一致。
equals比較的比較全面,而利用hashCode()進行對比,則只要生成一個hash值進行比較久可以了,效率高。
equal()相等的兩個物件他們的hashCode()肯定相等,也就是equal()是絕對可靠的。
hashCode()相等的兩個物件他們的equal()不一定相等,hashCode()不是絕對可靠的。

Map:這個集合是儲存鍵值對的,一對一對往裡存,而且要確保鍵的唯一性(01,張三)這樣的形式打印出來就是  01=張三
|--HashTable:底層是雜湊表資料結構,不可以存入null鍵和null值,該集合執行緒是同步的,效率比較低。出現於JDK1.0。執行緒安全,使用synchronized鎖住整張Hash表實現執行緒安全,即每次鎖住整張表讓執行緒獨佔。
|--HashMap:底層是雜湊表資料結構,可以存入null鍵和null值,執行緒不同步,效率較高,代替了HashTable,出現於JDK 1.2
|--TreeMap:底層是二叉樹資料結構,執行緒不同步,可以用於對map集合中的鍵進行排序
ConcurrentHashMap:執行緒安全,允許多個修改操作併發進行,其關鍵在於使用了鎖分離技術,它使用了多個鎖來控制對hash表的不同部分進行的修改。ConcurrentHashMap內部使用段(Segment)來表示這些不同的部分,每個段其實就是一個小的Hashtable,它們有自己的鎖。只要多個修改操作發生在不同的段上,它們就可以併發進行。
當兩個物件需要對比的時候,首先用hashCode()去對比,如果不一樣,則表示這兩個物件肯定不相等(也就不用再比較equal(0)了),如果hashCode()相同,再比較equal(),如果equal()相同,那兩個物件就是相同的。
|--TreeSet:可以對Set集合中的元素進行排序(自然循序),底層的資料結構是二叉樹,

2)HashMap的底層實現,之後會問ConcurrentHashMap的底層實現

HashMap實際上是一個“連結串列雜湊”的資料結構,即陣列和連結串列的結合體。允許使用null值和null鍵。

HashMap底層就是一個數組結構,陣列中的每一項又是一個連結串列。當新建一個HashMap的時候,就會初始化一個數組。

HashMap是基於hash演算法實現的,通過put(key,value)儲存物件到HashMap中,也可以通過get(key)從HashMap中獲取物件。

當我們使用put的時候,首先HashMap會對key的hashCode()的值進行hash計算,根據hash值得到這個元素在陣列中的位置,將元素儲存在該位置的連結串列上。
當我們使用get的時候,首先HashMap會對key的hashCode()的值進行hash計算,根據hash值得到這個元素在陣列中的位置,將元素從該位置上的連結串列中取出


當多執行緒的情況下,可能產生條件競爭。當重新調整HashMap大小的時候,確實存在條件競爭,如果兩個執行緒都發現HashMap需要重新調整大小了,
它們會同時試著調整大小。在調整大小的過程中,儲存在連結串列中的元素的次序會反過來,因為移動到新的陣列位置的時候,
HashMap並不會將元素放在LinkedList的尾部,而是放在頭部,這是為了避免尾部遍歷(tail traversing)。如果條件競爭發生了,那麼就死迴圈了

ConcurrentHashMap基於雙陣列和連結串列的Map介面的同步實現 
ConcurrentHashMap中元素的key是唯一的、value值可重複 
ConcurrentHashMap不允許使用null值和null鍵 
ConcurrentHashMap是無序的


為什麼使用ConcurrentHashMap:
我們都知道HashMap是非執行緒安全的,當我們只有一個執行緒在使用HashMap的時候,自然不會有問題,但如果涉及到多個執行緒,並且有讀有寫的過程中,HashMap就會fail-fast。要解決HashMap同步的問題,我們的解決方案有:Hashtable 、Collections.synchronizedMap(hashMap) 
這兩種方式基本都是對整個hash表結構加上同步鎖,這樣在鎖表的期間,別的執行緒就需要等待了,無疑效能不高,所以我們引入ConcurrentHashMap,既能同步又能多執行緒訪問
ConcurrentHashMap的資料結構:
ConcurrentHashMap的資料結構為一個Segment陣列,Segment的資料結構為HashEntry的陣列,而HashEntry存的是我們的鍵值對,可以構成連結串列。可以簡單的理解為數組裡裝的是HashMap

3)如何實現HashMap順序儲存:可以參考LinkedHashMap的底層實現
LinkedHashMap底層使用雜湊表與雙向連結串列來儲存所有元素,它維護著一個運行於所有條目的雙向連結串列(如果學過雙向連結串列的同學會更好的理解它的原始碼),此連結串列定義了迭代順序,該迭代順序可以是插入順序或者是訪問順序 
1.按插入順序的連結串列:在LinkedHashMap呼叫get方法後,輸出的順序和輸入時的相同,這就是按插入順序的連結串列,預設是按插入順序排序
2.按訪問順序的連結串列:在LinkedHashMap呼叫get方法後,會將這次訪問的元素移至連結串列尾部,不斷訪問可以形成按訪問順序排序的連結串列。簡單的說,按最近最少訪問的元素進行排序(類似LRU演算法)


4)String,StringBuffer和StringBuilder的區別
執行速度快慢為:StringBuilder > StringBuffer > String
String最慢的原因:
String為字串常量,而StringBuilder和StringBuffer均為字串變數,即String物件一旦建立之後該物件是不可更改的,但後兩者的物件是變數,是可以更改的。
String:適用於少量的字串操作的情況,
StringBuilder:適用於單執行緒下在字元緩衝區進行大量操作的情況(執行緒不安全)
StringBuffer:適用多執行緒下在字元緩衝區進行大量操作的情況(執行緒安全)


5)Object的方法有哪些:比如有wait方法,為什麼會有
wait、notify、notifuAll
1.使用wait()、notify()和notifyAll()時需要首先對呼叫物件加鎖
2.呼叫wait()方法後,執行緒狀態會從RUNNING變為WAITING,並將當執行緒加入到lock物件的等待佇列中
3.呼叫notify()或者notifyAll()方法後,等待在lock物件的等待佇列的執行緒不會馬上從wait()方法返回,必須要等到呼叫notify()或者notifyAll()方法的執行緒將lock鎖釋放,等待執行緒才有機會從等待佇列返回。這裡只是有機會,因為鎖釋放後,等待執行緒會出現競爭,只有競爭到該鎖的執行緒才會從wait()方法返回,其他的執行緒只能繼續等待
4.notify()方法將等待佇列中的一個執行緒移到lock物件的同步佇列,notifyAll()方法則是將等待佇列中所有執行緒移到lock物件的同步佇列,被移動的執行緒的狀態由WAITING變為BLOCKED
5.wait()方法上等待鎖,可以通過wait(long timeout)設定等待的超時時間


6)wait和sleep的區別,必須理解
sleep方法屬於執行緒,wait方法屬於物件
sleep休眠當前執行緒,不會釋放物件鎖,wait使當前執行緒進入等待狀態,釋放物件鎖,只有針對此物件呼叫notify()方法(且共享物件資源釋放)後本執行緒才會繼續執行

參考:https://www.cnblogs.com/hongten/p/hongten_java_sleep_wait.html

7)JVM的記憶體結構,JVM的演算法
JVM記憶體結構主要有三大塊:堆記憶體、方法區和棧,幾乎所有的物件例項都存放在堆裡,如果在堆中沒有記憶體完成例項分配,並且堆也無法再擴充套件時,將會丟擲OutOfMemoryError異常。
方法區用於儲存已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼等資料,當方法區無法滿足記憶體分配需求時,將丟擲OutOfMemoryError異常。
每個方法被執行的時候都會同時建立一個棧幀(Stack Frame)用於儲存區域性變量表、操作棧、動態連結、方法出口等資訊。
每一個方法被呼叫直至執行完成的過程,就對應著一個棧幀在虛擬機器棧中從入棧到出棧的過程。 
如果執行緒請求的棧深度大於虛擬機器所允許的深度,將丟擲StackOverflowError異常。


8)強引用,軟引用和弱引用的區別
強引用:
以前我們使用的大部分引用實際上都是強引用,這是使用最普遍的引用。如果一個物件具有強引用,那就類似於必不可少的生活用品,垃圾回收器絕不會回收它。
當記憶體空間不足,Java虛擬機器寧願丟擲OutOfMemoryError錯誤,使程式異常終止,也不會靠隨意回收具有強引用的物件來解決記憶體不足問題。 
軟引用:
如果一個物件只具有軟引用,那就類似於可有可物的生活用品。如果記憶體空間足夠,垃圾回收器就不會回收它,如果記憶體空間不足了,就會回收這些物件的記憶體
弱引用:
弱引用與軟引用的區別在於:只具有弱引用的物件擁有更短暫的生命週期。
在垃圾回收器執行緒掃描它所管轄的記憶體區域的過程中,一旦發現了只具有弱引用的物件,不管當前記憶體空間足夠與否,都會回收它的記憶體

總結:
強引用:String str = “abc”; list.add(str); 
軟引用:如果弱引用物件回收完之後,記憶體還是報警,繼續回收軟引用物件 
弱引用:如果虛引用物件回收完之後,記憶體還是報警,繼續回收弱引用物件 
虛引用:虛擬機器的記憶體不夠使用,開始報警,這時候垃圾回收機制開始執行System.gc(); String s = “abc”;如果沒有物件回收了, 就回收沒虛引用的物件


9)陣列在記憶體中如何分配
當一個物件使用關鍵字“new”建立時,會在堆上分配記憶體空間,然後返回物件的引用,這對陣列來說也是一樣的,因為陣列也是一個物件
簡單的值型別的陣列,每個陣列成員是一個引用(指標),引用到棧上的空間

10)用過哪些設計模式,手寫一個(除單例)
1.懶漢模式
public class SingletonDemo {
    private static SingletonDemo instance;
    private SingletonDemo(){}
    public static SingletonDemo getInstance(){
        if(instance==null){
            instance=new SingletonDemo();
        }
        return instance;
    }
}
2.餓漢模式
public class SingletonDemo {
    private static SingletonDemo instance=new SingletonDemo();
    private SingletonDemo(){}
    public static SingletonDemo getInstance(){
        return instance;
    }
}

3.簡單工廠模式

麵條工廠:
public abstract class INoodles {
    /**
     * 描述每種麵條啥樣的
     */
    public abstract void desc();
}
先來一份蘭州拉麵(具體的產品類):
public class LzNoodles extends INoodles {
    @Override
    public void desc() {
        System.out.println("蘭州拉麵 上海的好貴 家裡才5 6塊錢一碗");
    }
}
程式設計師加班必備也要吃泡麵(具體的產品類):
public class PaoNoodles extends INoodles {
    @Override
    public void desc() {
        System.out.println("泡麵好吃 可不要貪杯");
    }
}
準備工作做完了,我們來到一家“簡單面館”(簡單工廠類),選單如下:
public class SimpleNoodlesFactory {
    public static final int TYPE_LZ = 1;//蘭州拉麵
    public static final int TYPE_PM = 2;//泡麵
    public static INoodles createNoodles(int type) {
        switch (type) {
            case TYPE_LZ:
                return new LzNoodles();
            case TYPE_PM:
                return new PaoNoodles();
            default:
                return new PaoNoodles();
        }
    }
	/**
	 * 簡單工廠模式
	 */
	void creat(){
	    INoodles noodles = SimpleNoodlesFactory.createNoodles(SimpleNoodlesFactory.TYPE_PM);
            noodles.desc();
	}
} 
11)springmvc的核心是什麼,請求的流程是怎麼處理的,控制反轉怎麼實現的
aop和ioc
流程:使用者傳送請求給伺服器。url:user.do--->Dispatchservlet處理-->DispatchServlet通過HandleMapping呼叫這個url對應的Controller
Controller執行完畢後,如果返回字串,則ViewResolver將字串轉化成相應的檢視物件;如果返回ModelAndView物件,該物件本身就包含了檢視物件資訊。
DispatchServlet將執檢視物件中的資料,輸出給伺服器並呈現給客戶

IOC控制反轉:典型的工廠模式,就是具有依賴注入功能的容器,是可以建立物件的容器,IOC容器負責例項化、定位、配置應用程式中的物件及建立這些物件間的依賴。
通常new一個例項,控制權由程式設計師控制,而"控制反轉"是指new例項工作不由程式設計師來做而是交給Spring容器來做。。在Spring中BeanFactory是IOC容器的實際代表者

AOP依賴注入:典型的代理模式,面向切面程式設計將程式中的交叉業務邏輯(比如安全,日誌,事務),封裝成一個切面,然後注入到目標業務邏輯中去。
aop框架具有的兩個特徵: 1.各個步驟之間的良好隔離性 2.原始碼無關性 


12)mybatis如何處理結果集:反射,建議看看原始碼
通過在mapper配置檔案裡配置的屬性對照反射進物件裡

13)java的多型表現在哪裡
多型是同一個行為具有多個不同表現形式或形態的能力。
多型就是同一個介面,使用不同的例項而執行不同操作
比如同一個印表機,可以列印黑白的紙張也可以列印彩色的,同樣是人,卻有黑人白人之分

14)介面有什麼用
介面是一種規範,在這裡舉兩個例子
1.介面就比如KFC,你一聽KFC就知道是賣炸雞薯條的,他可以有不同的分店,也可以有自己的創新食品(多型),但是招牌炸雞、雞肉卷、全家桶什麼的肯定會有,
你不用進店看選單就知道他有,但如果不叫KFC換成炸雞店你也可以吃到炸雞,但是你不進店看選單你不知道他具體都賣的有哪些食品,這就是介面的好處
2.比如電插孔,多是兩孔和三孔的那種,如果沒有這種規範那每家電器公司都來做一種插孔的話,試想一下插頭換了怎麼辦?是不是隻能買原裝的來替換了


15)說說http,https協議
http是一種超文字協議,預設埠80,以明文傳輸。
https是http協議的安全版,安全基礎是SSL,以密文傳輸

16)osi五層網路協議
應用層、傳輸層、網路層、資料鏈路層、物理層

17)用過哪些加密演算法
對稱加密,非對稱加密演算法,Base64加密演算法,MD5加密演算法,SHA1加密演算法

18)說說tcp三次握手,四次揮手
1.客戶端向伺服器傳送一個syn包,進入傳送狀態
2.伺服器收到syn包,確認客戶的syn,並向客戶端傳送syn+ack包,進入接受狀態
3.客戶端接受的來自服務的的syn包資訊,向服務的發出ack包,次數兩者進入tcp連線成功狀態

19)cookie和session的區別,分散式環境怎麼儲存使用者狀態
cookie存在客戶端,session存在服務端
分散式Session的幾種實現方式
1.基於資料庫的Session共享
2.基於NFS共享檔案系統
3.基於memcached 的session,如何保證 memcached 本身的高可用性?
4.基於resin/tomcat web容器本身的session複製機制
5.基於TT/Redis 或 jbosscache 進行 session 共享。
6.基於cookie 進行session共享(唯一值token)


20)git,svn區別
Git是分散式的,而Svn不是分佈的
Git下載下來後,在OffLine狀態下可以看到所有的Log,SVN不可以
SVN的特點是簡單,只是需要一個放程式碼的地方時用是OK的,Git的特點版本控制可以不依賴網路做任何事情,對分支和合並有更好的支援

21)請寫一段棧溢位、堆溢位的程式碼
堆溢位,死迴圈存值,JVM就會丟擲OutOfMemoryError:java heap space異常
public static void main(String[] args) {
    List<byte[]> list = new ArrayList<>();
    int i=0;
    while(true){
        list.add(new byte[5*1024*1024]);
        System.out.println("分配次數:"+(++i));
    }
}
棧溢位,棧空間不足——StackOverflowError例項
public class StackSOFTest {
    int depth = 0;
    public void sofMethod(){
        depth ++ ;
        sofMethod();
    }
    public static void main(String[] args) {
        StackSOFTest test = null;
        try {
            test = new StackSOFTest();
            test.sofMethod();
        } finally {
            System.out.println("遞迴次數:"+test.depth);
        }
    }
}
22)ThreadLocal可以用來共享資料嗎
可以
ThreadLocal使用場合主要解決多執行緒中資料資料因併發產生不一致問題。ThreadLocal為每個執行緒的中併發訪問的資料提供一個副本,通過訪問副本來執行業務,這樣的結果是耗費了記憶體,單大大減少了執行緒同步所帶來效能消耗,也減少了執行緒併發控制的複雜度。
ThreadLocal和Synchonized都用於解決多執行緒併發訪問。但是ThreadLocal與synchronized有本質的區別。synchronized是利用鎖的機制,使變數或程式碼塊在某一時該只能被一個執行緒訪問。而ThreadLocal為每一個執行緒都提供了變數的副本,使得每個執行緒在某一時間訪問到的並不是同一個物件,這樣就隔離了多個執行緒對資料的資料共享。而Synchronized卻正好相反,它用於在多個執行緒間通訊時能夠獲得資料共享。
Synchronized用於執行緒間的資料共享,而ThreadLocal則用於執行緒間的資料隔離。


二.IO:

1)bio,nio,aio的區別;
2)nio框架:dubbo的實現原理;
3)京東內部的jsf是使用的什麼協議通訊:可參見dubbo的協議;

三.演算法:

1)java中常說的堆和棧,分別是什麼資料結構;另外,為什麼要分為堆和棧來儲存資料。
2)TreeMap如何插入資料:二叉樹的左旋,右旋,雙旋
3)一個排序之後的陣列,插入資料,可以使用什麼方法?答:二分法;問:時間複雜度是多少?
4)平衡二叉樹的時間複雜度
5)Hash演算法和二叉樹演算法分別什麼時候用
6)圖的廣度優先演算法和深度優先演算法:詳見jvm中垃圾回收實現

三.多執行緒相關

1)說說阻塞佇列的實現:可以參考ArrayBlockingQueue的底層實現(鎖和同步都行)
2)程序通訊的方式:訊息佇列,共享記憶體,訊號量,socket通訊等
3)用過併發包的哪些類
4)什麼地方用了多執行緒
5)Excutors可以產生哪些執行緒池
6)為什麼要用執行緒池

有效管理執行緒資源

7)volatile關鍵字的用法

使多執行緒中的變數可見,但是沒有原子性


四.資料庫相關(mysql)

1)msyql優化經驗
EXPLAIN 你的 SELECT 查詢
當只要一行資料時使用 LIMIT 1,原因:加上 LIMIT 1 可以增加效能。這樣一樣,MySQL資料庫引擎會在找到一條資料後停止搜尋,而不是繼續往後查少下一條符合記錄的資料。
為搜尋欄位建索引,什麼情況不適合用索引:當你需要在一篇大的文章中搜索一個詞時,如: “WHERE post_content LIKE ‘%apple%'”,索引可能是沒有意義的,因為建立索引也是需要佔用記憶體的
在Join表的時候對on條件裡相同型別、相同字符集的欄位使用索引
千萬不要 ORDER BY RAND(),比如需要返回隨機打亂順序的資料。因為MySQL執行RAND()函式會很耗CPU時間
最常見的:避免 SELECT *
永遠為每張表設定一個ID,最好是int型別的,因為使用 VARCHAR 型別來當主鍵會使用得效能下降
儘量使用 ENUM 而不是 VARCHAR,比如性別、狀態、民族等有限且固定的值
存值時候儘可能的使用 NOT NULL值
垂直拆分:“垂直分割”是一種把資料庫中的表按列變成幾張表的方法,這樣可以降低表的複雜度和欄位的數目,從而達到優化的目的。可以將一些冗餘的欄位或者不常用的欄位拆分出一個表

拆分大的 DELETE 或 INSERT 語句,因為這兩個操作是會鎖表的,比如刪除的量比較大可以加一個limit條件  判斷返回是否為0,為0代表已經沒有值了停止刪除

2)mysql的語句優化,使用什麼工具
Explain執行計劃

3)mysql的索引分類:B+,hash;什麼情況用什麼索引
Hash索引只能用於=或<=>的等式比較。而B+適合範圍查詢,如:id<30或者weight between 100 and 150
如何選擇索引列:
在where子句中出現的列,在join子句中出現的列,或者是在ORDER BY 或者GROUP BY子句中出現的資料列。
MySQL只對一下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些時候的like(不以萬用字元%或_開頭的情形)。

4)mysql的儲存引擎有哪些,區別是什麼
MyISAM  InnoDB  MEMORY  MERGE  TokuDB(說幾個常見的吧)
MyISAM:主要特點就是快,沒有事務處理操作,也不支援外來鍵操作
InnoDB:是新版本mysql的預設引擎,支援事務處理和外來鍵
MEMORY:資料訪問非常快的引擎,預設使用hash索引。一旦伺服器關閉表中的資料就會丟失

5)說說事務的特性和隔離級別
原子性:要麼發生要麼不發生
一致性:失誤前後資料必須保證完整性
隔離性:多使用者併發訪問事務互不干擾
永續性:事務一旦被提交對資料的改變是永久的,即便發生故障
如果不考慮隔離性,事務存在3中併發訪問問題。
1)髒讀:B事務讀取到了A事務尚未提交的資料   ------  要求B事務要讀取A事 務提交的資料
2)不可重複讀:一個事務中 兩次讀取的資料的內容不一致  ----- 要求的是一個事 務中多次讀取時資料是一致的  --- unpdate
3)幻讀/虛讀:一個事務中 兩次讀取的資料的數量不一致  ----- 要求在一個事務多 次讀取的資料的數量是一致的 --insert  delete


6)悲觀鎖和樂觀鎖的區別,怎麼實現
悲觀鎖:每次拿資料都以為別人會修改,所以每次拿資料時都會上鎖
樂觀鎖:每次拿資料時候都認為別人不會修改,所以不會上鎖,但是在更新資料時候會判斷在此期間是否有人更新過。
悲觀鎖實現:開啟事務,啟用鎖機制
樂觀鎖實現:1.使用版本號2.使用時間戳

五.mq

1)mq的原理是什麼:有點大。。都可以說
訊息佇列技術是分散式應用間交換資訊的一種技術,通過訊息佇列,應用程式可獨立地執行--它們不需要知道彼此的位置、或在繼續執行前不需要等待接收程式接收此訊息。
2)mq如何保證實時性
比如RocketMQ使用長輪詢Pull方式,可保證訊息非常實時
3)mq的持久化是怎麼做的
ActiveMQ提供了外掛式的訊息儲存,主要有有如下幾種:
  1.AMQ訊息儲存-基於檔案的儲存方式,是以前的預設訊息儲存
  2.KahaDB訊息儲存-提供了容量的提升和恢復能力,是現在的預設儲存方式
  3.JDBC訊息儲存-訊息基於JDBC儲存的
  4.Memory訊息儲存-基於記憶體的訊息儲存


六.nosql相關(主要是redis)

1)redis和memcache的區別
1、Redis和Memcache都是將資料存放在記憶體中,都是記憶體資料庫。不過memcache還可用於快取其他東西,例如圖片、視訊等等。
2、Redis不僅僅支援簡單的k/v型別的資料,同時還提供list,set,hash等資料結構的儲存。
3、虛擬記憶體--Redis當實體記憶體用完時,可以將一些很久沒用到的value 交換到磁碟
4、過期策略--memcache在set時就指定,例如set key1 0 0 8,即永不過期。Redis可以通過例如expire 設定,例如expire name 10
5、分散式--設定memcache叢集,利用magent做一主多從;redis可以做一主多從。都可以一主一從
6、儲存資料安全--memcache掛掉後,資料沒了;redis可以定期儲存到磁碟(持久化)
7、災難恢復--memcache掛掉後,資料不可恢復; redis資料丟失後可以通過aof恢復
8、Redis支援資料的備份,即master-slave模式的資料備份。


2)用redis做過什麼
1.做過熱點資料快取、
2.設定精準的搶購時間(通過key的過期失效策略)

3.輕鬆實現計數器(比如點贊)

3)redis是如何持久化的
rdb:原理是將Reids在記憶體中的資料庫記錄定時dump到磁碟上的RDB持久化
優點是對於災難恢復而言,rdb可以很輕鬆的將一個單獨的檔案轉移到其他儲存介質上
缺點是如果出現宕機,未來得及存入磁碟的資料將會丟失
aof;原理是將Reids的操作日誌以追加的方式寫入檔案
優點是能更大程度的保證記錄的完整性
缺點是對於相同數量的資料集而言,AOF檔案通常要大於RDB檔案。RDB 在恢復大資料集時的速度比 AOF 的恢復速度要快。
可參考:https://www.cnblogs.com/chenliangcl/p/7240350.html
4)redis叢集如何同步

主從複製、讀寫分離

5)redis的資料新增過程是怎樣的:雜湊槽
6)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(驅逐):禁止驅逐資料

7)redis有哪些資料結構
String字串、List列表、Set集合、Hash雜湊、Zset有序集合

七.zookeeper

1)zookeeper是什麼
分散式的、開源的分散式應用程式協調服務
2)zookeeper哪裡用到
結合我實際工作中使用Dubbo框架的情況,Zookeeper主要是做註冊中心用
3)zookeeper的選主過程
當leader崩潰或者leader失去大多數的follower,這時zk進入恢復模式,
4)zookeeper是如何保證事務的順序一致性的

zookeeper採用了遞增的事務Id來標識,所有的proposal都在被提出的時候加上了zxid,zxid實際上是一個64位的數字,高32位是epoch用來標識leader是否發生改變,如果有新的leader產生出來,epoch會自增,低32位用來遞增計數。當新產生proposal的時候,會依據資料庫的兩階段過程,首先會向其他的server發出事務執行請求,如果超過半數的機器都能執行並且能夠成功,那麼就會開始執行

5)分散式鎖的實現過程
在zookeeper指定節點(locks)下建立臨時順序節點node_n
獲取locks下所有子節點children
對子節點按節點自增序號從小到大排序
判斷本節點是不是第一個子節點,若是,則獲取鎖;若不是,則監聽比該節點小的那個節點的刪除事件
若監聽事件生效,則回到第二步重新進行判斷,直到獲取到鎖


八.linux相關

1)linux常用的命令有哪些

1、cd命令  
2、ls命令 
3、grep命令 
4、find命令 find / -name passwd # 查詢檔名為passwd的檔案 
5、cp命令 cp file1 file2 file3 dir #把檔案file1、file2、file3複製到目錄dir中
6、mv命令 移動或更名 mv file1 file2 # 把檔案file1重新命名為file2
7、rm命令 rm -fr dir # 強制刪除目錄dir中的所有檔案  
8、ps命令 ps aux # 檢視系統所有的程序資料  
9、kill命令 kill -9 PID
10、killall命令 killall java
11、tar命令 壓縮:tar -jcv -f filename.tar.bz2 要被處理的檔案或目錄名稱  解壓:tar -jxv -f filename.tar.bz2 -C 欲解壓縮的目錄
12、cat命令  cat text | less # 檢視text檔案中的內容
13、chmod命令 修改許可權 chmod 0755 file # 把file的檔案許可權改變為-rxwr-xr-x  
14、vim命令

2)如何獲取java程序的pid
grep -ef|grep java

3)如何獲取某個程序的網路埠號
netstat -antup //檢視已建立的連線程序,所佔用的埠。 

4)如何實時列印日誌
tail -f catalina.out

5)如何統計某個字串行數
find access_log.20160423.txt | xargs cat | grep .*關鍵字.*|wc -l
例子說明:統計含"關鍵字"字串的總行數

九.設計與思想

1)重構過程式碼沒有?說說經驗
比如一些常見的處理程式碼可以封裝成工具、list的為空判斷可以用CollectionUtils工具判斷、字串的為空判斷可以用StringUtils
2)一千萬的使用者實時排名如何實現
3)五萬人併發搶票怎麼實現;

補充:

垂直架構的session解決方案

1.Nginx的ip_hash。缺點是一臺tomcat宕機會導致這臺機器的session回話資料會丟失,不符合高可用
2.tomcat的session複製。缺點是每臺tomcat都需要保持全域性session資料,記憶體佔用嚴重
3.cookie based。缺點是不安全
4.session叢集儲存:Nginx負載+spring session+redis

分散式下如何保證ID全域性唯一
1.UUID。缺點是不同機器下的高併發場景下可能會重複
2.雪花生成器
3.自己寫redis生成:規則:key=字首+year+day的補位值+hour的補位值 id=redis.incr(key);