秋招相關面試總結(三)

HashMap爲什麼線程不安全concurrentHashMap

1 在put數據的時候可能照成插入的數據被掩蓋。

2.在插入時,可能會照成resize,此時可能會造成環形鏈表 ,在get時會造成死循環

HashMap在put的時候,插入的元素超過了容量(由負載因子決定)的範圍就會觸發擴容操作,就是rehash,這個會重新將原數組的內容重新hash到新的擴容數組中,在多線程的環境下,存在同時其他的元素也在進行put操作,如果hash值相同,可能出現同時在同一數組下用鏈表表示,造成閉環,導致在get時會出現死循環,所以HashMap是線程不安全的。

concurrentHashMap底層使用的是CAS樂觀鎖技術

Kafka與現有MQ的比較

可擴展。Kafka集羣可以透明的擴展,增加新的服務器進集羣。

高性能。Kafka性能遠超過傳統的ActiveMQ、RabbitMQ等,Kafka支持Batch操作。

容錯性。Kafka每個Partition數據會複製到幾臺服務器,當某個Broker失效時,Zookeeper將通知生產者和消費者從而使用其他的Broker。

缺點:

 

重複消息。Kafka保證每條消息至少送達一次,雖然機率很小,但一條消息可能被送達多次。

消息亂序。Kafka某一個固定的Partition內部的消息是保證有序的,如果一個Topic有多個Partition,partition之間的消息送達不保證有序。

複雜性。Kafka需要Zookeeper的支持,Topic一般需要人工創建,部署和維護比一般MQ成本更高

 

 

保證每個消費者讀取數據都是有序的,而傳統隊列在服務器上按順序保留消息,如果多個消費者從隊列中消耗,則服務器按照存儲的順序分發消息。但是,儘管服務器按順序分發消息,但消息是異步傳遞給消費者的,因此它們可能會在不同的消費者上無序傳送。

 

 

Kafka 持久化日誌,這些日誌可以被重複讀取和無限期保留

Kafka 是一個分佈式系統:它以集羣的方式運行,可以靈活伸縮,在內部通過複製數據提升容錯能力和高可用性

Kafka 支持實時的流式處理

 

 

kafka設計的目標是:

高吞吐量,支持大容量事件流;高抗壓,支持離線系統週期性的數據壓力;低延遲;動態分佈式分區;容錯;

2.1 消息交付保證

消息交付是否可靠,有以下幾種保證:

At least once。至少一次。消息絕不會丟失,但有可能重新發送。(request.required.acks=1或-1)。Kafka的默認保證。 At most once。最多一次。消息可能丟失,但永遠不會重發。通過設置Producer異步提交可以實現。(request.required.acks=0)。 Exactly once。傳遞一次且僅一次。要求利用外部存儲系統配合Kafka的offset來保證。

2.2 高吞吐量

高吞吐量依賴於OS文件系統的頁緩存、sendfile技術和線性讀寫磁盤:

PageCache

依賴OS的頁緩存能大量減少IO,高效利用內存來作爲緩存。當上層有寫操作時,操作系統只是將數據寫入OS的PageCache,同時標記Page屬性爲Dirty。當讀操作發生時,先從PageCache中查找,如果發生缺頁才進行磁盤調度,最終返回需要的數據。實際上PageCache是把儘可能多的空閒內存都當做了磁盤緩存來使用。同時如果有其他進程申請內存,回收PageCache的代價又很小。

zero-copy

傳統網絡IO,OS 從硬盤把數據讀到內核區的PageCache,用戶進程把數據從內核區Copy到用戶區。然後用戶進程再把數據寫入到Socket,數據流入內核區的Socket Buffer上。OS 再把數據從Buffer中Copy到網卡的Buffer上,這樣完成一次發送。整個過程共經歷兩次Context Switch,四次System Call。

同一份數據在內核Buffer與用戶Buffer之間重複拷貝,效率低下。其中2、3兩步沒有必要,完全可以直接在內核區完成數據拷貝。這也正是Sendfile所解決的問題,經過Sendfile優化後,整個I/O過程就變成了下面這個樣子。

磁盤順序寫

磁盤線性讀寫要比隨機讀寫快很多。順序IO不僅可以利用RAID技術帶來很高的吞吐量,同時可以基於文件的讀和追加來構建持久化隊列,利用隊列來提供常量時間O(1)時間複雜度的put和get。

消息壓縮

