だいぶ前にかった[[UNIX magazine 2009年04月号>http://www.amazon.co.jp/gp/product/B001U52MP0?ie=UTF8&tag=muranagasview-22&linkCode=as2&camp=247&creative=1211&creativeASIN=B001U52MP0]]でクラウドを特集していた。 この中で、サーバ台数を増やしてスケールアウトする場合に、クライアントがどのサーバに処理させるかを決めるためにコンシステントハッシング(Consistent Hashing)が紹介されていた。 なお、コンシステントハッシングについては、以下のリンクを見てください。 -[[Tom White's Blog: Consistent Hashing>http://weblogs.java.net/blog/tomwhite/archive/2007/11/consistent_hash.html]] -[[コンシステント・ハッシュ法 (Tom White's Blog の日本語訳)>http://www.hyuki.com/yukiwiki/wiki.cgi?ConsistentHashing]] 最近ネットをみていたら、[[「Consistent Hasing を Ruby で試す」>http://tam.qmix.org/dist/wiki/ConsistentHashingRuby]]にて、rubyを使ってConsistent Hashingをためしていた。そのプログラムは、もともと[[「Consistent Hashing を試す」>http://8-p.info/consistent-hashing/]]にあるperlのプログラムをrubyにしたそうで、私もJavaで作成してみました。 上記のサイトでは、 import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; public class Main { //private static final SortedMap<byte[], String> circle = new TreeMap<byte[], String>(); private static final SortedMap<BigInteger, String> circle = new TreeMap<BigInteger, String>(); private static final SortedMap<String, List> nodesmap = new TreeMap<String, List>(); private static final List<String> alphalist = Arrays.asList( "A","B","C","D","E","F","G","H","I","J","K","L","M", "N","O","P","Q","R","S","T","U","V","W","X","Y","Z"); private static String search( SortedMap circle, BigInteger rec ){ // circleはSortedMapなので、Keyが小さい方から取得される前提 for( Object circleKey : circle.keySet()){ if( rec.compareTo((BigInteger)circleKey) != 1 ){ return (String)circle.get(circleKey); } } // ノードの最大値を越える場合は最小ノードに入れる return (String)circle.get(circle.firstKey()); } private static BigInteger getHash( String value ) throws NoSuchAlgorithmException{ int ret = 0; MessageDigest digest = MessageDigest.getInstance( "md5" ); byte[] byteHash = digest.digest(value.getBytes()); return new BigInteger(byteHash); } public static void main(String[] args) throws NoSuchAlgorithmException { int numOfReplicants = args.length; Collection<String> nodes = Arrays.asList(args); for( String node : nodes ){ circle.put( getHash(node), node ); } for( String str : alphalist ){ String node = search(circle, getHash(str)); if( !nodesmap.containsKey(node)){ List<String> asciiList = new LinkedList<String>(); asciiList.add(str); nodesmap.put(node, asciiList); }else{ nodesmap.get(node).add(str); } } for( String node : nodesmap.keySet()){ System.out.print(node + " "); List<String> asciiList = nodesmap.get(node); for( String strascii : asciiList ){ System.out.print(strascii + " "); } System.out.print("\n"); } } }