聊聊Ozone的Topology Awareness

前言


衆所周知,在大規模分佈式存儲系統中,數據往往通過多副本的形式來保持其可用性。但是多副本如何進行位置放置又是一項值得深挖的領域。至少我們總不能將所有副本都放在一臺機器這樣的極端情況。對於副本數據的放置,其實涉及到的考量因素還是比較多的,副本放置過於分散化,網絡traffic開銷就打了,但是過於靠攏增加本地性讀呢,冗餘性又會受到影響,例如某個rack機器突然故障等等。這裏我們將這類的問題稱爲Topology Awareness問題,本文我們來聊聊Ozone的Topology Awareness方面的內容。

HDFS的Topology Awareness


筆者第一次瞭解到Topology Awareness是在學習HDFS Block placement的時候,HDFS遵守3副本塊按照,同rack,非同rack的三副本放置策略原則來達到數據高可用性的目的。這樣的放置策略當然沒有什麼大的問題,它能容忍一臺機器或一個rack不可用導致實際數據不可用的情況。

所以在這裏,管理員配置什麼樣的topology規則就顯得十分得重要了。我們可以使用最簡單的規則,比如,用物理rack作爲邏輯的topology位置rack。如果我們不配置任何的topology的規則,則所有機器的網絡位置將會變成default-rack,default-rack並不是一個好的設置。

HDFS Topology的層級,距離定義問題


管理員根據集羣節點的實際物理位置,給出對於topology location位置,這並不是難事。但問題來了,有的時候我們需要構建出更加複雜的topology結構,而不僅僅是data center–>rack—>node這樣的三級結構。

比如說,我們還想在rack層再做一個group,變成4級結構,或者可能在group層上在做個別屬性劃分。目前HDFS的Topology還不支持5級層級,group層已經有對應的實現類。因此在layer層的自定義上,HDFS的Topology Awareness還沒有達到足夠靈活的程度。

/dc
|
/rackgroup
|
/rack
|
/node

另外一點,Topology多層級的劃分一方面是爲了表明各節點的物理歸屬位置的不同,還有一點是不同層級的distance不同。這個distance可理解爲數據網絡傳輸的開銷,跨rack節點間的數據傳輸比同rack間的節點數據傳輸的慢,前者的distance就長一點。所以在這裏,我們可以給不同layer直接定義不同的distance cost。比如/dc到/rack是2,/rack到/node是1。

在HDFS現有的Topology規則下,沒有自定義distance cost的概念,不同layer間的距離是等價的,可以理解爲都是1個單位長度。

爲什麼這裏我們這麼強調network distance cost的概念呢?因爲這裏會涉及到最近距離的數據read的問題。對於客戶端的數據讀操作來說,選擇與其最近的節點去讀數據顯然是一種更優的策略方法。

Ozone同樣作爲數據存儲系統,它在HDFS Topology Awareness以上提到的2點不足之處都做了進一步地完善和改進,使之變成了更加靈活的Topology Awareness。

Ozone的Topology Awareness的配置使用


Ozone的Topology Awareness的核心思想和HDFS 類似,同樣基於的是同rack,不同rack的多副本放置策略。這裏重點談談它的自定義layer和distance cost的設置。

相比於HDFS爲了支持不同layer,通過定義新的實現子類這樣略顯笨重的方式,Ozone則定義了node schema的概念,來支持用戶自定義的topology。

在一個node schema中,它包含了node的類型,這裏的類型爲以下3類:

  • ROOT(“Root”, NetConstants.INNER_NODE_COST_DEFAULT),
  • INNER_NODE(“InnerNode”, NetConstants.INNER_NODE_COST_DEFAULT),
  • LEAF_NODE(“Leaf”, NetConstants.NODE_COST_DEFAULT);

然後後面屬性是其cost值。

然後這些被加載好的node schema被NodeSchemaManager以list的方式維護,按照深度順序,從上往下。

這裏schema的定義由外部傳入的topology文件決定,以下爲一份自定義的topology文件,深度爲4,相當於HDFS的NetworkTopologyWithNodeGroup類。

<?xml version="1.0"?>
<configuration>
    <layoutversion>1</layoutversion>
    <layers>
        <layer id="datacenter">
            <prefix></prefix>
            <cost>1</cost>
            <type>Root</type>
        </layer>
        <layer id="rack">
            <prefix>rack</prefix>
            <cost>1</cost>
            <type>InnerNode</type>
            <default>/default-rack</default>
        </layer>
        <layer id="node">
            <prefix></prefix>
            <cost>0</cost>
            <type>Leaf</type>
        </layer>
    </layers>
    <topology>
        <path>/datacenter/rack/node</path>
        <!-- When this field is true, each InnerNode layer should has its prefix defined with not empty value,
         otherwise the content is not valid. Default value is false.
         -->
        <enforceprefix>false</enforceprefix>
    </topology>
