2020 面試題精選

1.java.util.concurrent.locks.Lock&ReentrantLock和synchronized的區別

答:Lock是Java 5以後引入的新的API,和關鍵字synchronized相比

    主要相同點:Lock 能完成synchronized所實現的所有功能;
    主要不同點:Lock有比synchronized更精確的線程語義和更好的性能,而且不強制性的要求一定要獲得鎖。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,並且最好在finally 塊中釋放(這是釋放外部資源的最好的地方)。
    synchronized是和if、else、for、while一樣的關鍵字&ReentrantLock是類   
    ReentrantLock可以對獲取鎖的等待時間進行設置,這樣就避免了死鎖
    ReentrantLock可以獲取各種鎖的信息
    ReentrantLock可以靈活地實現多路通知


ReentrantLock是Lock的默認實現,在聊ReentranLock之前,我們需要先弄清楚一些概念:

可重入鎖:可重入鎖是指同一個線程可以多次獲得同一把鎖;ReentrantLock和關鍵字Synchronized都是可重入鎖
可中斷鎖:可中斷鎖時只線程在獲取鎖的過程中,是否可以相應線程中斷操作。synchronized是不可中斷的,ReentrantLock是可中斷的
公平鎖和非公平鎖:公平鎖是指多個線程嘗試獲取同一把鎖的時候,獲取鎖的順序按照線程到達的先後順序獲取,而不是隨機插隊的方式獲取。synchronized是非公平鎖,而ReentrantLock是兩種都可以實現,不過默認是非公平鎖
Object中wait類似的方法Condition相同


2.數據庫事務的ACID是指什麼
原子性/一致性/隔離性/持久性
default 可重複讀 不可避免幻讀 --事務A讀取了符合條件的行,發現插入了事務B插入的數據

髒讀:A事務讀取B事務尚未提交的數據並在此基礎上操作,而B事務執行回滾,那麼A讀取到的數據就是髒數據。
不可重複讀:事務A重新讀取前面讀取過的數據,發現該數據已經被另一個已提交的事務B修改過了。
幻讀:事務A重新執行一個查詢,返回一系列符合查詢條件的行,發現其中插入了被事務B提交的行


3.獲得一個類的類對象有哪些方式

方法1:類型.class,例如:String.class
方法2:對象.getClass(),例如:"hello".getClass()
方法3:Class.forName(),例如:Class.forName("java.lang.String")

4.如何通過反射創建對象

方法1:通過類對象調用newInstance()方法,例如:String.class.newInstance()
方法2:通過類對象的getConstructor()或getDeclaredConstructor()方法獲得構造器(Constructor)對象並調用其newInstance()方法創建對象, 
  例如:String.class.getConstructor(String.class).newInstance("Hello");  

5.如何通過反射調用對象的方法

String str = "hello";
Method m = str.getClass().getMethod("toUpperCase");
System.out.println(m.invoke(str));

 

6.常用設計模式

共23種設計模式,包括:

Abstract Factory(抽象工廠模式),Builder(建造者模式),Factory Method(工廠方法模式),Prototype(原始模型模式),Singleton(單例模式);Facade(門面模式),Adapter(適配器模式),Bridge(橋樑模式),Composite(合成模式),Decorator(裝飾模式),Flyweight(享元模式),Proxy(代理模式);Command(命令模式),Interpreter(解釋器模式),Visitor(訪問者模式),Iterator(迭代子模式),Mediator(調停者模式),Memento(備忘錄模式),Observer(觀察者模式),State(狀態模式),Strategy(策略模式),Template Method(模板方法模式), Chain Of Responsibility(責任鏈模式)

7.用Java寫一個單例類

餓漢

private static Singleton instance = new Singleton();
public static Singleton getInstance(){
return instance;
}

懶漢

private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance(){
if (instance == null) instance = new Singleton();
return instance;
}

8.CyclicBarrier&CountDownLatch區別
CyclicBarrier的某個線程運行到某個點上之後,該線程即停止運行,直到所有的線程都到達了這個點,所有線程才重新運行
CyclicBarrier只能喚起一個任務,CountDownLatch可以喚起多個任務
CyclicBarrier可重用,CountDownLatch不可重用,計數值爲0該CountDownLatch就不可再用了
CountDownLatch則不是,某線程運行到某個點上之後,只是給某個數值-1而已,該線程繼續運行

