Load balancing and improved failover in Hector

Balance the load, woman!

I’ve added a very simple load balancing feature, as well as improved failover behavior to Hector. Hector is a Java Cassandra client, to read more about it please see my previous post Hector – a Java Cassandra client.

In version 0.5.0-6 I added poor-man’s load balancing as well as improved failover behavior.

The interface CassandraClientPool used to have this method for obtaining clients:

/**
 * Borrows a client from the pool defined by url:port
 * @param url
 * @param port
 * @return
 */
CassandraClient borrowClient(String url, int port)
    throws IllegalStateException, PoolExhaustedException, Exception;

Now with the added LB and failover it has:

/**
 * Borrow a load-balanced client, a random client from the array of given client addresses.
 *
 * This method is typically used to allow load balancing b/w the list of given client URLs. The
 * method will return a random client from the array of the given url:port pairs.
 * The method will try connecting each host in the list and will only stop when there's one
 * successful connection, so in that sense it's also useful for failover.
 *
 * @param clientUrls An array of "url:port" cassandra client addresses.
 *
 * @return A randomly chosen client from the array of clientUrls.
 * @throws Exception
 */
CassandraClient borrowClient(String[] clientUrls) throws Exception;

And usage looks like that:

// Get a connection to any of the hosts cas1, ca2 or cas3
CassandraClient client = pool.borrowClient(new String[] {"cas1:9160", "cas2:9160", "cas3:9160"});

So, when calling borrowClient(String[]) the method randomly chooses any of the clients in the array and connects to it. That’s what I call poor man’s load balancing, just plain dumb random, not real load balancing. By all means, true load balancing which takes into account performance measurements such as response time and throughput is infinitely better than the plain random selection I’m employing here and in my opinion should be left out for your ops folks to deal with and not to the program, however, if you only need a very simplistic approach of random selection, then this method may suite your needs.

A nice side effect of using this method is improved failover. In previous versions hector implemented failover, but in order to find out about the ring structure it had to connect to at least one host in the ring first and query it to learn about the rest. The result was that if a new connection is made and it’s so unfortunate that this new connections is made to unavailable host, then this new client cannot connect to the host to learn about other live hosts so it fails right away. With this new method which sends an array of hosts the client keeps connecting to hosts in the list in random order until it finds one that’s up. In the example above the client may choose to connect to cas2 first; if cas2 is down it’ll try to connect to (say) cas3 and if cas3 is also down it’ll try to connect to cas1; only if all three hosts are down will it give up and return an error. Failing to connect to hosts is considered an error, but a recoverable error, so it’s transparent to the client of hector but is reported to JMX and has its own special counter (RecoverableLoadBalancedConnectErrors).

