2012-09-07 16 views
19

Bazı java kodlarında consistent hash algoritmasını arıyorum. Guava Hashing kitaplığı consistentHash(HashCode, int) yöntemine sahiptir, ancak the documentation eksiktir. İlk umudum, bir dizi arka uç sunucusunda yükü verimli bir şekilde dağıtmak için consistentHash()'u basit oturum yakınlığı olarak kullanabilmemdi.Guava'nın Hashing # consistentHash'ı nasıl kullanmalıyım?

Bu yöntemin nasıl kullanılacağına dair gerçek bir dünya örneği var mı? Özellikle de hedef alandan bir kepçenin kaldırılmasını yönetmekle ilgileniyorum.

@Test 
public void testConsistentHash() { 
    List<String> servers = Lists.newArrayList("server1", "server2", "server3", "server4", "server5"); 

    int bucket = Hashing.consistentHash(Hashing.md5().hashString("someId"), servers.size()); 
    System.out.println("First time routed to: " + servers.get(bucket)); 

    // one of the back end servers is removed from the (middle of the) pool 
    servers.remove(1); 

    bucket = Hashing.consistentHash(Hashing.md5().hashString("blah"), servers.size()); 
    System.out.println("Second time routed to: " + servers.get(bucket)); 
} 

çıkışına İlanlar: Örneğin:

 
First time routed to: server4 
Second time routed to: server5 

İstediğim bir sunucu daha önce kaldırılmasından sonra aynı sunucuya eşlemek için bu tanımlayıcı ("SomeID") içindir listede. Yukarıdaki örnekte, kaldırma işleminden sonra, "server1" 'e eşlemek için "bucket", "server3"' e eşlemek için bucket 1, "server4" 'e eşlemek için bucket 2 ve "server5"' e eşlemek içinse bucket 3 'ün olmasını istiyorum.

Kova çıkarma ve ekleme işlemlerini yönetmek için ayrı bir (bir listeden daha karmaşık) veri yapısını korumalı mıyım? Sanırım özellikle benim için özel kovalar ekledikten ve çıkardıktan sonra yeniden işlemeyi yönetecek daha karmaşık bir Hashing API'sini tahmin ettim.

Not: Örnek kodun küçük bir giriş ve kova seti kullandığını biliyorum. Bunu 100 kova üzerinden 1000'lerce girdi ile denedim ve sonuç aynı. buckets - 99'u değiştirdiğimde 0-98 no'lu kovalara eşlenen girişler aynı kalır ve kova 99, kalan 99 kovaya dağıtılır.

+0

haklı için kova manange gerekiyor ... ama Guava boyutuna dışında listenizdeki hakkında hiçbir şey bilmiyor görebilirsiniz: Sadece bu garanti edemez sen misin Yani başka hiçbir şey yapamaz. – maaartinus

+0

Bunun gerçekten istediğiniz doküman bağlantısı olduğunu düşünüyorum: http://docs.guava-libraries.googlecode.com/git-history/release13/javadoc/com/google/common/hash/Hashing.html#consistentHash%28com. google.common.hash.HashCode,% 20int% 29 - doğru olduğu halde orada pek bir şey yok, başka ne söyleyeceğinizi düşünüyorsunuz? –

+0