CountDownLatch:
假如有這樣一個需求,當我們需要解析一個Excel裏多個sheet的數據時,可以考慮使用多線程,每個線程解析一個sheet裏的數據,等到所有的sheet都解析完之後,程序需要統計解析總耗時。分析一下:解析每個sheet耗時可能不一樣,總耗時就是最長耗時的那個操作。
CountDownLatch稱之爲閉鎖,它可以使一個或一批線程在閉鎖上等待,等到其他線程執行完相應操作後,閉鎖打開,這些等待的線程纔可以繼續執行。確切的說,閉鎖在內部維護了一個倒計數器。通過該計數器的值來決定閉鎖的狀態,從而決定是否允許等待的線程繼續執行。

創建CountDownLatch對象
調用其實例方法 await(),讓當前線程等待
調用 countDown()方法,讓計數器減1
當計數器變爲0的時候, await()方法會返回
Semaphore常用場景:限流
有5個空位,門口有個門衛,手中5把鑰匙分別對應5個車位上面的鎖,來一輛車,門衛會給司機一把鑰匙,然後進去找到對應的車位停下來,出去的時候司機將鑰匙歸還給門衛。停車場生意比較好,同時來了100兩車,門衛手中只有5把鑰匙,同時只能放5輛車進入,其他車只能等待,等有人將鑰匙歸還給門衛之後,才能讓其他車輛進入

 

9.volatile關鍵字的作用

多線程主要圍繞可見性和原子性兩個特性而展開,使用volatile關鍵字修飾的變量,保證了其在多線程之間的可見性,即每次讀取到volatile變量,一定是最新的數據

使用volatile則會對禁止語義重排序,當然這也一定程度上降低了代碼執行效率

volatile的一個重要作用就是和CAS結合,保證了原子性,詳細的可以參見java.util.concurrent.atomic包下的類,比如AtomicInteger。

 

10.什麼是線程安全如果你的代碼在多線程下執行和在單線程下執行永遠都能獲得一樣的結果,那麼你的代碼就是線程安全的。
不可變
像String、Integer、Long這些,都是final類型的類,任何一個線程都改變不了它們的值,要改變除非新創建一個,因此這些不可變對象不需要任何同步手段就可以直接在多線程環境下使用
絕對線程安全
不管運行時環境如何,調用者都不需要額外的同步措施。要做到這一點通常需要付出許多額外的代價,Java中標註自己是線程安全的類,實際上絕大多數都不是線程安全的,不過絕對線程安全的類,Java中也有,比方說CopyOnWriteArrayList、CopyOnWriteArraySet
相對線程安全
相對線程安全也就是我們通常意義上所說的線程安全,像Vector這種,add、remove方法都是原子操作,不會被打斷,但也僅限於此,如果有個線程在遍歷某個Vector、有個線程同時在add這個Vector,99%的情況下都會出現ConcurrentModificationException,也就是fail-fast機制。
線程非安全
這個就沒什麼好說的了,ArrayList、LinkedList、HashMap等都是線程非安全的類

 

11.如何在兩個線程之間共享數據
通過在線程之間共享對象就可以了,然後通過wait/notify/notifyAll、await/signal/signalAll進行喚起和等待,比方說阻塞隊列BlockingQueue(有界阻塞隊列&無界阻塞隊列)就是爲線程之間共享數據而設計的

 

12.Linux環境下如何查找哪個線程使用CPU最長
(1)獲取項目的pid,jps或者ps -ef | grep java,這個前面有講過
(2)top -H -p pid,順序不能改變

 

13.面向服務分佈式架構SOA:
拆分架構 :
1.分擔服務器壓力。
2.提高項目併發能力。
拆分原則 :
1.根據業務和職能拆分。
爲了減輕數據庫壓力,提高數據庫效率?
解決方案 :
1.集羣(主主,主備,讀寫分離)
2.分表,分庫。
3.開啓緩存。
4.開啓索引.
5.sql語句優化。
6.數據庫設計優化。


數據庫本身優化,還可以加redis緩存?
1.減輕數據庫壓力(查詢緩存,不再查詢數據庫)。
2.提高查詢效率(redis是內存版nosql數據庫)
3.提高併發能力。
dubbo :服務治理中間件(分佈式服務架構)
特點 :
1.rpc 遠程通信
2.NIO new IO 異步通信。
dubbo優化 :
1.服務集羣。
2.序列化優化 kryo
3.失敗重試。

 

