"; */ ?>


06
Jul 11

NoRAM DB => “If It Does Not Fit in RAM, I Will Quietly Die For You”

Out of 472 NoSQL databases / distributed caches that are currently available, highly buzzed and scream that only their precious brand solves the world toughest problems.. There are only a few that have less screaming and more doing that I found so far:

Choosing a Drink


See.. Choice makes things better and worse at the same time =>

if I am thirsty, and I only have water available, 
I'll take that, satisfy my thirst, 
and come back to focusing on whatever it is I was doing

at the same time

if I am thirsty, and I have 472 sodas, and 253 juices, and 83 waters available
I'll take a two hour brake to choose the right one, satisfy my thirst, 
and come back to focusing on whatever it is I was doing

It may not seem as two different experiences at first, but they are different approaches.

Especially bad is when out of those 472 sodas, #58 has such a seductive ad on a can, and it promisses you $1,000,000 prize, if only you make a sip. So you are interested ( many people drink it too ), trying it… and spitting it out immediately => now there are 471 left to go.. remaining thirst, and such a dissatisfaction

If there is CAP, there is CRACS


NoSQL is no different now days. Choosing the right data store for your task / project / problem really depends on several factors. Let’s redefine a CAP theorem (because we can), and call it CRACS instead:

  • Cost:                    Do you have spare change for several TB of RAM?
  • Reliability:            Fault Tolerance, Availability
  • Amount of data:   Do you operate Megabytes or Terabytes, or maybe Petabytes?
  • Consistency:         Can you survive two reads @ the same millisecond return different results?
  • Speed:                  Reading, which includes various aggregates AND writing

That’s pretty much it, let me know if you have you favorite that is missing from CRACS, but at least for now, five is a good number. Of course there are other important things, like simplicity ( hello Cassandra: NOT ) and ease of development ( hello VoltDB, KDB: NOT ), and of course fun to work with, and of course great documentation, and of course great community, and of course… there are others, but above five seem to nail it.

Distributed Cache: Why Redis and Hazelcast?


Well, let’s see Redis and Hazelcast are distributed caches with an optional persistent store. They score because they do just that => CACHE, they are data structure based: e.g. List, Set, Queue.. even DistributedTask, DistributedEvent, etc. Again they are upfront with you: we do awesome CACHE => and they do. I have a good feeling about GemFire, but I have not tried it, and last time I contacted them, they did not respond, so that’s that.

NoSQL: Going Beyond RAM


See, what I really learned to dislike is “if it does not fit in RAM, I will quietly die for you” NoSQL data stores ( hello MongoDB ). And it is not just the index that should entirely fit into memory, but also the data that has not yet been fsync’ed, data that was brought back for querying, data that was fsync’ed, but still hangs around, etc..

The thing to understand when comparing Riak to MongoDB is that Riak actually writes to disk, and MongoDB writes to mmap files ( memory ). Try setting Mongo’s WriteConcern to “FSYNC_SAFE”, and now compare it to Riak => that would be a fair comparison. And having LevelDB as Riak’s backend, or even good old Bitcask, Riak will take Gold. Yes, Riak’s storage is pluggable : ).

Another thing besides that obvious Mongo “RAM problem” is JSON, I mean BSON. Don’t let this ‘B‘ fool you, a key name such as “name” will take at least 4 bytes, without even getting to the actual value for this key, which affects performance, as well as storage. Riak has protocol buffers as an alternative to JSON, which can really help with the document size. And with secondary indicies on the way, it may even prove be searchable : ).

Both Riak and MongoDB struggle with Map/Reduce: MongoDB does it in a single (!) SpiderMonkey thread, and of course it has a friendly GlobalLock that does not help, but it takes a point from Riak by having secondary indicies. But both: Mongo and Riak are in the process of rewriting their MapReduce frameworks completely, so we’ll see how it goes.

Cassandra Goodness and Awkwardness


Cassandra is however a solid piece of software, with one caveat: you have to hire DataStax guys, who are really, really, really good, by the way, but you have to pay up good money for such goodness. Otherwise, on your own, you don’t need to really have a PhD to handle Cassandra [ you only really need to have a PhD in Comp Sci, if you actually can and like to hang around in school for a couple more years, but that is a topic for another blog post ].

Cassandra documentation is somewhat good, and the code is there, the only problem is it looks and feels a bit Frankenstein: murmurhash from here, bloom filter from here, here is a sprinkle of Thrift ( really!? ), in case you want to Insert/Update, here is a “mutator”, etc.. Plus adding a node is really an afterthought => if you have TBs of data, adding a node can take days, no really => days. Querying is improving with CQL roll out in 0.8, but any kind of even simplistic aggregation requires some “Thriftiveness” [ read “Awkwardness” ].