@Kevin - Belgeleme muhtemelen O.K. Ekleme/kaldırma gereksiniminde bir çift daha fazla kelime varsa sonunda. Sorgumu yayınladım çünkü yorumumun yanlış olduğunu umuyordum ve düşünmediğim kova manipülasyonunu yönetmenin belli bir yolu vardı. Ben wikipedia girişi ve orada başvurulan java uygulama okumaya başladıktan sonra guava yöntemine var, bu yüzden bu iki makalenin ne anlattığına daha yakın bir şey görmeyi beklediğimi tahmin ediyorum (Chris'in aşağıda bir cevabın içinde ne çıkacağına dair açıklaması gibi). – GamingBuck

cevap

3

Hiçbir veri yapısının, geçerli consistentHash ile gerçekten doğru yapamayacağından korkuyorum. Yöntem yalnızca liste boyutunu kabul ettiğinden, sondan ekleme ve çıkarma işlemlerinden hiçbiri desteklenemez. Şu anda, en iyi çözüm

server.set(n, servers.get(servers.size() - 1); 
servers.remove(servers.size() - 1); 

sıralamak başarısız takas Bu şekilde ve en son sunucu tarafından

servers.remove(n) 

değiştirme muhtemelen oluşur. Bu, iki takaslı sunucuya atamaları yanlış yaptığı için kötü görünüyor. Bu sorun, bir tanesi başarısız olduğu kadar sadece yarısı kadar kötü. Ancak, son liste elemanının kaldırılmasından sonra, başarısız sunucuya ve önceki son sunucuya yapılan atamalar haricinde her şey yolundadır.

Gerekli değişiklik olarak iki kat fazla ödev.Optimal değil, ama umarım kullanılabilir mi?

+0

Hızlı cevap için teşekkürler. Daha zengin bir API bulunana kadar makul bir çalışma gibi görünüyor. Muhtemelen bununla devam edeceğim ya da diğer dil uygulamalarına dayanarak kendi başıma döneceğim. – GamingBuck

+0

@GamingBuck: [Daha iyi (belki de en uygun) bir çözüm oluşturdum] (https://dl.dropbox.com/u/4971686/published/maaartin/guava/consistenthash/index.html). – maaartinus

3

Şu anda bunu yapmanın iyi bir yolu olduğunu sanmıyorum. Mevcut haliyle consistentHash sadece basit durumlarda yararlıdır - temelde, sunucu sayısını artırmak veya azaltmak için bir düğme var ... ama her zaman sonunda ekleyerek ve kaldırarak.

WeightedConsistentHash<String, String> serverChooser = 
    WeightedConsistentHash.create(stringFunnel(), stringFunnel()); 
serverChooser.setBucketWeight("server1", 1); 
serverChooser.setBucketWeight("server2", 1); 
// etc. 

System.out.println("First time routed to: " + serverChooser.hash("someId")); 

// one of the back end servers is removed from the (middle of the) pool 
serverChooser.setBucketWeight("server2", 0); 

System.out.println("Second time routed to: " + serverChooser.hash("someId")); 

Ve aynı her seferinde sunucuyu almalısınız:

public final class WeightedConsistentHash<B, I> { 
    /** Initially, all buckets have weight zero. */ 
    public static <B, I> WeightedConsistentHash<B, I> create(
     Funnel<B> bucketFunnel, Funnel<I> inputFunnel); 

    /** 
    * Sets the weight of bucket "bucketId" to "weight". 
    * Requires "weight" >= 0.0. 
    */ 
    public void setBucketWeight(B bucketId, double weight); 

    /** 
    * Returns the bucket id that "input" maps to. 
    * Requires that at least one bucket has a non-zero weight. 
    */ 
    public B hash(I input); 
} 

Sonra yazardı:

Orada böyle bir sınıf eklenmesi için çalışmalar bazı iş. Bu API uygun görünüyor mu?

+0

Yine de Funnel API'sine yakından bakmadım ama işe yaramış gibi görünen ilk bakışta. Kullanılabilirliğini görmek için sabırsızlanıyorum. – GamingBuck

+0

Bu konuda herhangi bir haber var mı? [V14] 'da "weightedConsistentHash" referansını görebiliyorum (http://docs.guava-libraries.googlecode.com/git-history/v14.0.1/javadoc/com/google/common/hash/Hashing.html) Ancak, [v16] adresinden yoksundur (http://docs.guava-libraries.googlecode.com/git-history/v16.0.1/javadoc/com/google/common/hash/Hashing.html). Referans, Colin tarafından 9acc76ba4 işleminde kaldırıldı. – maaartinus

2

guava API'sı sunucu listeniz hakkında herhangi bir bilgiye sahip değildir. can,

int bucket1 = Hashing.consistentHash(Hashing.md5().hashString("server1"),N);  
int bucket2 = Hashing.consistentHash(Hashing.md5().hashString("server1"),N-1); 

assertThat(bucket1,is(equalTo(bucket2))); iff bucket1==bucket2!=N-1 

Eğer sunucu listesinden kendinize Sen dikkat