第一級優化 :
1.集羣(主主,主備,讀寫分離)

作用 :高可用和高併發。
2.分表和分庫(大數據查詢效率低)
3.開啓緩存
4.開啓索引
5.優化sql查詢
5.數據庫設計

 

第二級優化 :redis緩存
作用 :
1.減輕數據庫壓力
2.提高項目查詢效率
(redis是一個nosql版內存版數據庫)
redis服務器本身優化:
1.內存淘汰策略。
2.線程安全問題。
3.redis3.0 :自動高可用,自動容錯。

 

第三極優化 :solr進行搜索
作用 :
1.減輕數據庫壓力。
2.提高檢索效率(搜索索引)
案例 :
solr服務器本身優化:
1.集羣(高可用,高容錯)

 

第四級優化 :SOA面向服務分佈式的架構
作用 :
1.分擔服務器壓力。
2.提高項目併發能力。jvm優化。
優化 :soa使用dubbo+zookeeper tomcat服務器優化
dubbo優化 :
1.服務集羣。
2.序列化優化 kryo
3.失敗重試。


第五級優化 :fastDFS分佈式文件系統
作用 :存儲圖片
1.訪問效率高。
2.自動容錯。
3.線性擴容。


第六級優化 :

使用mq消息服務器,應用於服務與服務之間進行通信。
作用 :1.異步通信。2.任務異步處理。優勢:流量削峯。
優化mq :集羣。


第七級優化 :頁面靜態化
1.查詢效率提高(訪問靜態數據)
2.併發能力提高。
技術 :freemarket實現靜態化。
思考 : 優化。
缺點 :
html頁面商品數據。
商品描述,規格,詳情。
不能及時和數據庫同步。
優化 :
mq進行同步靜態頁面。
同步流程:
商品添加,修改,刪除。
發送消息
詳情繫統接收消息動態生成,刪除html頁面。


第8級優化 :nginx的使用
1.http服務器。
2.負載均衡。
優化:
集羣。
頁面靜態化 :
技術選型 ;freemarket
優勢 :簡單,容易上手,語法簡單,功能更強大。

 

14.TCP如何保證可靠傳輸?三次握手過程?

在TCP的連接中,數據流必須以正確的順序送達對方。TCP的可靠性是通過順序編號和確認(ACK)來實現的。TCP 連接是通過三次握手進行初始化的。三次握手的目的是同步連接雙方的序列號和確認號並交換 TCP 窗口大小信息。第一次是客戶端發起連接;第二次表示服務器收到了客戶端的請求;第三次表示客戶端收到了服務器的反饋。

 

15.常用的hash算法有哪些?
(1)加法hash:所謂的加法Hash就是把輸入元素一個一個的加起來構成最後的結果。
(2)位運算hash:這類型Hash函數通過利用各種位運算(常見的是移位和異或)來充分的混合輸入元素
(3)乘法hash:33*hash + key.charAt(i)

 

16.什麼是一致性哈希?
設計目標是爲了解決因特網中的熱點(Hot spot)問題,一致性hash算法提出了在動態變化的Cache環境中,判定哈希算法好壞的四個定義:平衡性(Balance) ;單調性(Monotonicity) ;分散性(Spread) ;負載(Load)


17.數據庫中的範式有哪些?
第一範式----數據庫中的表(所有字段值)都是不可分割的原子數據項。
第二範式----數據庫表中的每一列都和主鍵相關,而不能只和主鍵的某一部分相關。
第三範式----數據庫表中每一列數據都和主鍵直接相關,不能間接相關。範式是爲了減小數據冗餘。

 

18.數據庫中的索引的結構?什麼情況下適合建索引?
數據庫中索引的結構是一種排序的數據結構,數據庫索引是通過B樹和變形的B+樹實現的。什麼情況下不適合建立索引:1.對於在查詢過程中很少使用或參考的列;對於那些只有很少數據值的列;對於那些定義爲image,text和bit數據類型的列;當修改性能遠大於檢索性能。
根據系統自身的環境情況,有效的限制執行線程的數量,使得運行效果達到最佳。線程主要是通過控制執行的線程的數量,超出數量的線程排隊等候,等待有任務執行完畢,再從隊列最前面取出任務執行

 

