隨便分享點不那麼常規的面試題(二)

1. 觀察者模式和訪問者模式有什麼區別?

這兩種設計模式相對來講都偏冷門,本題可以回答好的話說明對設計模式有過深刻的瞭解,在面試偏業務的崗位上有加分mysql

先解釋二者概念:面試

  • 觀察者模式定義了一種一對多的依賴關係,當某一對象狀態改變時,會通知全部觀察者
  • 訪問者模式定義了一系列訪問接口,負責接收具體的數據對象,被訪問者經過這些接口將本身的數據交給訪問者來處理

再解釋二者核心區別和功能不一樣點:redis

  • 觀察者模式的核心是觸發器,主要用於廣播通知和動態觸發某些行爲
  • 訪問者模式的核心是解耦,主要用於將數據對象和數據分離,避免讓對象上的操做污染對象所在類

最後解釋二者優缺點和各自使用場景:算法

  • 觀察者模式的優勢是能夠實現動態觸發機制,可是若是存在循環依賴會致使系統崩潰,適用於廣播通知/發佈訂閱/鏈式觸發等場景
  • 訪問者模式的優勢是契合單一職責原則,同時擁有高度的靈活性,可是具體數據對訪問者公佈了細節,適用於須要使用數據對象進行不少不一樣操做的場景

2. 數據庫的頁分裂問題講一下

若是問頁分裂問題,通常會在聚簇索引以後緊接着提出,若是沒有問,在回答完聚簇索引相關的概念後,要儘可能地給面試官帶出頁分裂的概念,體現出本身對這一塊的熟悉程度sql

數據庫索引底層使用B+樹來實現,若是插入不規則的數據(指不按key順序插入),會致使樹結構頻繁發生較大改變數據庫

在數據庫中,聚簇索引和非聚簇索引在頻繁插入不規律數據時,都會致使嚴重的頁分裂問題。mysql中一頁大小爲8k,是固定的:設計模式

  • 聚簇索引中,由於索引順序與物理表順序一致,因此當插入包含不規律的索引列的數據時,會致使索引樹結構發生較大改變,數據頁也同時須要分裂,並且會破壞磁盤順序索引的高效性保證
  • 非聚簇索引中,由於索引是有序的,因此當插入不規律數據時,若是以前的數據頁已滿,會致使數據頁的分裂,同時也會破壞磁盤順序索引的高效性保證

3. 排序的穩定性意義是什麼,若是必定要使用非穩定性排序算法,如何保證穩定性?

本題主要用於考察面試者是否瞭解排序的概念,而不是僅僅背知識點。第一問不難,基本上知道穩定性的概念就能順勢推出其意義,第二問稍微有點難度,可是隻要真正瞭解穩定性的概念,就能想到一些解決辦法緩存

排序的穩定性指擁有相同關鍵字的記錄,在排序後的相對次序保持不變。由於有些數據在排序前的相對順序是有語義的,非穩定性排序會在排序後丟失這些語義,因此在這種場景下須要保證排序的穩定性bash

當必須使用非穩定性排序算法,且須要保證穩定性時,有兩種解決方案:服務器

  1. 剝奪原數據順序上的語義,好比可使用另外一個數據結構保存語義,或者從業務需求上解決
  2. 若是數據直接擁有在順序上的語義屬性時(好比插入時間/次序等),則重寫數據比較器,當關鍵詞相等時,比較數據的順序屬性

4. HashSet是如何實現的?

實現原理很簡單,但前提是你主動去了解過

HashSet內部維護了一個HashMap類型的變量,其key值爲Set的元素類型,value爲Object類型

對全部添加到Set中的元素,HashSet會添加一個元素 => PRESENT的鍵值對到HashMap中,這個PRESENT是HashSet中定義的一個普通的Object對象。由於HashMap中key相同的元素會相互覆蓋,因此保證了集合中沒有重複key值的元素存在

5. 事務的ACID特性各自是如何實現的?

ACID的概念很簡單,可是想說清原理不容易,其中隔離性和持久性是重點。隔離性的要點是鎖機制,有的面試官會緊接着出一些場景題,須要提早準備;持久性的要點是redo logbinlog,有的面試官會引伸到讀寫分離的數據一致性問題,也須要提早作好準備

A(原子性):原理是undo log,即「撤銷日誌」。當事務對數據庫進行修改時,會生成對應的undo log,若是事務回滾,數據庫會使用undo log中的內容將數據修改到以前的狀態

C(一致性):經過數據庫自己(如外鍵等)和服務端的代碼邏輯層面共同保證

I(隔離性):經過數據庫鎖機制和MVCC來實現。鎖機制保證兩個事務的寫操做不會相互影響,MVCC保證一個事務的讀操做不會被其餘事務的寫操做影響

