一、單選題(共10題,每題5分)
設計模式(面向對象)有七大原則,分別是: 1.開放-封閉原則 2.單一職責原則 3.依賴倒轉原則 4.迪米特法則(也稱為最小知識原則) 5.接口隔離原則 6.合成/聚合復用原則 7.里氏代換原則 詳情參考 :https://www.cnblogs.com/qingjiaowoxiaoxioashou/p/6273658.html
B-Tree是滿足條件: d>=2,即B-Tree的度; h為B-Tree的高; 每個非葉子結點由n-1個key和n個指針組成,其中d
A和B選項的區別在於第3步和第4步,B中當i=999時,先執行步驟3,則i=i+2=1001,接着第4步s=s+1001,如此看來這種3、4步的寫法求得的S會多加了一個i=1001.
1)編譯器負責把java文件編譯為class文件, 2)JAVA虛擬機(JVM)對class文件,進行加載、校驗、執行, 故本題的答案為C。
補圖:
無
略
選項B 應該是 釋放鎖就是刪除 key。
RedLock 算法
這個場景是假設有一個 redis cluster,有 5 個 redis master 實例。然后執行如下步驟獲取一把鎖:
獲取當前時間戳,單位是毫秒; 跟上面類似,輪流嘗試在每個 master 節點上創建鎖,過期時間較短,一般就幾十毫秒; 嘗試在大多數節點上建立一個鎖,比如 5 個節點就要求是 3 個節點 n / 2 + 1; 客戶端計算建立好鎖的時間,如果建立鎖的時間小於超時時間,就算建立成功了; 要是鎖建立失敗了,那么就依次之前建立過的鎖刪除; 只要別人建立了一把分布式鎖,你就得不斷輪詢去嘗試獲取鎖。
二、多選題(共10題,每題5分)
臟讀 : 臟讀就是指當一個事務正在訪問數據,並且對數據進行了修改,而這種修改還沒有提交到數據庫中,這時,另外一個事務也訪問這個數據,然后使用了這個數據。 不可重復讀 : 是指在一個事務內,多次讀同一數據。在這個事務還沒有結束時,另外一個事務再修改數據。那么第一個事務兩次讀到的的數據可能是不一樣的,因此稱為是不可重復讀。 幻讀: 當某事物正在執行插入或刪除操作同時,第二個事物也在操作此表的數據,就會顯示有一行還未存在的數據,就像發生了幻覺一樣。
解決辦法:如果在操作事務完成數據處理之前,任何其他事務都不可以操作此數據,則可避免該問題。
Java虛擬機管理的內存包括幾個運行時數據內存:方法區、虛擬機棧、本地方法棧、堆、程序計數器,其中方法區和堆是由線程共享的數據區,其他幾個是線程隔離的數據區
redis 內存淘汰機制有以下幾個:
noeviction: 當內存不足以容納新寫入數據時,新寫入操作會報錯,這個一般沒人用吧,實在是太惡心了。 allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的 key(這個是最常用的)。 allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個 key,這個一般沒人用吧,為啥要隨機,肯定是把最近最少使用的 key 給干掉啊。 volatile-lru:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,移除最近最少使用的 key(這個一般不太合適)。 volatile-random:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,隨機移除某個 key。 volatile-ttl:當內存不足以容納新寫入數據時,在設置了過期時間的鍵空間中,有更早過期時間的 key 優先移除。
Hystrix 的設計原則
- 對依賴服務調用時出現的調用延遲和調用失敗進行控制和容錯保護。
- 在復雜的分布式系統中,阻止某一個依賴服務的故障在整個系統中蔓延。比如某一個服務故障了,導致其它服務也跟着故障。
- 提供 fail-fast(快速失敗)和快速恢復的支持。
- 提供 fallback 優雅降級的支持。
- 支持近實時的監控、報警以及運維操作。
ActiveMQ 基於 Java 開發的, RabbitMQ 是基於 erlang 開發的。 所以選項A 錯誤。 B、C、D都正確。
特性 | ActiveMQ | RabbitMQ | RocketMQ | Kafka |
---|---|---|---|---|
單機吞吐量 | 萬級,比 RocketMQ、Kafka 低一個數量級 | 同 ActiveMQ | 10 萬級,支撐高吞吐 | 10 萬級,高吞吐,一般配合大數據類的系統來進行實時數據計算、日志采集等場景 |
topic 數量對吞吐量的影響 | topic 可以達到幾百/幾千的級別,吞吐量會有較小幅度的下降,這是 RocketMQ 的一大優勢,在同等機器下,可以支撐大量的 topic | topic 從幾十到幾百個時候,吞吐量會大幅度下降,在同等機器下,Kafka 盡量保證 topic 數量不要過多,如果要支撐大規模的 topic,需要增加更多的機器資源 | ||
時效性 | ms 級 | 微秒級,這是 RabbitMQ 的一大特點,延遲最低 | ms 級 | 延遲在 ms 級以內 |
可用性 | 高,基於主從架構實現高可用 | 同 ActiveMQ | 非常高,分布式架構 | 非常高,分布式,一個數據多個副本,少數機器宕機,不會丟失數據,不會導致不可用 |
消息可靠性 | 有較低的概率丟失數據 | 基本不丟 | 經過參數優化配置,可以做到 0 丟失 | 同 RocketMQ |
功能支持 | MQ 領域的功能極其完備 | 基於 erlang 開發,並發能力很強,性能極好,延時很低 | MQ 功能較為完善,還是分布式的,擴展性好 | 功能較為簡單,主要支持簡單的 MQ 功能,在大數據領域的實時計算以及日志采集被大規模使用 |
分布式服務接口,只靠數據庫的事務是保證不了冪等性的。 選項D錯誤。
所謂冪等性,就是說一個接口,多次發起同一個請求,你這個接口得保證結果是准確的,比如不能多扣款、不能多插入一條數據、不能將統計值多加了 1。這就是冪等性。
其實保證冪等性主要是三點:
- 對於每個請求必須有一個唯一的標識,舉個栗子:訂單支付請求,肯定得包含訂單 id,一個訂單 id 最多支付一次,對吧。
- 每次處理完請求之后,必須有一個記錄標識這個請求處理過了。常見的方案是在 mysql 中記錄個狀態啥的,比如支付之前記錄一條這個訂單的支付流水。
- 每次接收請求需要進行判斷,判斷之前是否處理過。比如說,如果有一個訂單已經支付了,就已經有了一條支付流水,那么如果重復發送這個請求,則此時先插入支付流水,orderId 已經存在了,唯一鍵約束生效,報錯插入不進去的。然后你就不用再扣款了。
- 實際運作過程中,你要結合自己的業務來,比如說利用 redis,用 orderId 作為唯一鍵。只有成功插入這個支付流水,才可以執行實際的支付扣款。
要求是支付一個訂單,必須插入一條支付流水,order_id 建一個唯一鍵 unique key。你在支付一個訂單之前,先插入一條支付流水,order_id 就已經進去了。你就可以寫一個標識到 redis 里面去,set order_id payed,下一次重復請求過來了,先查 redis 的 order_id 對應的 value,如果是 payed 就說明已經支付過了,你就別重復支付了。
緩存雪崩的事前事中事后的解決方案如下。
- 事前:進行系統壓力測試,在負載均衡層做限流處理,過載丟棄請求或者進入隊列
- 事前:redis 高可用,主從+哨兵,redis cluster,避免全盤崩潰。
- 事中:本地 ehcache 緩存 + hystrix 限流&降級,避免 MySQL 被打死。
- 事后:redis 持久化,一旦重啟,自動從磁盤上加載數據,快速恢復緩存數據。
Cache Aside Pattern 最經典的緩存+數據庫讀寫的模式,就是 Cache Aside Pattern。
讀的時候,先讀緩存,緩存沒有的話,就讀數據庫,然后取出數據后放入緩存,同時返回響應。 更新的時候,先更新數據庫,然后再刪除緩存。 為什么是刪除緩存,而不是更新緩存?
原因很簡單,很多時候,在復雜點的緩存場景,緩存不單單是數據庫中直接取出來的值。
比如可能更新了某個表的一個字段,然后其對應的緩存,是需要查詢另外兩個表的數據並進行運算,才能計算出緩存最新的值的。
另外更新緩存的代價有時候是很高的。是不是說,每次修改數據庫的時候,都一定要將其對應的緩存更新一份?也許有的場景是這樣,但是對於比較復雜的緩存數據計算的場景,就不是這樣了。如果你頻繁修改一個緩存涉及的多個表,緩存也頻繁更新。但是問題在於,這個緩存到底會不會被頻繁訪問到?
舉個栗子,一個緩存涉及的表的字段,在 1 分鍾內就修改了 20 次,或者是 100 次,那么緩存更新 20 次、100 次;但是這個緩存在 1 分鍾內只被讀取了 1 次,有大量的冷數據。實際上,如果你只是刪除緩存的話,那么在 1 分鍾內,這個緩存不過就重新計算一次而已,開銷大幅度降低。用到緩存才去算緩存。
其實刪除緩存,而不是更新緩存,就是一個 lazy 計算的思想,不要每次都重新做復雜的計算,不管它會不會用到,而是讓它到需要被使用的時候再重新計算。像 mybatis,hibernate,都有懶加載思想。查詢一個部門,部門帶了一個員工的 list,沒有必要說每次查詢部門,都里面的 1000 個員工的數據也同時查出來啊。80% 的情況,查這個部門,就只是要訪問這個部門的信息就可以了。先查部門,同時要訪問里面的員工,那么這個時候只有在你要訪問里面的員工的時候,才會去數據庫里面查詢 1000 個員工。
全對,IO和NIO的主要對比如下:
IO | NIO |
---|---|
面向流 | 面向緩沖 |
阻塞IO | 非阻塞IO |
無 | 選擇器 |