Producer支持End-to-End的壓縮。數據在本地壓縮後放到網絡上傳輸,在Broker一般不解壓(除非指定要Deep-Iteration),直至消息被Consume之後在客戶端解壓。

當然用戶也可以選擇自己在應用層上做壓縮和解壓的工作(畢竟Kafka目前支持的壓縮算法有限,只有GZIP和Snappy),不過這樣可能造成效率的意外降低!

Kafka的End-to-End壓縮與MessageSet配合在一起工作效果最佳,上面的做法直接割裂了兩者間聯繫。至於道理其實很簡單,壓縮算法中一條基本的原理「重複的數據量越多,壓縮比越高」。大多數情況下輸入數據量大一些會取得更好的壓縮比。

Zookeeper的特性和怎麼實現主從切換

Zookeeper通過事務日誌和數據快照來避免因爲服務器故障導致的數據丟失。

  • 事務日誌是指服務器在更新內存數據前先將事務操作以日誌的方式寫入磁盤,Leader和Follower服務器都會記錄事務日誌。
  • 數據快照是指週期性通過深度遍歷的方式將內存中的樹形結構數據轉入外存快照中。但要注意這種快照是"模糊"的,因爲可能在做快照時內存數據發生了變化。但是因爲Zookeeper本身對事務操作進行了冪等性保證,故在將快照加載進內存後會通過執行事務日誌的方式來講數據恢復到最新狀態。

Redis分片

redis cluster集羣通過分片的方式來保存數據庫中鍵值對:集羣的整個數據庫被分爲16384個槽(slot),

數據庫中的每個鍵都屬於這16384個槽的其中一個,集羣中的每個節點可以處理0個或者最多16384個槽

每個結點存儲一部分的slot。一個槽只能存儲一條數據?

Kafka中bootstrap-server、broker-list和zookeeper的區別

0.8 以前,消費進度是直接寫到 zookeeper 的,consumer 必須知道 zookeeper 的地址。這個方案有性能問題,0.9 的時候整體大改了一次,brokers 接管了消費進度,consumer 不再需要和 zookeeper 通信

broker-list和bootstrap-server是同種意思,前者是老版本

Kafka如何保證數據不丟失

生產端配置參數:

 

request.required.acks

This value controls when a produce request is considered completed. Specifically, how many other brokers must have committed the data to their log and acknowledged this to the leader? Typical values are

  • 0, which means that the producer never waits for an acknowledgement from the broker (the same behavior as 0.7). This option provides the lowest latency but the weakest durability guarantees (some data will be lost when a server fails).
  • 1, which means that the producer gets an acknowledgement after the leader replica has received the data. This option provides better durability as the client waits until the server acknowledges the request as successful (only messages that were written to the now-dead leader but not yet replicated will be lost).
  • -1, The producer gets an acknowledgement after all in-sync replicas have received the data. This option provides the greatest level of durability. However, it does not completely eliminate the risk of message loss because the number of in sync replicas may, in rare cases, shrink to 1. If you want to ensure that some minimum number of replicas (typically a majority) receive a write, then you must set the topic-level min.insync.replicas setting. Please read the Replication section of the design documentation for a more in-depth discussion.

 

 

 

 

min.insync.replicas

 

When a producer sets request.required.acks to -1, min.insync.replicas specifies the minimum number of replicas that must acknowledge a write for the write to be considered successful. If this minimum cannot be met, then the producer will raise an exception (either NotEnoughReplicas or NotEnoughReplicasAfterAppend). 

When used together, min.insync.replicas and request.required.acks allow you to enforce greater durability guarantees. A typical scenario would be to create a topic with a replication factor of 3, set min.insync.replicas to 2, and produce with request.required.acks of -1. This will ensure that the producer raises an exception if a majority of replicas do not receive a write.

request.required.acks = ALL   (0就是不需要任何ack,相當於異步發送,只管發不管ack; 設成all或者-1,要求所有的fowller給leader回覆,然後leader給producer確認,是最保險的,但是犧牲吞吐量)

數據複製及ISR隊列

leader會維護一個與其基本保持同步的replica列表,這個列表被稱爲isr(in-sync-replica)

如果一個follower比leader落後太多,或者超過一定時間未發起數據複製請求,則leader將其從ISR移除

當Isr中所有replica都向leader發送ACK時,leader就commit同步的數據,之後consumer才能夠消費這部分commit的數據

https://blog.csdn.net/longlovefilm/article/details/88342512