</configuration>

然後我們再配上topology mapping,用來指定各節點的topology 位置,按照上述的schema模式,layer層深度爲4。上面cost的配置取決於實際物理cost開銷,進行配置。

 hostrack file:
 xx(lyq-s2xx)    /dc1/rack1
 xx(lyq-s4xx)    /dc1/rack2
 xx(lyq-s3xx)    /dc2/rack1
 xx(lyq-s1xx)    /dc2/rack2

這裏的dc相當於rack上的group。然後配置上Ozone topology相關配置項,

<property>
   <name>ozone.scm.network.topology.schema.file</name>
   <value>/home/hdfs/apache/ozone/etc/hadoop/ozone-topology-default.xml</value>
</property>

<property>
  <name>net.topology.node.switch.mapping.impl</name>
  <value>org.apache.hadoop.net.ScriptBasedMapping</value>
</property>

<property>
  <name>net.topology.script.file.name</name>
  <value>/home/hdfs/apache/ozone/etc/hadoop/topology.py</value>
</property>

python解析腳本,

import sys
import os
import pwd
sys.argv.pop(0)
rack_dic = {}
try:
   with open("/home/hdfs/apache/ozone/etc/hadoop/hostrack") as f:
        for line in f:
           (key, val) = line.split()
           rack_dic[key] = val
   for ip in sys.argv:
        print '{0}'.format(rack_dic[ip])
except Exception,e:
    print "/default-rack"

配置完畢後,我們進行scm的重啓,然後執行命令printTopology的命令,我們可以看到各個節點已經加載了最新的topology位置,

[hdfs@lyq hadoop]$ ~/apache/ozone/bin/ozone scmcli printTopology
State = HEALTHY
 xx(lyq-s2xx)    /dc1/rack1
 xx(lyq-s4xx)    /dc1/rack2
 xx(lyq-s3xx)    /dc2/rack1
 xx(lyq-s1xx)    /dc2/rack2

倘若用戶傳入了一個層級不對的topology mapping,將會導致類似如下的節點註冊錯誤,

2019-12-18 07:56:58,579 WARN org.apache.hadoop.ipc.Server: IPC Server handler 1 on 9861, call Call#9916 Retry#0 org.apache.hadoop.ozone.protocol.StorageContainerDatanodeProtocol.submitRequest from xx.xx.xx.xx:40568
org.apache.hadoop.hdds.scm.net.NetworkTopology$InvalidTopologyException: Failed to add /dc2/rack2/0d98dfab-9d34-46c3-93fd-6b64b65ff543: Its path depth is not 3
	at org.apache.hadoop.hdds.scm.net.NetworkTopologyImpl.add(NetworkTopologyImpl.java:100)
	at org.apache.hadoop.hdds.scm.node.SCMNodeManager.register(SCMNodeManager.java:263)
	at org.apache.hadoop.hdds.scm.server.SCMDatanodeProtocolServer.register(SCMDatanodeProtocolServer.java:225)
	at org.apache.hadoop.ozone.protocolPB.StorageContainerDatanodeProtocolServerSideTranslatorPB.register(StorageContainerDatanodeProtocolServerSideTranslatorPB.java:69)
	at org.apache.hadoop.ozone.protocolPB.StorageContainerDatanodeProtocolServerSideTranslatorPB.processMessage(StorageContainerDatanodeProtocolServerSideTranslatorPB.java:104)
	at org.apache.hadoop.hdds.server.OzoneProtocolMessageDispatcher.processRequest(OzoneProtocolMessageDispatcher.java:72)
	at org.apache.hadoop.ozone.protocolPB.StorageContainerDatanodeProtocolServerSideTranslatorPB.submitRequest(StorageContainerDatanodeProtocolServerSideTranslatorPB.java:77)

Ozone Topology Awareness的用途


Ozone topology awareness配置使用完畢之後,它將會在哪些地方起到作用呢?主要在以下2個方面:

  • 第一,在Container做replication的時候,用以選擇符合topology awareness條件的節點做Container級別的replication。
  • 第二,Container選取Pipeline時,Pipeline內部節點的構成需要滿足topology awareness規則。

以上,就是本文今天所談論的關於Ozone系統內的Topology Awareness相關的內容,和HDFS的Topology Awareness類似但靈活許多。

引用


[1].https://issues.apache.org/jira/browse/HDDS-698 . Support Topology Awareness for Ozone

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