CouchDB is Awesome, but JSON


CouchDB looks and feels like an awesome choice if the size of the data is not a problem. Same as with MongoDB, “JSON only” approach is a bit weird, why only JSON? The point of no schema is NOT that it changes ALL the time => then you have just a BLOB, content of which you cannot predict, hence index. The point is, the schema ( and rather some part of it ) may/will change, so WHY the heck do I have to carry those key names (that are VARCHARs and take space) around? Again CouchDB + alternative protocol would make it in my “Real NoSQL Dudes” list easily, as I like most things about it, especially secondary indicies, Ubuntu integration, mobile expansion, and of course Erlang, but Riak has Erlang too : )

VoltDB: With Great Speed Comes Great Responsibility


As far as speed, VoltDB would probably leave most of others behind (well, besides OneTick and KDB), but it actually is not NoSQL (hence it is fully ACID), and it is not NotJustInRam store, since it IS Just RAM. Three huge caveats are:

1. Everything is a precoded store procedure => ad hoc querying is quite difficult
2. Aggregation queries can’t work with data greater than 100MB ( for a temp table )
3. Data “can” be exported to Hadoop, but there is no real integration (yet) to analyze the data that is currently in RAM along with the data in Hadoop.

But it is young and worth mentioning, as I think RAM and hardware gets cheaper, “commodity nodes” become less important, so “Scale Up” solutions may actually win back some architectures. There is of course a question of Fault Tolerance, which Erlang / AKKA based systems will solve a lot better than any “Scale Up”s, but it is a topic for another time.

Dark Hourses of NoSQL


There are others, such as Tokyo Cabinet ( or is it Kyoto Cabinet now days ), Project Voldemort => I have not tried them, but have heard good stories about them. The only problem I see with these “dark horse” solutions is lack of adoption.

Neo4j: Graph it Like You Mean It


Ok, so why Neo4j? Well, because it is a graph data store, that screws with your mind a bit (data modeling) until you get it. But once you get it, there is no excuse not to use it, especially when you create your next “social network, location based, shopping smart” start up => modeling connected things as a graph just MAKES SENSE, and Neo4j is perfect for it.

You know how fast it is to find “all” connections for a single node in a non graph data store? Well, it is longer and longer with “all” being a big number. With Neo4j, it is as fast as to find a single connection => cause it is a graph, it’s a natural data structure to work with graph shaped data. It comes with a price it is not as easy to Scale Out, at least for free. But.. it is fully transactional ( even JTA ), it persists things to disk, it is baked into Spring Data. Try it, makes your brain do a couple of front splits, but your mind feels really stretched afterwards.

The Future is 600 to 1


There is of course HBase, which Hadapt guys are promising to beat 600 to 1, so we’ll see what Hadapt brings to the table. Meanwhile I invite Riak, Redis, Hazecast and Neo4j to walk together with me the slippery slope of NoSQL.


06
Apr 11

Spock It Like You Mean It!

So here we go.. Yesterday night we hacked our way into The Ancient Database where besides the data about ancients themselves, we found incredible stats about many different living species of all the planets ancients traveled to.

So what do we do now? Well, we need a way to query/read this data. So we asked Sam to develop a reader ( ancients called it a ‘DAO’ ) to find a number of living species on each planet since the “beginning of time”.

So she did, and called this “species reader” a ‘SpeciesDao’.

We, of course, trust Sam. But in ancient technology, trust is always based on challenging the assumption by testing all the possible permutations. So we are calling Mr. Spock to help us out…

Sam of course used a well known ancient technique ( code name: Spring Framework ) to create a “species reader”, so Mr. Spock will use all the goodies of this technique to inject all the dependencies ( e.g. data source, a reader itself, etc.. ) for a test.

Since Mr. Spock is a peaceful inhabitant from a planet Simplicity, it speaks a simple language called Groovy. This language is unique in a way that living beings of all the galaxies can pick it up and understand it within minutes, which by the way makes it a perfect choice for various intergalactic conferences.

To start off, we’ll tell Mr. Spock where to look for all the dependencies:

@ContextConfiguration( locations = [ "classpath:/conf/test-context.xml", "classpath:/conf/persistence-context.xml" ] )

The data we are going to test against will be in a form of DbUnit datasets, which by the way can be XML based, Excel based or even YAML based. In this example we are going to focus on planets of two galaxies that peak our curiosity the most: Milky Way and Pegasus.

  // Species of the Milky Way Galaxy by Planet
  static final P3X_888_SPECIES_DATASET = "/dataset/stage/p3x-888-species.xml"
  static final DAKARA_SPECIES_DATASET = "/dataset/stage/dakara-species.xml"
  ....
 
  // Species of the Pegasus Galaxy by Planet
  static final ASURAS_SPECIES_DATASET = "/dataset/stage/asuras-species.xml"
  static final WRAITH_HOMEWORLD_SPECIES_DATASET = "/dataset/stage/wraith-homeworld-species.xml"
  ....