19.TCP 協議與 UDP 協議有什麼區別?
TCP(Tranfer Control Protocol)的縮寫,是一種面向連接的保證傳輸的協議,在傳輸數據流前,雙方會先建立一條虛擬的通信道。可以很少差錯傳輸數據。
UDP(User DataGram Protocol)的縮寫,是一種無連接的協議,使用UDP傳輸數據時,每個數據段都是一個獨立的信息,包括完整的源地址和目的地,在網絡上以任何可能的 路徑傳到目的地,因此,能否到達目的地,以及到達目的地的時間和內容的完整性都不能保證。
所以TCP比UDP多了建立連接的時間。相對UDP而言,TCP具有更高的安全性和可靠性。
TCP協議傳輸的大小不限制,一旦連接被建立,雙方可以按照一定的格式傳輸大量的數據,而UDP是一個不可靠的協議,大小有限制,每次不能超過64K。

 

20.tomcat 如何調優,涉及哪些參數。
硬件上選擇,操作系統選擇,版本選擇,jdk選擇,配置jvm參數,配置connector的線程數量,開啓gzip壓縮,trimSpaces,集羣等
a) 內存優化:主要是對Tomcat啓動參數進行優化,我們可以在Tomcat啓動腳本中修改它的最大內存數等等。
b) 線程數優化:Tomcat的併發連接參數,主要在Tomcat配置文件中server.xml中配置,比如修改最小空閒連接線程數,用於提高系統處理性能等等。
c) 優化緩存:打開壓縮功能,修改參數,比如壓縮的輸出內容大小默認爲2KB,可以適當的修改

 

21.說說你對 Spring 的理解,非單例注入的原理?它的生命週期?循環注入的原理, aop 的實現原理,說說 aop 中的幾個術語,它們是怎麼相互工作的。
AOP與IOC的概念(即spring的核心)
a) IOC:Spring是開源框架,使用框架可以使我們減少工作量,提高工作效率並且它是分層結構,即相對應的層處理對應的業務邏輯,減少代碼的耦合度。而spring的核心是IOC控制反轉和AOP面向切面編程。IOC控制反轉主要強調的是程序之間的關係是由容器控制的,容器控制對象,控制了對外部資源的獲取。而反轉即爲,在傳統的編程中都是由我們創建對象獲取依賴對象,而在IOC中是容器幫我們創建對象並注入依賴對象,正是容器幫我們查找和注入對象,對象是被獲取,所以叫反轉。
b) AOP:面向切面編程,主要是管理系統層的業務,比如日誌,權限,事物等。AOP是將封裝好的對象剖開,找出其中對多個對象產生影響的公共行爲,並將其封裝爲一個可重用的模塊,這個模塊被命名爲切面(aspect),切面將那些與業務邏輯無關,卻被業務模塊共同調用的邏輯提取並封裝起來,減少了系統中的重複代碼,降低了模塊間的耦合度,同時提高了系統的可維護性。
核心組件:bean,context,core,單例注入是通過單例beanFactory進行創建,生命週期是在創建的時候通過接口實現開啓,循環注入是通過後置處理器,aop其實就是通過反射進行動態代理,pointcut,advice等。

 

22.Springmvc 中 DispatcherServlet 初始化過程。
入口是web.xml中配置的ds,ds繼承了HttpServletBean,FrameworkServlet,通過其中的init方法進行初始化裝載bean和實例,initServletBean是實際完成上下文工作和bean初始化的方法。

 

23.springMVC的執行流程
springMVC是由dispatchservlet爲核心的分層控制框架。首先客戶端發出一個請求web服務器解析請求url並去匹配dispatchservlet的映射url,如果匹配上就將這個請求放入到dispatchservlet,dispatchservlet根據mapping映射配置去尋找相對應的handel,然後把處理權交給找到的handel,handel封裝了處理業務邏輯的代碼,當handel處理完後會返回一個邏輯視圖modelandview給dispatchservlet,此時的modelandview是一個邏輯視圖不是一個正式視圖,所以dispatchservlet會通過viewresource視圖資源去解析modelandview,然後將解析後的參數放到view中返回到客戶端並展現。

 

24.事物的理解
a) 事物具有原子性,一致性,持久性,隔離性
b) 原子性:是指在一個事物中,要麼全部執行成功,要麼全部失敗回滾。
c) 一致性:事物執行之前和執行之後都處於一致性狀態
d) 持久性:事物多數據的操作是永久性
e) 隔離性:當一個事物正在對數據進行操作時,另一個事物不可以對數據進行操作,也就是多個併發事物之間相互隔離。


