1. 程式人生 > >Cassandra學習筆記之機架感應策略

Cassandra學習筆記之機架感應策略

Snitches概述

Cassandra提供了Snitches功能,可以知道叢集中的每個節點所屬資料中心和機架。所有機架感應策略都實現了相同的介面IEndpointSnitch。先來看看Snitches的類圖:


IEndpointSnitch介面中提供了比較實用的方法:

//通過ip地址獲取機架
public String getRack(InetAddress endpoint);
//通過ip地址獲取資料中心
public String getDatacenter(InetAddress endpoint);
//按節點距離排序
public List<InetAddress> getSortedListByProximity(InetAddress address, Collection<InetAddress> unsortedAddress);
//比較節點與指定節點遠近
public int compareEndpoints(InetAddress target, InetAddress a1, InetAddress a2);
//開如gossip協議
public void gossiperStarting();
Snitches按實現分為三種:

(1)SimpleSnitch:這種策略不能識別資料中心和機架資訊,適合在單資料中心使用;

(2)NetworkTopologySnitch:這種策略提供了網路拓撲結構,以便更高效地訊息路由;

(3)DynamicEndpointSnitch:這種策略可以記錄節點之間通訊時間間隔,記錄節點之間通訊速度,從而達到動態選擇最合適節點的目的。
SimpleSnitch比較簡單就不用介紹了,此類只是一個預設實現。下面主要介紹NetworkTopologySnitch和DynamicEndpointSnitch兩種策略。

NetworkTopologySnitch

此策略提供了網路拓撲結構,因此可以知道節點之間的遠近關係,該抽象類實現了compareEndpoints方法,程式碼如下:
    public int compareEndpoints(InetAddress address, InetAddress a1, InetAddress a2)
    {
        if (address.equals(a1) && !address.equals(a2))
            return -1;
        if (address.equals(a2) && !address.equals(a1))
            return 1;

        String addressDatacenter = getDatacenter(address);
        String a1Datacenter = getDatacenter(a1);
        String a2Datacenter = getDatacenter(a2);
        if (addressDatacenter.equals(a1Datacenter) && !addressDatacenter.equals(a2Datacenter))
            return -1;
        if (addressDatacenter.equals(a2Datacenter) && !addressDatacenter.equals(a1Datacenter))
            return 1;

        String addressRack = getRack(address);
        String a1Rack = getRack(a1);
        String a2Rack = getRack(a2);
        if (addressRack.equals(a1Rack) && !addressRack.equals(a2Rack))
            return -1;
        if (addressRack.equals(a2Rack) && !addressRack.equals(a1Rack))
            return 1;
        return 0;
    }
1、先比較ip地址,如果其中一個節點的ip地址與給定節點相同,另一個不相同,則返回; 2、到這裡表示3個節點ip均不相同,與1一樣,比較資料中心,然後比較機架; 3、到這裡表示同資料中心,同機架,返回0. 這裡用到了兩個方法:getDatacenter和getRack,不同的子類實現不同。AbstractNetworkTopologySnitch有四個子類實現:

PropertyFileSnitch

使用屬性檔案配置拓撲結構,該檔案位於conf/cassandra-topology.properties中,配置類似
# Data Center One
175.56.12.105=DC1:RAC1
175.50.13.200=DC1:RAC1
175.54.35.197=DC1:RAC1
該檔案記錄資料中心和機架的位置,資料中心名稱可以隨意定義,叢集中的所有節點都應該有相同的配置。獲取資料中心和機架直接讀取配置檔案即可:
public String getDatacenter(InetAddress endpoint)
{
    String[] info = getEndpointInfo(endpoint);
    assert info != null : "No location defined for endpoint " + endpoint;
    return info[0];
}
public String getRack(InetAddress endpoint)
{
    String[] info = getEndpointInfo(endpoint);
    assert info != null : "No location defined for endpoint " + endpoint;
    return info[1];
}

GossipingPropertyFileSnitch

通過屬性檔案(conf/cassandra-rackdc.properties)定義當前節點的資料中心和機架,並使用Gossip協議傳播到其他節點,當cassandra-topology.properties檔案存在的時候,cassandra-rackdc.properties只是做為一個備用。配置類似:
dc =DC1
rack =RAC1
該策略便於快速傳播一個節點的變化,一般和PropertyFileSnitch配合使用。其獲取資料中心的程式碼如下:
    public String getDatacenter(InetAddress endpoint)
    {
        if (endpoint.equals(FBUtilities.getBroadcastAddress()))
            return myDC;

        EndpointState epState = Gossiper.instance.getEndpointStateForEndpoint(endpoint);
        if (epState == null || epState.getApplicationState(ApplicationState.DC) == null)
        {
            if (psnitch == null)
            {
                if (savedEndpoints == null)
                    savedEndpoints = SystemKeyspace.loadDcRackInfo();
                if (savedEndpoints.containsKey(endpoint))
                    return savedEndpoints.get(endpoint).get("data_center");
                return DEFAULT_DC;
            }
            else
                return psnitch.getDatacenter(endpoint);
        }
        return epState.getApplicationState(ApplicationState.DC).value;
    }
1、如果是本機,直接返回本地配置檔案中的資料中心; 2、不是本機的情況:如果接收到了Gossip訊息,直接返回Gossip訊息中的資料中心;否則返回本機conf/cassandra-topology.properties檔案中的資料中心; 機架的獲取與資料中心獲取類似。

RackInferringSnitch

其實現與PropertyFileSnitch類似,根據ip地址確定資料中心和機架,如圖所示:
第二個8位決定資料中心,第三個8位決定機架。

Ec2Snitch

主要使用在單區域資料中心,使用私有ip地址的情況。

DynamicEndpointSnitch

該策略通過監控兩個節點的通訊時間,來決定最佳選擇方案,該策略是預設使用的,也是Cassandra推薦的。該策略和失敗檢測密切相關,Cassandra失敗檢測原理基於Hayashibara的一篇論文(http://ddg.jaist.ac.jp/pub/HDY+04.pdf). 參考資料: 原始碼下載地址git://git.apache.org/cassandra.git