Since it is a test, we already know the exact number of living spices since the ‘beginning of time’ for each dataset. And we’d need to call the reader Sam wrote ( ‘SpeciesDao’ ) for each dataset and compare it with an expected number. So you see, lots of repetitive actions. But no worries humans! Spock has an elegant way to deal with all these repetitions, by using its ‘WHERE’ power:

    where:
 
             planet                        |          numberOfSpeciesFound
 
      // Milky Way Galaxy
      P3X_888_SPECIES_DATASET              |                  888
      DAKARA_SPECIES_DATASET               |                 123804
      HELIOPOLIS_SPECIES_DATASET           |                   7
      .....

That’s neat. The only problem is if the number does not match ( yes, even Sam has bugs ) for example for planet Dakara, Mr. Spock will tell us that [ “something did not match up..” ], but will forget to mention that “it” did not match up specifically for a Dakara planet. And if we have thousands of such planets, it’ll be extremely difficult to find the culprit. But again, humans, this is easily solvable by using a Mr. Spock’s secret power: The power of ‘@Unroll’!

  @Unroll("#planet should have #numberOfSpeciesFound species found")
  def "only living species since begining of time should be found"() { ... }

By annotating a test method with @Unroll, in case where a number of living species found did not match a number that we expected, Mr. Spock will say just that. For example for Dakara, it’ll now say: “Dakara should have 123804 species found”, while also telling us the actual number that was found to compare. Pretty handy!

One last touch before we can fully trust Mr. Spock.. The way the ancient technology ( Spring ) was written, it won’t allow to inject collaborators ( e.g. data source ) statically before all the specifications / permutations. It can be tweaked to do that, but cmmon, who are we to tweak the ancients.. Instead we’ll tell Mr. Spock to do all the setup it needs only the first time a data source is injected:

    // setupSpec() cannot access Spring beans ( e.g. dataSource ), hence need to check it every time
    if ( ! databaseTester ) {
      databaseTester = new DataSourceDatabaseTester( dataSource )
    }

Now we are ready to roll. Let’s put all the pieces together and make sure Sam’s creation does what it’s supposed to:

 
@ContextConfiguration( locations = [ "classpath:/conf/test-context.xml", "classpath:/conf/persistence-context.xml" ] )
class FindNumberOfSpeciesTest extends Specification {
 
  // Species of the Milky Way Galaxy by Planet
  static final P3X_888_SPECIES_DATASET = "/dataset/stage/p3x-888-species.xml"
  static final DAKARA_SPECIES_DATASET = "/dataset/stage/dakara-species.xml"
  static final HELIOPOLIS_SPECIES_DATASET = "/dataset/stage/heliopolis-species.xml"
  static final ASCHEN_PRIME_SPECIES_DATASET = "/dataset/stage/aschen-prime-species.xml"
  static final P4X_650_SPECIES_DATASET = "/dataset/stage/p4x-650-species.xml"
  static final VIS_UBAN_SPECIES_DATASET = "/dataset/stage/vis-uban-species.xml"
  static final PROCLARUSH_SPECIES_DATASET = "/dataset/stage/proclarush-species.xml"
  static final DAKARA_SPECIES_DATASET = "/dataset/stage/dakara-species.xml"
  static final HEBRIDAN_SPECIES_DATASET = "/dataset/stage/hebridan-species.xml"
 
  // Species of the Pegasus Galaxy by Planet
  static final ASURAS_SPECIES_DATASET = "/dataset/stage/asuras-species.xml"
  static final WRAITH_HOMEWORLD_SPECIES_DATASET = "/dataset/stage/wraith-homeworld-species.xml"
  static final SATEDA_SPECIES_DATASET = "/dataset/stage/sateda-species.xml"
  static final DAGAN_SPECIES_DATASET = "/dataset/stage/dagan-species.xml"
  static final LORD_PROTECTORS_SPECIES_DATASET = "/dataset/stage/lord-protectors-species.xml"
  static final M7G_677_SPECIES_DATASET = "/dataset/stage/m7g-677-species.xml"
  static final ATHOS_SPECIES_DATASET = "/dataset/stage/athos-677-species.xml"
 
  static final THE_BEGINNING_OF_TIME = Date.parse( "yyyy-M-d", "1979-01-01" )
 
  @Autowired
  SpeciesDao speciesDao
  @Autowired
  DataSource dataSource
 
  @Shared IDatabaseTester databaseTester
 