25.spring 的 controller 是單例還是多例,怎麼保證併發的安全。
單例
通過單例工廠 DefaultSingletonBeanRegistry實現單例
通過AsyncTaskExecutor保持安全

 

26.redis 的持久化的機制,aof 和 rdb 的區別。

RDB 定時快照方式(snapshot):定時備份,可能會丟失數據

AOF 基於語句追加方式 只追加寫操作

AOF 持久化和 RDB 持久化的最主要區別在於,前者記錄了數據的變更,而後者是保存了數據本身

 

27.elasticsearch 瞭解多少,說說你們公司 es 的集羣架構,索引數據大小,分片有多少,以及一些調優手段。elasticsearch 的倒排索引是什麼。

ElasticSearch(簡稱ES)是一個分佈式、Restful的搜索及分析服務器,設計用於分佈式計算;能夠達到實時搜索,穩定,可靠,快速。和Apache Solr一樣,它也是基於Lucence的索引服務器,而ElasticSearch對比Solr的優點在於:

1.輕量級:安裝啓動方便,下載文件之後一條命令就可以啓動。
2.Schema free:可以向服務器提交任意結構的JSON對象,Solr中使用schema.xml指定了索引結構。
3.多索引文件支持:使用不同的index參數就能創建另一個索引文件,Solr中需要另行配置。
4.分佈式:Solr Cloud的配置比較複雜。

倒排索引是實現“單詞-文檔矩陣”的一種具體存儲形式,通過倒排索引,可以根據單詞快速獲取包含這個單詞的文檔列表。倒排索引主要由兩個部分組成:“單詞詞典”和“倒排文件”。

##elasticsearch 索引數據多了怎麼辦,如何調優,部署。

使用bulk API

初次索引的時候,把 replica 設置爲 0

增大 threadpool.index.queue_size

增大 indices.memory.index_buffer_size

增大 index.translog.flush_threshold_ops

增大 index.translog.sync_interval

增大 index.engine.robin.refresh_interval

 

28.有 3n+1 個數字,其中 3n 箇中是重複的,只有 1 個是不重複的,怎麼找出來。

##常用的排序算法,快排,歸併、冒泡。快排的最優時間複雜度,最差複雜度。冒泡排序的優化方案。

##二分查找的時間複雜度,優勢。

##一個已經構建好的 TreeSet,怎麼完成倒排序。

//冒泡
  public static void mp(int a[]) {
    int swap = 0;
    for (int i = 0; i < a.length; i++) {
       for (int j = i; j < a.length; j++) {
            if (a[j] > a[i]) {
                swap = a[i];
                a[i] = a[j];
                a[j] = swap;
             }
          }
       }
     System.out.println(Arrays.toString(a));
   }

 

/**
     * 不使用遞歸的二分查找
     *title:commonBinarySearch
     *@param arr
     *@param key
     *@return 關鍵字位置
     */
    public static int commonBinarySearch(int[] arr,int key){
        int low = 0;
        int high = arr.length - 1;
        int middle = 0;//定義middle
    }

 

 /**
   * 使用遞歸的二分查找
   *title:recursionBinarySearch
   *@param arr 有序數組
   *@param key 待查找關鍵字
   *@return 找到的位置
   */
  public static int recursionBinarySearch(int[] arr,int key,int low,int high){

    if(key < arr[low] || key > arr[high] || low > high){
      return -1;        
    }
    int middle = (low + high) / 2;//初始中間位置
    if(arr[middle] > key){
      //比關鍵字大則關鍵字在左區域
      return recursionBinarySearch(arr, key, low, middle - 1);
    }else if(arr[middle] < key){
      //比關鍵字小則關鍵字在右區域
      return recursionBinarySearch(arr, key, middle + 1, high);
    }else {
      return middle;
    }  
  }

29.數據庫隔離級別有哪些,各自的含義是什麼,MYSQL 默認的隔離級別是是什麼。
 

1.未提交讀(Read Uncommitted):允許髒讀,也就是可能讀取到其他會話中未提交事務修改的數據
2.提交讀(Read Committed):只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 (不重複讀)
3.可重複讀(Repeated Read):可重複讀。在同一個事務內的查詢都是事務開始時刻一致的,InnoDB默認級別。在SQL標準中,該隔離級別消除了不可重複讀,但是還存在幻象讀
4.串行讀(Serializable):完全串行化的讀,每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞

MYSQL默認是RepeatedRead級別

30.SQL 優化的一般步驟是什麼,怎麼看執行計劃,如何理解其中各個字段的含義。

查看慢日誌(show [session|gobal] status ),定位慢查詢,查看慢查詢執行計劃 根據執行計劃確認優化方案

Explain sql

select_type:表示select類型。常見的取值有SIMPLE(簡單表,即不使用連接或者子查詢)、PRIMARY(主查詢,即外層的查詢)、UNION(union中的第二個或者後面的查詢語句)、SUBQUERY(子查詢中的第一個SELECT)等。

talbe:輸出結果集的表。

type:表的連接類型。性能由高到底:system(表中僅有一行)、const(表中最多有一個匹配行)、eq_ref、ref、ref_null、index_merge、unique_subquery、index_subquery、range、idnex等

possible_keys:查詢時,可能使用的索引

key:實際使用的索引

key_len:索引字段的長度

rows:掃描行的數量

Extra:執行情況的說明和描述

Oracle優化​​​​​​​

1.對查詢進行優化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
2.應儘量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設置默認值0,確保表中num列沒有null值,然後這樣查詢:
select id from t where num=0
3.應儘量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
4.應儘量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎用,否則會導致全表掃描,如:
select id from t where num in(1,2,3)
對於連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查詢也將導致全表掃描:
select id from t where name like ‘%abc%’
若要提高效率,可以考慮全文檢索。
7.如果在 where 子句中使用參數,也會導致全表掃描。因爲SQL只有在運行時纔會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作爲索引選擇的輸入項。如下面語句將進行全表掃描:
select id from t where num=@num
可以改爲強制查詢使用索引:
select id from t with(index(索引名)) where num=@num
8.應儘量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2=100
應改爲:
select id from t where num=100*2
9.應儘量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)=‘abc’ // oracle總有的是substr函數。
select id from t where datediff(day,createdate,‘2005-11-30’)=0 //查過了確實沒有datediff函數。
應改爲:
select id from t where name like ‘abc%’
select id from t where createdate>=‘2005-11-30’ and createdate<‘2005-12-1’ //
oracle 中時間應該把char 轉換成 date 如:createdate >= to_date(‘2005-11-30’,‘yyyy-mm-dd’)
10.不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
11.在使用索引字段作爲條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個字段作爲條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓字段順序與索引順序相一致。
12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:
select col1,col2 into #t from t where 1=0
這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
create table #t(…)
13.很多時候用 exists 代替 in 是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)
14.並不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重複時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那麼即使在sex上建了索引也對查詢效率起不了作用。
15.索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因爲 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。
16.應儘可能的避免更新 clustered 索引數據列,因爲 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列,那麼需要考慮是否應將該索引建爲 clustered 索引。
17.儘量使用數字型字段,若只含數值信息的字段儘量不要設計爲字符型,這會降低查詢和連接的性能,並會增加存儲開銷。這是因爲引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對於數字型而言只需要比較一次就夠了。
18.儘可能的使用 varchar/nvarchar 代替 char/nchar ,因爲首先變長字段存儲空間小,可以節省存儲空間,其次對於查詢來說,在一個相對較小的字段內搜索效率顯然要高些。
19.任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。
20.儘量使用表變量來代替臨時表。如果表變量包含大量數據,請注意索引非常有限(只有主鍵索引)。
21.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。
22.臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重複引用大型表或常用表中的某個數據集時。但是,對於一次性事件,最好使用導出表。
23.在新建臨時表時,如果一次性插入數據量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,爲了緩和系統表的資源,應先create table,然後insert。
24.如果使用到了臨時表,在存儲過程的最後務必將所有的臨時表顯式刪除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。
25.儘量避免使用遊標,因爲遊標的效率較差,如果遊標操作的數據超過1萬行,那麼就應該考慮改寫。
26.使用基於遊標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。
27.與臨時表一樣,遊標並不是不可使用。對小型數據集使用 FAST_FORWARD 遊標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括“合計”的例程通常要比使用遊標執行的速度快。如果開發時間允許,基於遊標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。
28.在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句後向客戶端發送 DONE_IN_PROC 消息。
29.儘量避免大事務操作,提高系統併發能力。
30.儘量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。