17 Responses to “Load balancing and improved failover in Hector”

  1. Hi,
    Thank you for this cool library.
    Is there a cassandra 6.0 rc version plan ?

    Best Regards,

    By SI on Mar 9, 2010

  2. Some folks started to work on it (not me personally), but I don’t have ETA yet

    By Ran Tavory on Mar 10, 2010

  3. Hi.
    Can you prototype very simple example how to reading all the keys or better range of keys with Hector?!

    I’m at very begging.

    By Andrey on Mar 24, 2010

  4. Well, that would require some time, which I don’t have, but there is something very close to that at the test file http://github.com/rantav/hector/blob/master/src/test/java/me/prettyprint/cassandra/service/KeyspaceTest.java

    By Ran Tavory on Mar 24, 2010

  5. Thanks :)
    At the end it was helpful!

    For hector v0.6 it can looks like this:

    ColumnParent cp = new ColumnParent(“Standard1″);
    SlicePredicate sp = new SlicePredicate();
    SliceRange range = new SliceRange();
    range.setStart(new byte[0]);
    range.setFinish(new byte[0]);
    sp.setSlice_range(range);

    Map<String, List> map = ks.getRangeSlice(cp, sp, “”, “”, 5);
    for (String s : map.keySet()) {
    List columns = map.get(s);
    System.out.println(s);
    for (Column column : columns) {
    System.out.println(“\t” + new String(column.getName()) + “\t>>\t” + new String(column.getValue()));
    }
    }

    By Andrey on Mar 25, 2010

  6. How would I specify my own maxActive, maxIdle numbers (that are inside package private CassandraClientPoolByHostImpl)?

    CassandraClientPool pool = CassandraClientPoolFactory.INSTANCE.get();

    I get the pool above, but with default maxActives..

    I am using 0.6.0-10

    Thank you

    By tc on Apr 17, 2010

  7. @tc see CassandraClientPoolFactory.createNew(CassandraHostConfigurator cassandraHostConfigurator)

    By Ran Tavory on Apr 17, 2010

  8. thanx Ran .. The problem is, even though I can browse the src on your website to find CassandraHostConfigurator, it is missing in the download for 0.6.0-10. Also the CassandraClientPoolFactory only has a createNew() method instead of a createNew(CassandraHostConfigurator config).

    I guess the modification wasn’t made at the time of building the jar for download. Could you please update the download?

    By tc on Apr 17, 2010

  9. @hc let me look into that, but in the mean time, do you mind taking the discussion to hector-users@googlegroups.com for the benefit of all?

    By Ran Tavory on Apr 18, 2010

  10. you got it. Done.

    By tc on Apr 18, 2010

  11. Hello Ran,

    1) Can you provide a solution or a sample for searching (Column and SuperColumn) (Fulltext). What is the Way to realize this? Hadoop/MapReduce? See you a posibility to build/use a index for columns?

    2) How can be realized a “relation” For Sample: (http://arin.me/blog/wtf-is-a-supercolumn-cassandra-data-model) Arin describes good a simple Data-Model to build a Blog. But how can we read (filter) all Posts from “BlogEntries” from a single Autor? (filter the Supercolumns by a culum inside of a SuperColumn)

    The “relation” for Sample is Autor -> BlogEntries…

    To filter the Datas there is a needing to specify in a “get” a Key OR a Column/Value combination…

    Thanks in Advance! – and thx for Hector! We love it…
    With Hector i build a (Apache)Cocoon-Transformer.

    With kind regards,
    Falk

    By Falk Wolsky on May 2, 2010

  12. Hi @Falk, this is an excellent question to user@cassandra

    By Ran Tavory on May 2, 2010

  13. Hello Ran,

    hmm. the answer on this List was “not so good”… ;-)
    I Think, Lucandra can be a good point to start indexing and Text-Search. I have to evaluate this..

    Ok. Please let us focus to the relation question:
    (Sample Data-Model from Arin)

    BlogEntries : {
    i-got-a-new-guitar : { // row key
    title: This is a blog entry about my new, awesome guitar,
    body: this is a cool entry. etc etc yada yada
    author: Arin Sarkissian // a row key into the Authors CF
    }
    }

    Now, the question is: See you any possibility to build a “get” Function with it i can find all “BlogEntries” from a “named” autor?

    For sample:
    ks.getColumn(search,key,ColumnPath); (simplified)
    “search” should be {column:value} / {author:Arin Sarkissian} and key for this sample can be used or not set (“*”).

    Maybe we can handle this inside a SliceRange “query”?

    Thanks in Advance

    By Falk Wolsky on May 3, 2010

  14. @Falk this cannot be done out of the box. I’ll give you my answer, but really this is a question suitable to user@cassandra.

    you can do this by implementing an application level index
    Or by denormalizing the data
    Or wait until cassandra adds indexes (I think version 0.7.0, but not sure)

    By Ran Tavory on May 4, 2010

3 Trackback(s)

  1. Jun 9, 2010: OCTO talks ! » Jouons avec Cassandra… (1/3)
  2. Jun 9, 2010: OCTO talks ! » Let’s play with Cassandra… (Part 1/3)
  3. Aug 6, 2010: Hector API v2 | PrettyPrint.me

Sorry, comments for this entry are closed at this time.