權衡問題---學習了微服務各大常用組件的一點思考

1.沒有什麼技術可以完全通用,只要深度使用一定需要從業務出發對技術進行權衡

從幾個例子出發:

1.ES的分片機制天生支持分佈式,同時也帶來了分佈式了弊端:排序和算分問題;

搜索的場景需要嚴格的定製化,通過對mapping的修改可以支持算分的調整,影響查詢的結果-----代價是大大增加開發和mapping的維護成本

想要精確的算分和排序--->需要大量的計算和內存

如果數據量不大---->默認使用一個分片---->不需要對排序和算法另外處理/同時犧牲了分佈式的特性(建議一個業務場景的分片不超過20g。日誌索引的分片不超過50g),這也是爲什麼7.x版本之後默認一個分片

如果數據量巨大---->必須使用分片----->定製化mapping,粒度到字段級別----->同時還需要大量的內存(只能通過優化儘量壓縮,對業務進行區分,必要的時候只能佔用大量的cpu和內存 DFS query then Fetch

 

 

下面來看一下ES的查詢過程:默認場景下的-----犧牲精準度保證效率

 

 

 

 

 

2.kafka與ES面臨相同的問題:kafka的單個分區內可以保證順序性,分區之間是不能保證順序性的

如果是類似於日誌,不需要考慮消息的順序性,那可以很好的發揮性能

 

如果需要保證順序性:

2.1)從業務上把需要有序的打到同一個partition。因爲大多數情況只需要業務上保證有序就可以,不用全局有序通過message key來定義,因爲同一個key的message可以保證只發送到同一個partition,比如說key是user id,table row id等等,所以同一個user或者同一個record的消息永遠只會發送到同一個partition上,保證了同一個user或record的順序

 

那麼單個分片內kafka如何保證有序?

  1. producer發消息到隊列時,通過加鎖保證有序
    現在假設兩個問題:
    broker leader在給producer發送ack時,因網絡原因超時,那麼Producer 將重試,造成消息重複。
    先後兩條消息發送。t1時刻msg1發送失敗,msg2發送成功,t2時刻msg1重試後發送成功。造成亂序。

     2.解決重試機制引起的消息亂序

       爲實現Producer的冪等性,Kafka引入了Producer ID(即PID)和Sequence Number。對於每個PID,該Producer發送消息的每個<Topic, Partition>都對應一個單調遞增的Sequence Number。同樣,Broker端也會爲每個<PID, Topic, Partition>維護一個序號,並且每Commit一條消息時將其對應序號遞增。對於接收的每條消息,如果其序號比Broker維護的序號)大一,則Broker會接受它,否則將其丟棄:

  • 如果消息序號比Broker維護的序號差值比一大,說明中間有數據尚未寫入,即亂序,此時Broker拒絕該消息,Producer拋出InvalidSequenceNumber
  • 如果消息序號小於等於Broker維護的序號,說明該消息已被保存,即爲重複消息,Broker直接丟棄該消息,Producer拋出DuplicateSequenceNumber
  • Sender發送失敗後會重試,這樣可以保證每個消息都被髮送到broker

 

 

3.分佈式的系統中路由算法的弊端:增加/刪除節點時會有路由錯誤的問題(引發類似於緩存雪崩的場景)

對應的解決方案:

3.1)如redis的一致性hash算法

3.2)ES同樣面臨類似的場景:每個index的主分片設置策略,動態分配會有大量的數據遷移,分配不合理又會影響性能

對此,ES的解決方案是:index建立好之後不允重新設置分片,需要重新設置需要reindex

 

2.從CAP到BASE,都是對分佈式的一種權衡策略

 

 

總結:

根據不同的需求和場景,進行定製化的使用

 

 

 

 

 

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