31.數據庫會死鎖嗎,舉一個死鎖的例子,mysql 怎麼解決死鎖。

產生死鎖的原因主要是:

(1)系統資源不足。

(2) 進程運行推進的順序不合適。

(3)資源分配不當等。

如果系統資源充足,進程的資源請求都能夠得到滿足,死鎖出現的可能性就很低,否則就會因爭奪有限的資源而陷入死鎖。其次,進程運行推進順序與速度不同,也可能產生死鎖。

產生死鎖的四個必要條件:

(1) 互斥條件:一個資源每次只能被一個進程使用。

(2) 請求與保持條件:一個進程因請求資源而阻塞時,對已獲得的資源保持不放。

(3) 不剝奪條件:進程已獲得的資源,在末使用完之前,不能強行剝奪。

(4) 循環等待條件:若干進程之間形成一種頭尾相接的循環等待資源關係。

這四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要上述條件之一不滿足,就不會發生死鎖。

這裏提供兩個解決數據庫死鎖的方法:

1)重啓數據庫(誰用誰知道)

2)殺掉搶資源的進程:

先查哪些進程在搶資源:SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

殺掉它們:Kill trx_mysql_thread_id;

 

32.mysql的索引原理,索引的類型有哪些,如何創建合理的索引,索引如何優化。

索引是通過複雜的算法,提高數據查詢性能的手段。從磁盤io到內存io的轉變

普通索引,主鍵,唯一,單列/多列索引建索引的幾大原則

1.最左前綴匹配原則,非常重要的原則,mysql會一直向右匹配直到遇到範圍查詢(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 4 如果建立(a,b,c,d)順序的索引,d是用不到索引的,如果建立(a,b,d,c)的索引則都可以用到,a,b,d的順序可以任意調整。

2.=和in可以亂序,比如a = 1 and b = 2 and c = 3 建立(a,b,c)索引可以任意順序,mysql的查詢優化器會幫你優化成索引可以識別的形式

3.儘量選擇區分度高的列作爲索引,區分度的公式是count(distinct col)/count(*),表示字段不重複的比例,比例越大我們掃描的記錄數越少,唯一鍵的區分度是1,而一些狀態、性別字段可能在大數據面前區分度就是0,那可能有人會問,這個比例有什麼經驗值嗎?使用場景不同,這個值也很難確定,一般需要join的字段我們都要求是0.1以上,即平均1條掃描10條記錄

4.索引列不能參與計算,保持列“乾淨”,比如from_unixtime(create_time) = ’2014-05-29’就不能使用到索引,原因很簡單,b+樹中存的都是數據表中的字段值,但進行檢索時,需要把所有元素都應用函數才能比較,顯然成本太大。所以語句應該寫成create_time = unix_timestamp(’2014-05-29’);

5.儘量的擴展索引,不要新建索引。比如表中已經有a的索引,現在要加(a,b)的索引,那麼只需要修改原來的索引即可

##聚集索引和非聚集索引的區別。

“聚簇”就是索引和記錄緊密在一起。

非聚簇索引 索引文件和數據文件分開存放,索引文件的葉子頁只保存了主鍵值,要定位記錄還要去查找相應的數據塊。

 

33.MQ 系統的數據如何保證不丟失。

基本都是對數據進行持久化,多盤存儲

 

34.rabbitmq 如何實現集羣高可用。

集羣是保證服務可靠性的一種方式,同時可以通過水平擴展以提升消息吞吐能力。RabbitMQ是用分佈式程序設計語言erlang開發的,所以天生就支持集羣。接下來,將介紹RabbitMQ分佈式消息處理方式、集羣模式、節點類型,並動手搭建一個高可用集羣環境,最後通過java程序來驗證集羣的高可用性。

三種分佈式消息處理方式

RabbitMQ分佈式的消息處理方式有以下三種:

1、Clustering:不支持跨網段,各節點需運行同版本的Erlang和RabbitMQ, 應用於同網段局域網。

2、Federation:允許單臺服務器上的Exchange或Queue接收發布到另一臺服務器上Exchange或Queue的消息, 應用於廣域網,。

3、Shovel:與Federation類似,但工作在更低層次。

RabbitMQ對網絡延遲很敏感,在LAN環境建議使用clustering方式;在WAN環境中,則使用Federation或Shovel。我們平時說的RabbitMQ集羣,說的就是clustering方式,它是RabbitMQ內嵌的一種消息處理方式,而Federation或Shovel則是以plugin形式存在。

 

35.Redis的數據結構都有哪些。

字符串(strings):存儲整數(比如計數器)和字符串(廢話。。),有些公司也用來存儲json/pb等序列化數據,並不推薦,浪費內存;

哈希表(hashes):存儲配置,對象(比如用戶、商品),優點是可以存取部分key,對於經常變化的或者部分key要求atom操作的適合;

列表(lists):可以用來存最新用戶動態,時間軸,優點是有序,確定是元素可重複,不去重集合(sets):無序,唯一,對於要求嚴格唯一性的可以使用;

有序集合(sorted sets):集合的有序版,很好用,對於排名之類的複雜場景可以考慮。

 

##Redis 的使用要注意什麼,講講持久化方式,內存設置,集羣的應用和優劣勢,淘汰策略等。

持久化方式:RDB時間點快照 AOF記錄服務器執行的所有寫操作命令,並在服務器啓動時,通過重新執行這些命令來還原數據集。

內存設置 maxmemory used_memory

虛擬內存:vm-enabled yes

3.0採用Cluster方式,Redis集羣相對單機在功能上存在一些限制,需要開發人員提前瞭解,在使用時做好規避。限制如下:

1) key批量操作支持有限。如mset、mget,目前只支持具有相同slot值的key執行批量操作。對於映射爲不同slot值的key由於執行mget、 mget等操作可能存在於多個節點上因此不被支持。