  @Unroll("#planet should have #numberOfSpeciesFound species found")
  def "only living species since the beginning of time should be found"() {
 
    when: stageTestData planet
 
    then: speciesDao.findNumberOfSpeciesLivingSince( THE_BEGINNING_OF_TIME ) == numberOfSpeciesFound
 
    where:
 
             planet                        |          numberOfSpeciesFound
 
      // Milky Way Galaxy
      P3X_888_SPECIES_DATASET              |                  888
      DAKARA_SPECIES_DATASET               |                 123804
      HELIOPOLIS_SPECIES_DATASET           |                   7
      ASCHEN_PRIME_SPECIES_DATASET         |                 2423984
      P4X_650_SPECIES_DATASET              |                  2600
      VIS_UBAN_SPECIES_DATASET             |                   0
      PROCLARUSH_SPECIES_DATASET           |                 8869346
      DAKARA_SPECIES_DATASET               |                  5672
      HEBRIDAN_SPECIES_DATASET             |                   67
 
      // Pagasus Galaxy
      ASURAS_SPECIES_DATASET               |                  823
      WRAITH_HOMEWORLD_SPECIES_DATASET     |                 62634
      SATEDA_SPECIES_DATASET               |                  327
      SATEDA_SPECIES_DATASET               |                   0
      DAGAN_SPECIES_DATASET                |                  777
      LORD_PROTECTORS_SPECIES_DATASET      |                  8786
      M7G_677_SPECIES_DATASET              |                  4739
      ATHOS_SPECIES_DATASET                |                3767822
 
  }
 
  def stageTestData = { dataSetLocation ->
 
    dataSource != null
    speciesDao != null
 
    // setupSpec() cannot access Spring beans ( e.g. dataSource ), hence need to check it every time
    if ( ! databaseTester ) {
      databaseTester = new DataSourceDatabaseTester( dataSource )
    }
 
    databaseTester.setDataSet( new FlatXmlDataFileLoader().load( dataSetLocation ) )
    databaseTester.onSetup()
  }
}

Spock away Humans!


05
Apr 11

Mobile Devices Visiting Dotkam

Looking at mobile stats I can conclude that Android users are most interested in my content ( number of users vs average 21 seconds on the page ), where iPhone users are most curious ( max number of visits ), and of course thank you the lonely “Sony” user who spent 4 and a half minutes here :)

Moible Devices Visiting Dotkam

But overall most of my daily visits ( currently about 1300 ) are coming from other places. Need to work on that..


15
Mar 11

Spring Batch: CommandLineJobRunner to Run Multiple Jobs

Sometimes this requirement may jump at you: “I still want to have them as several jobs, but I want no operational overhead, and need to run them in sequence via a single launch…”.

So if you were using CommandLineJobRunner to launch these jobs, it would only be natural to aggregate those calls under your own e.g. “CommandLineMultipleJobRunner” that just delegates its calls to “CommandLineJobRunner” for each job in a list..

The only caveat is the default SystemExiter which is set to JvmSystemExiter, which makes it imposible to make more than one launch using a “CommandLineJobRunner”, since “JvmSystemExiter” does:

public void exit(int status) {
    System.exit(status);
}

Fortunately, there is a static accessor to override this behavior:

// disabling a default "JvmSystemExiter" to be able to run several times
CommandLineJobRunner.presetSystemExiter( new SystemExiter() { public void exit( int status ) {} } );

Now, call “CommandLineJobRunner.main( String[] args )” as many times as you’d like.

If you have a choice, think about creating a single multi step job instead, but if you don’t have a luxury, “CommandLineMultipleJobRunner” should now be not all that hard to implement.

Batch Away! :)


10
Mar 11

Having Fun with Groovy Date Parsing

How do you convert a String to Date in Groovy? Well it’s simple:

   Date.parse( "yyyy-M-d", "2011-01-15" )

Now, let’s say I would like to shorten this: yes, it looks to long, remember the actual data I am interested in is “2011-01-15”, everything else means nothing really.. datawise.

Ok, so I can

  Date.metaClass.'static'.fromString = { str ->
    Date.parse( "yyyy-M-d", str )
  }

which gives me a shorter representation ( less fluff around the actual data ):

  Date.fromString( "2011-01-15" )

That’s not bad, but I would like to take it further :) I am staging data ( domain objects ) in my Spock tests, and need as less fluff as possible => “only data matters”. So here it is, the geeky solution:

Create a DataParser:

  class DateParser {
    def static te = { str -> Date.parse( "yyyy-M-d", str ) }
  }

Wherever you need parse dates, import it as ‘d’:

  import org.dotkam.util.date.DateParser as d

Now create your d.tes ( I mean dates :) ) as:

  d.te( "2011-01-05" )

Awesome!
//TODO: it can of course be extended with multiple formats