D(持久性):原理是redo logbinlog,當數據修改時,會在redo log中記錄此次操做(記錄的是物理數據,內容基於磁盤page),一般當事務提交時,會調用fsync對redo log進行刷盤(將數據寫入磁盤),若是mysql機器宕機,可使用redo log對數據進行恢復。同時binlog做爲二進制邏輯日誌也能夠用戶數據恢復

6. strictfp關鍵詞有了解過嗎?

若是面試官問你這個問題,惟一的緣由就是他昨天臨睡前看到了這個知識點,因此就拿來考你(固然也有多是工做中確實用到)。本題單純的就是知識擴展,若是不會也不影響

stricpy,即strict float point(精確浮點),只能用來修飾方法或類。被strictpy修飾的方法或類中全部的float/double表達式都嚴格遵循FP-strict的限制,全部表達式的結果都必須是IEEE-754對操做數預期的結果

strictpy能夠消除因硬件不一樣而帶來的浮點數計算差別,可是並不能避免相似0.05 + 0.01 != 0.06這樣的狀況,因此在要求高精度浮點計算時,須要使用BigDecimal

7. 看下面這段代碼,和fun1相互阻塞的方法有哪幾個,爲何?

public synchronized static void fun1() {
        try {
            Thread.sleep(2000);
        } catch(Exception e) {
            e.printStackTrace();
        }
        System.out.println("[同步-靜態方法-1]");
    }

    // -------------------------------------------------

    public synchronized static void fun2() {
        System.out.println("[同步-靜態方法-2]");
    }

    public static void fun3() {
        System.out.println("[普通靜態方法]");
    }

    public void fun4() {
        System.out.println("[普通方法]");
    }

    public void fun5() {
        synchronized (Demo.class) {
            System.out.println("[類同步-靜態方法]");
        }
    }

    public void fun6() {
        synchronized (this) {
            System.out.println("[對象同步-方法]");
        }
    }
複製代碼

本題考察點是對synchronized關鍵字的掌握程度,有些人理論背的很熟,可是隨便丟個場景應用就懵了。因此在學一個知識點的時候,最起碼本身要動手寫幾行代碼跑一下看看

與fun1相互阻塞的方法是fun2和fun5

fun2是另外一個被synchronized修飾的方法,和fun1同屬一類,因此會相互阻塞

fun5中使用了類鎖,而synchronized在靜態方法上的鎖也屬於類鎖,因此也會相互阻塞

8. 多個客戶端要同時修改redis中的一個key怎麼辦?

通常這種併發修改的場景,均可以用消息中間件來將並行轉串行解決,可是面試官一般還想要另外一種答案,因此最少要準備兩套方案。本題固然不止我下面列出的這兩種方案,只要合理便可

  1. 全部的更新操做所有送入消息中間件中(如kafka/rabbitmq/...)串行化處理
  2. 經過redis的MUTLIWATCH實現:在redis中設置一個key,而後WATCH這個key,經過MUTLI開啓事務,而後自增這個key的值,接着再執行真正的修改操做,最後使用EXEC提交事務。經過這種方法,若是發生多線程競爭,因爲WATCH機制,監聽到key值變化的線程會執行redis操做失敗

9. 緩存雪崩、緩存擊穿、緩存穿透分別是什麼,怎麼解決?

本題應該算是偏常規的緩存題,可是有的面試官會把這三個場景放一塊兒說來故意迷惑你,因此要注意區分它們之間的不一樣點,千萬不要死記硬背,不然必定會搞混的

  • 緩存雪崩:指緩存服務器宕機或大量key同時過時,致使大量請求直接打到數據庫上,導致數據庫服務器宕機。
    • 若是是緩存服務器宕機:部署高可用集羣,啓用熔斷限流機制,以及在啓動前使用rdb日誌進行數據預熱
    • 若是是key批量過時:設置緩存時間時乘上一個隨機的負載因子
  • 緩存擊穿:某個頻繁訪問的key過時的瞬間,大量流量直接打到數據庫服務器上,致使宕機
    • 能夠將熱點key設置爲永不過時
    • 也可使用雙檢鎖,當在緩存中發現數據不存在時,先獲取鎖,而後再檢查緩存中是否存在數據,若是依然不存在則查詢數據庫
  • 緩存穿透:用戶惡意訪問數據庫不存在的數據,致使每次查詢都會走數據庫
    • 若是某次查詢沒有在數據庫中查到數據,則將該key放入緩存中,值設爲空,同時設置一個很短的過時時間
    • 限制同一ip短期的頻繁訪問

10. 爲何事務註解不加在Controller層或是Dao層?

本題主要考察對mvc分層的理解程度,只要能把每一層的概念理解了,說個大概仍是沒問題的,即便不知道,舉幾個反例出來就能夠了

  • 不加在controller層的緣由:controller的重點是請求邏輯,而不是數據庫事務。一般controller會調用多個服務,若是失敗只須要一個回滾便可
  • 不加在dao層的緣由:當服務發生異常時,須要總體進行回滾,而加在dao層只能回滾一個操做
相關文章
相關標籤/搜索