2) key事務操作支持有限。同理只支持多key在同一節點上的事務操作, 當多個key分佈在不同的節點上時無法使用事務功能。

3) key作爲數據分區的最小粒度, 因此不能將一個大的鍵值對象如hash、 list等映射到不同的節點。

4) 不支持多數據庫空間。單機下的Redis可以支持16個數據庫, 集羣模式下只能使用一個數據庫空間, 即db0。

5) 複製結構只支持一層,從節點只能複製主節點,不支持嵌套樹狀複製結構。Redis Cluster是Redis的分佈式解決方案,在3.0版本正式推出,有效地解決了Redis分佈式方面的需求。當遇到單機內存、併發、流量等瓶頸時,可以採用Cluster架構方案達到負載均衡的目的。之前, Redis分佈式方案一般有兩種:①客戶端分區方案,優點是分區邏輯可控,缺點是需要自己處理數據路由、高可用、故障轉移等問題。②代理方案,優點是簡化客戶端分佈式邏輯和升級維護便利,缺點是加重架構部署複雜度和性能損耗。

現在官方爲我們提供了專有的集羣方案:Redis Cluster, 它非常優雅地解決了Redis集羣方面的問題, 因此理解應用好Redis Cluster將極大地解放我們使用分佈式Redis的工作量, 同時它也是學習分佈式存儲的絕佳案例。LRU(近期最少使用算法)TTL(超時算法) 去除ttl最大的鍵值

 

最後

答題時,先答是什麼,再答有什麼作用和要注意什麼(這部分最重要,展現自己的心得)
答案的段落分別,層次分明,條理清晰都非常重要,從這些表面的東西也可以看出一個人的習慣、辦事風格、條理等。

要講你做出答案的思路過程,或者說你記住答案的思想都寫下來。把答題想着是辯論賽。答題就是給別人講道理、擺事實。答題不侷限於什麼格式和形式,就是要將自己的學識展現出來!

別因爲人家題目本來就模棱兩可,你就心裏膽怯和沒底氣了,不敢回答了。你要大膽地指出對方題目很模糊和你的觀點,不要把面試官想得有多高,其實他和你就是差不多的,你想想,如果他把你招進去了,你們以後就是同事了,可不是差不多的嗎?

關於就業薪水,如果你是應屆生,那不能要高工資,好比大餅的故事,沒有文憑還想拿高工資,就去中關村缺什麼補什麼吧!少數人基礎確實很好,在校期間確實又做過一些項目,那仍然是可以要到相對高的工資的。

 

最後由於篇幅原因,在這就不做全部展示了,我整理大量的面試資料及學習視頻,有需要的朋友可以加我微信:211566433 免費獲取

 

想看新鮮、有料的最新招聘資訊?

鎖定【工作LIFE】

第一時間發佈相關信息

抓住機會獲取更多資訊

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章