副本節點的選擇(機架感知)
1、默認情況下
第一個副本在client所處的節點上,如果客戶端在集羣之外,(在win7上運行程序,寫文件到集羣上),隨機選一個。
第二個副本和第一個副本在不同機架上,節點隨機選
第三個副本和第二個副本在相同的機架上,節點隨機
2、hadoop2.7.2
第一個副本在client所處的節點上,如果客戶端在集羣之外,(在win7上運行程序,寫文件到集羣上),隨機選一個
第二個副本與第一個副本在同一機架上
第三個副本在不同的機架上
{對於副本來講,有一個副本在不同的機架上,可以保證可用性,在client上寫入數據,用網絡拓撲距離計算,在client上寫入兩個副本的速度強於 將兩個副本寫入到另外的機架上}
自定義機架感知
1、創建類實現DNSToSwitchMapping接口
2、配置文件core-site.xml
<property>
<name>net.topology.node.switch.mapping.impl</name>
<value>自己定義的jar的全路徑</value>
</property>
3、分發core-site.xml
4、編譯程序並打包成jar,分發給所有節點的hadoop的classpath下
/app/hadoop/shared/hadoop/common/lib/
hadoop不能探測到節點所在的交換機,只能知道節點的IP地址和主機名稱,所以需要自己定義規則。
package Hadoop;
import org.apache.hadoop.net.DNSToSwitchMapping;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 2018/7/5
* 16:11
* 自定義機架感知
*/
public class RackAware implements DNSToSwitchMapping {
/**
* 傳遞的是客戶端的ip列表,返回機架感知的路徑列表
*/
@Override
public List<String> resolve(List<String> names) {
ArrayList<String> list = new ArrayList<String>();
if (names != null && names.size() > 0) {
for (String name : names) {
if (name.startsWith("s")) {
String ip = name.substring(1);
Integer intIP = Integer.parseInt(ip);
if (intIP < 103) {
list.add("/rack1/" + intIP);
} else {
list.add("/rack2/" + intIP);
}
} else if (name.startsWith("192")) {
int ip = Integer.parseInt(name.substring(name.lastIndexOf(".")) + 1);
if (ip < 103) {
list.add("/rack2/" + ip);
} else {
list.add("/rack2/" + ip);
}
}
}
}
// 寫入文件
try {
FileOutputStream fos = new FileOutputStream("");
for (String name : list) {
fos.write((name + "\r\n").getBytes());
}
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
@Override
public void reloadCachedMappings() {
}
@Override
public void reloadCachedMappings(List<String> list) {
}
}