Tag Archive: Twitter


Run Cassandra As A Windows Service

ne of the main issues that comes up over and over again for Cassandra is:

How do I run Cassandra as a Windows Service?

In this post I am going to answer that question and in the process demonstrate how to do it in less than 10 minutes.

Background

Cassandra is mainly developed by Linux developers so very little attention has been paid to the Windows developer or administrator as far as Cassandra goes.  So as Windows developers we have to hop through a couple more hoops than just clicking on an install.exe file and and letting it do all the work.  However lucky for us, those hoops are easy and quickly hopped through.

Step 1

If you haven’t done so already please read my jump start for Windows users on install Cassandra, this guide will get you ready for the next steps.

Step 2

The second step is also an easy one, you need to download a package called RunAsService, which provides the ability to run any program as a Windows Service.

After you have downloaded the file extract the contents to a directory of your choosing.  (I extracted it to c:\RunAsService)

Note: RunAsService was originally developed here, however I recompiled it to run on .NET 2.0.

Step 3

To install RunAsService open up a command prompt with Administrative privileges and run this command.

cd c:\RunAsService
install networkservice

This registers RunAsService with your Windows Service.  Make sure to keep your command prompt open because you will need it for the 5th step.

Step 4

To configure RunAsService for Cassandra open up the RunAsService.exe.config file in your favorite text editor and replace <service.settings> section with the following so that it looks like this:

<!– Services configuration –>
<service.settings>
<!– Run Cassandra as a service –>
<!– My Cassandra install path is C:\apache-cassandra\ –>
<service>
<name>Cassandra Database</name>
<executable>C:\apache-cassandra\bin\cassandra.bat</executable>
<parameters></parameters>
</service>
</service.settings>

<!– Services configuration –><service.settings>    <!– Run Cassandra as a service –>    <!– My Cassandra install path is C:\apache-cassandra\ –>    <service>        <name>Cassandra Database</name>        <executable>C:\apache-cassandra\bin\cassandra.bat</executable>        <parameters></parameters>    </service></service.settings>

After you have finished, save the config file and exit your text editor.

Note: My Cassandra install is in c:\apache-cassandra\ you will have to correct the config above for where you installed it if different than mine.

Step 5

The last and final step of this process is to start the RunAsService service.  You can either do it through the Services control panel or just type the following in to your command prompt.

net start runasservice

You should see a response in the command line saying that the service has been successfully started.  To verify that Cassandra has been started you can use the cassandra-cli.bat file:

cd c:\apache-cassandra\bin\ cassandra-cli.bat connect localhost/9160

It should report that it is connected to the server if the service is running.  And with that we are done, and I told you it would only take about 10 minutes.

Cassandra’s data model cheat sheet

Cassandra is a structured store. It has a rich data model that goes beyond a simple key-value model. This is a good thing as some of the complexity can be pushed to Cassandra, leading to simpler and more efficient applications. There is problem though: the guys who designed Cassandra have given complex names to the (rather simple) data model elements. This post tries to explain(again): “WTF is a SuperColumn“?

Data model elements

You can also download a PDF version.

Column

A name value pair (contains also a time-stamp, not represented here for the sake of clarity).
Cassandra ColumnColumn

Super Column

A sorted associative array of columns.

Super Column
Super Column

Column Family

A container for columns sorted by their names. Column Families are referenced and sorted by row keys.

Column FamilyColumn Family

Super Column Family

A container for super columns sorted by their names. Like Column Families,  Super Column Families are referenced and sorted by row keys.

Super Column FamilySuper Column Family

Keyspace

Top level element of a schema. Container for column families.

Examples

These examples are extracted from the model of a simple twitter clone discussed here.  I picked the statuses column family and the user relationships super column family.

Statuses Column FamilyStatuses Column Family

User Relationships Super Column Family
User Relationships Super Column Family

A name value pair (contains also a time-stamp, not represented here for the sake of clarity).

Cassandra meets Hector(Sharp)

A few days ago, I set up a Cassandra node on my machine.  Time to write some code now! In this post, we’ll get started with HectorSharp, a .NET client for Cassandra.

I assume you have a Cassandra node up and running on your machine on port 9160. If you didn’t do this already, you might find this useful. You will need to download and build the HectorSharp library (I didn’t find any pre-built binaries?).

To get a first taste, here is the traditional “Hello World!”:

var clientFactory = new KeyedCassandraClientFactory(
new CassandraClientPoolFactory().Create(),
new KeyedCassandraClientFactory.Config());
var client = clientFactory.Make(new Endpoint("localhost", 9160));
var keyspace = client.GetKeyspace("Keyspace1");
var path = new ColumnPath("Standard1", null, "greeting");
keyspace.Insert("0", path, "Hello World!");
Column column = keyspace.GetColumn("0", path);
Console.WriteLine(column.Value);

Looks pretty straight forward. Let’s do a quick walk-through:

var clientFactory = new KeyedCassandraClientFactory(
new CassandraClientPoolFactory().Create(),
new KeyedCassandraClientFactory.Config());

We create a factory for the clients we will be using to access Cassandra. The factory takes two parameters: a pool for clients, as you’d have for database connections, and a configuration object.

var client = clientFactory.Make(new Endpoint("localhost", 9160));

The factory is used to get a client for the local machine on port 9160, where our Cassandra server is already listening and waiting for requests.

var keyspace = client.GetKeyspace("Keyspace1");

I didn’t change the out-of-the box config. It happens that the default key space name is Keyspace1.

var path = new ColumnPath("Standard1", null, "greeting");

The column path object indicates where a column is located in a family or super family. Standard1 is the family name. The second argument is null since the column we want to acess is not embedded into a super column. The last argument is the column name. If you are confused about Cassandra’s data model, you can have a look at this post.

keyspace.Insert("0", path, "Hello World!");
Column column = keyspace.GetColumn("0", path);
Console.WriteLine(column.Value);

We used the path object to put and get back the string “Hello World!”. The column family at row “0″ is now containing a key “greeting” pointing to the value “Hello World!”.

Hello World!

So far, HectorSharp seems to be doing the job. Time to write a bigger application!

In this post we will write a sample account management system for Asp.NET MVC applications using Cassandra as a back-end and HectorSharp as Cassandra’s .NET client.

Before we begin, if you are not familiar with HectorSharp, here is a gentle introduction. Note also that we will be using .NET framework 3.5 and Asp.NET MVC 1.0 in the code fragments presented here.

Interface

In our application, account management and authentication is handled by a dedicated MVC controller: AccountController. As you would expect, this controller will handle actions like: LogOn, LogOff, Register, ChangePassword etc. The actual work is not implemented in the controller methods. It is instead delegated to a separate authentication service. This separation of concerns is important as it will make the code cleaner and easier to change. Moreover, it eases controller testing as we will be able to inject a mocked disconnected authentication services into the controller.

Let’s start by specifying the contract of our authentication service:

using System.Web.Security;
public interface IAuthentificationService
{
bool SignIn(string userName, string password, bool createPersistentCookie);
void SignOut();
MembershipCreateStatus SignUp(string userName, string password, string email);
bool ChangePassword(string userName, string oldPassword, string newPassword);
}

This interface allows the basic operations needed to back up our controller actions, let’s keep it simple for the moment. We’ll refactor the code as new requirements and needs emerge during development iterations. Notice that we are reusing the MembershipCreateStatus enumeration from System.Web.Security.

Implementation

Now, time to implement the interface using Cassandra as a store for user information. Basically, each time a new user sings up we will insert his info into Cassandra, and each time a user want’s to sign in, we will look for his info in Cassandra. Before writing code, let’s have a look at the schema we will be using. For the purpose of demonstration, we will simplify things.  We will use a single column family, keyed by user names, to hold the user information: name, password and email. Here is an example of what a column family row would look like:

User Info

Our column family is defined in the storage-conf.xml as follows:

<Keyspace Name="Chripper">
<ColumnFamily Name="Users" CompareWith="UTF8Type" />
</Keyspace>

Based on this schema, the authentication service implementation is straightforward. We will use FormsAuthentication for maintaining the authentication cookie and focus on the membership management.

using System.Web.Security;
using HectorSharp;
public class AuthentificationService : IAuthentificationService
{
private static readonly ColumnPath UsersPasswordPath =
new ColumnPath("Users", null, "Password");
private static readonly ColumnPath UsersNamePath =
new ColumnPath("Users", null, "Name");
private static readonly ColumnPath UsersEmailPath =
new ColumnPath("Users", null, "Email");
private readonly ICassandraClient client;
public AuthentificationService(ICassandraClient cassandraClient)
{
client = cassandraClient;
}
private IKeyspace Keyspace { get { return client.GetKeyspace("Chirpper"); } }
public bool SignIn(string userName, string password, bool createPersistentCookie)
{
if (!ValidateUser(userName, password))
{
return false;
}
FormsAuthentication.SetAuthCookie(userName, createPersistentCookie);
return true;
}
public void SignOut()
{
FormsAuthentication.SignOut();
}
public MembershipCreateStatus SignUp(string userName, string password, string email)
{
Column nameColumn;
if (Keyspace.TryGetColumn(userName, UsersNamePath, out nameColumn))
{
return MembershipCreateStatus.DuplicateUserName;
}
Keyspace.Insert(userName, UsersNamePath, userName);
Keyspace.Insert(userName, UsersPasswordPath, password);
Keyspace.Insert(userName, UsersEmailPath, email);
return MembershipCreateStatus.Success;
}
public bool ChangePassword(string userName, string oldPassword, string newPassword)
{
if (!ValidateUser(userName, oldPassword))
{
return false;
}
Keyspace.Insert(userName, UsersPasswordPath, newPassword);
return true;
}
private bool ValidateUser(string userName, string password)
{
Column passwordColumn;
if (Keyspace.TryGetColumn(userName, UsersPasswordPath, out passwordColumn))
{
return string.Equals(password, passwordColumn.Value);
}
return false;
}
}

Conclusion

We implemented an authentication service using Cassandra as a store for user information. This implementation is a first iteration and chances are that we would like to have a richer schema (enable searching users by email, add a password question etc.) and to add more functionality to the service (control password strength, hash or crypt stored passwords etc.). We might also want to refactor the code that queries and updates the Cassandra store to a separate class. This class will act as a mediator between Cassandra and our application code (aka a repository).

Epilogue

If you are curious on how the MVC controller would consume our authentication service, here is a sample implementation:

using System;
using System.Security.Principal;
using System.Web.Mvc;
using System.Web.Security;
[HandleError]
public class AccountController : Controller
{
private readonly AccountInputValidator validator;
public AccountController()
: this(null)
{
}
public AccountController(IAuthentificationService authentificationService)
{
AuthentificationService = authentificationService
?? new AuthentificationService(CassandraClients.Make());
validator = new AccountInputValidator(ModelState);
}
private IAuthentificationService AuthentificationService { get; set; }
public ActionResult LogOn()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
{
if (!validator.ValidateLogOn(userName, password))
{
return View();
}
if (!AuthentificationService.SignIn(userName, password, rememberMe))
{
ModelState.AddModelError("_FORM", "The username or password provided is incorrect.");
}
if (!string.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
return RedirectToAction("Index", "Home");
}
public ActionResult LogOff()
{
AuthentificationService.SignOut();
return RedirectToAction("Index", "Home");
}
public ActionResult Register()
{
return View();
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Register(string userName, string email, string password, string confirmPassword)
{
if (validator.ValidateRegistration(userName, email, password, confirmPassword))
{
var status = AuthentificationService.SignUp(userName, password, email);
if (status == MembershipCreateStatus.Success)
{
return RedirectToAction("Index", "Home");
}
ModelState.AddModelError("_FORM", AuthentificationStatus.ToString(status));
}
// If we got this far, something failed, redisplay form
return View();
}
[Authorize]
public ActionResult ChangePassword()
{
return View();
}
[Authorize]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult ChangePassword(string currentPassword, string newPassword, string confirmPassword)
{
if (!validator.ValidateChangePassword(currentPassword, newPassword, confirmPassword))
{
return View();
}
try
{
if (AuthentificationService.ChangePassword(User.Identity.Name, currentPassword, newPassword))
{
return View("ChangePasswordSuccess");
}
ModelState.AddModelError("_FORM", "The current password is incorrect or the new password is invalid.");
return View();
}
catch
{
ModelState.AddModelError("_FORM", "The current password is incorrect or the new password is invalid.");
return View();
}
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.User.Identity is WindowsIdentity)
{
throw new InvalidOperationException("Windows authentication is not supported.");
}
}
}

Chirper is the first open-source non trivial web application example with .NET/NoSql integration. Chirper implements a simple twitter clone that, unlike twitter :P , uses Cassandra as its only database. It would’ve been probably cooler to code Chirper it in Ruby or in Python but, unfortunately, this is already done.

Chirper’s front-end is written in C# / Asp.net MVC 2.0. The back-end is based on Cassandra using the Aquiles library. The source code is freely available under the terms of the Apache License, Version 2.0.

Installation

Before going into Chirper’s design details in the next sections, you might want to play a bit with it first. For this, you will need to: (1) configure the database store with Chirper’s schema, and (2) setup Chirper in your favorite webserver that supports Asp.net.

Cassandra configuration

Simply edit Cassandra’s storage-conf.xml file and add a Chirper keyspace as follows:

<Keyspaces>
<Keyspace Name='Chirper'>
<ColumnFamily Name='Users' CompareWith='UTF8Type'/>
<ColumnFamily Name='Tweets' CompareWith='UTF8Type'/>
<ColumnFamily Name='Following' CompareWith='UTF8Type'/>
<ColumnFamily Name='Followers' CompareWith='UTF8Type'/>
<ColumnFamily Name='TimeLine' CompareWith='UTF8Type'/>
<ColumnFamily Name='UserLine' CompareWith='UTF8Type'/>
...
</Keyspace>
</Keyspaces>

We will go through the data schema in more details below. If you don’t have already a Cassandra node at hand don’t worry, it’s easy to set up. Here is how I did.

Installing the webapp

Just download the Chirper’s latest binary and unzip it somewhere on your hard drive. From your webserver configuration console create a new webapp based on the unzipped Chirper folder. The exact webapp creation steps depend on your webserver. Here are the instructions for IIS7.

The alternative would be to check-out the source code and run (or debug) Chirper from visual studio, using the development web server.

Design

Front-end

Chirper is still work in progress. However, it has already the most important features: tweeting, following other users, displaying timeline and userline, dispalying followers list etc. The front-end is really simple, nothing much to say here. Here are the main components:

  • Two MVC controllers are handling all the user actions: one controller for authentication and registration (similar to the one presented here) and another controller for everything else. The views are kept very simple too.
  • The model consists essentially of two classes: User and Tweet. Follower and Following are just users with a time-stamp.
  • A repository class abstracts all the web application logic from the back-end operations. This is really helpful in case we might want to mock the db store for testing.

Back-end

Chirper’s schema is really straightforward and very similar to the one implemented in Twissandra. Basically, we have two main families: Users and Tweets. Four other families are introduced to join theses main families in order to implement timelines and followers lists.

Users family

All Chirper users are recorded in this family. Rows are keyed by user name. Each column name/value represents a user’s property: Name, DisplayName, Location, Password etc.

Users Family

Tweets family

This family holds all Chirper tweets (or chirps :) ).  The rows are keyed by tweet id (a UUID). As for users, the columns represent the tweet properties.

Tweets family

Timeline and Userline families

A timeline (resp. userline) is simply a set of time-stamp/tweet id pairs held in rows keyed by user ids. The timestamps correspond to when the tweet was tweeted. In the userline family, the tweets are those tweeted by the user  used as row key. In the timeline family, the tweets are tweeted by the followed users.

User tweets family

Following and Followers families

The following (resp. followers) family joins users with their following (resp. followers) users.

User Following/Followers family

Conclusion

It was surprisingly easy to interface a .NET webapp with Cassandra. I had to write a few helper functions around the Aquiles connector but it did the job very well. Chirper’s schema is NOT designed to scale. It was kept very simple for the purpose of demonstration. I am currently looking for some help on Chirper’s web design, if you feel like contributing, please drop a comment here. It would also be nice to host a running instance of Chirper on the web (as Twissandra and Retwis do). If you can help on this please contact me.

Resource : http://www.javageneration.com/?p=318

Cassandra up and running on windows in 10 min (or so)

I was surprised how easy it is to set up and run the Apache key-value store Cassandra on Windows. There is no self-contained Windows-based installer, but I got it running from the extracted archive quite easily. All I wanted to do is to get it up and running quickly and do some basic testing. No fancy config, I used the out-of-the-box config to set up a single node on my Windows Vista dev machine. Here is how it went.

Download and unzip the archive

Just go to the Cassandra download page and get the latest binary archive from there. I downloaded the 0.6.1 archive: apache-cassandra-0.6.1-bin.tar.gz and unzipped it to c:\cassandra.

Quick setup

The storage-conf.xml file contains some important config information, including the data schema. Let’s not change the schema for now. All we needed to do is to tell Cassandra where to put the commit logs and the data on the hard disk. I created a new directory cassandra-data and created in it two sub-directories data and commitlog. So let’s modify the config file located in c:\cassandra\conf\storage-conf.xml and modify the corresponding elements:

<CommitLogDirectory>c:\cassandra-data\commitlog</CommitLogDirectory>
<DataFileDirectories>
<DataFileDirectory>c:\cassandra-data\data</DataFileDirectory>
</DataFileDirectories>

That’s it! Time to run the server :-)

Running the server

First of all, we need to check that the environment variable JAVA_HOME is correctly set, Cassandra scripts rely on it.

I switched to the bin directory and I launched the cassandra.bat command with -f switch (-f keeps the server in “foreground” mode, on order to have the logs in stdout).

C:\cassandra\bin>cassandra.bat -f
Starting Cassandra Server
Listening for transport dt_socket at address: 8888
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/cassandra/thrift/CassandraDaemon
Caused by: java.lang.ClassNotFoundException: org.apache.cassandra.thrift.CassandraDaemon
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)

Ouch! Something went wrong. After having a quick look at the cassandra.bat script, I figured out that it assumes that the current directory is the Cassandra “home directory”, i.e. c:\cassandra in my case. Let’s give it a second try:

c:\cassandra>bin\cassandra.bat -f
Starting Cassandra Server
Listening for transport dt_socket at address: 8888
INFO 16:27:12,627 Auto DiskAccessMode determined to be standard
INFO 16:27:13,123 Saved Token not found. Using 47823312181423841445299406225505462239
INFO 16:27:13,124 Saved ClusterName not found. Using Test Cluster
INFO 16:27:13,134 Creating new commitlog segment c:\cassandra-data\commitlog\CommitLog-1272205633134.log
INFO 16:27:13,256 Starting up server gossip
INFO 16:27:13,369 Binding thrift service to localhost/127.0.0.1:9160
INFO 16:27:13,418 Cassandra starting up...

Hurray! Seems to be working. It says it’s listening on localhost port 9160, let’s verify this.

Hello World!

Cassandra comes with a nice test utility: Cassandra CLI. It’s an interactive command line that you can use to put/get values in Cassandra. Let’s open a second shell window and run it.

c:\cassandra>bin\cassandra-cli.bat
Starting Cassandra Client
Welcome to cassandra CLI.
Type 'help' or '?' for help. Type 'quit' or 'exit' to quit.

Cool! It even has a friendly help command. First, let’s connect to our server using the connect command.

cassandra> connect localhost/9160
Connected to: "Test Cluster" on localhost/9160

We succeeded to connect to the Cassandra server. Before going further, let’s have a quick look at the schema. Remember, it is defined in the same file we modified earlier in the setup step: storage-conf.xml.

<Keyspace Name="Keyspace1">
<ColumnFamily Name="Standard1" CompareWith="BytesType" />
...
</Keyspace>

Cassandra’s Data model nomenclature is not obvious. In a nutshell: Keyspace1 is the name of the schema, Standard1 is a collection of rows, each row has an ordered set of key-value pairs. Let’s put some data there:

cassandra> set Keyspace1.Standard1['0']['greeting'] = 'Hello World!'
Value inserted.

Cassandra obeyed and stored our data: in Column Family Standard1 at row ’0′ we inserted the key-value pair (‘greeting’, ‘Hello World’). Let’s try to query Cassandra and see if the data is actually there.

cassandra> get Keyspace1.Standard1['0']['greeting']
=> (column=6772656574696e67, value=Hello World!, timestamp=1272208335786000)

It worked :) Notice the timestamp added to the inserted key-value.

Conclusion

That’s it for tonight! It’s surprisingly easy to setup a Cassandra node on Windows. Next step would be to write some code and try the Ruby or C# clients.

Resource : http://www.javageneration.com/?p=19

Cassandra has gotten a lot of hype lately, having been recently chosen as the nucleus of the Digg upgrade simultaneous with Reddit taking baby-steps to the platform. Digg ispromoting their revised technology stack as enabling a “wicked fast” experience that is much more individualized, while Reddit is thus far only really using it as a drop-in key/value replacement for MemcacheDB.

And of course Cassandra is well known for its use by Facebook and Twitter.

Naturally, given the white-hot hype, most want to see what the big deal is. Emerging web technologies often require that you either have a Linux box available (either a physical box or a virtual instance in a product like VirtualBox), however with just a couple of minor config changes and deviations from the docs, you can do a trial run and kick the wheels on Windows as a first class host, even if any possible production use would almost certainly see it deployed to Linux.

Cassandra is layered over Java, and of course a benefit of that platform is that it is inherently cross platform.

  1. Download and install the latest Java JDKEnsure, post install, that the JAVA_HOME environment variable is pointed at the root of your JDK install(which on a 64-bit machine might be C:\Program Files (x86)\Java\jdk1.6.0_18).
  2. Download Apache Ant. Uncompress to the folder C:\Apache\Ant (giving you files like C:\Apache\Ant\bin\ant.bat).
  3. Download Cassandra. Given that you’re probably going to be playing around for a while, go with the 6.0b2 copy, downloading the bin versionUncompress the package into the location C:\Apache\Cassandra.
  4. Open a command prompt and navigate to the cassandra directory (e.g. after runningC:, do a cd C:\Apache\Cassandra). Run the commandC:\Apache\Ant\bin\ant ivy-retrieve. This will download Cassandra depedencies.
  5. Edit C:\Apache\Cassandra\conf\storage-conf.xml, updating lines 188 – 193 to replace each instance of /var/lib/cassandra/ references withC:\Apache\Cassandra\Files\.
  6. Copy the files from C:\apache\cassandra\build\lib\jars (which are the files that ant downloaded) to C:\apache\cassandra\lib. It isn’t the most elegant solution but it’s the most concise in point form.
  7. In a command prompt, after running C: and cd \Apache\Cassandra, run the command bin\cassandra. Cassandra should start up successfully (and if applicable the Windows firewall will ask if it should make an exception). If it doesn’t start successfully you likely didn’t follow one of the prior points correctly.
  8. In another console window navigate to C:\Apache\Cassandra and run the command bin\cassanda-cli. At the prompt run the command connect localhost/9160 and you should connect. You can now try out some of the simple set and get commands you can find in the README.txt.
  9. Start reading up on the Thrift API, the basics of data storage, what a “super-column is”, and so on.

I’ve been playing around with various NoSQL* solutions for some time, however given the incredible hype — which is strangely coupled with a complete lack of any objective measure — I’ve decided to put it to the test. In the next couple of days a high-performance SSD will arrive and I’ll gather some metrics for objective purposes, because the message being sold doesn’t technically pass the B.S. test.

* – A better name than “NoSQL” is desperately needed. Backronyms and revisionist history — seriously, guys, “Not Only SQL?” — don’t solve the problem that the name is incendiary, inaccurate, and a little ridiculous. KVDBMS works for some of the products, but isn’t quite applicable to richer solutions like Cassandra.

Cassandra is a very, very cool product, and I immediately see lots of very interesting uses for it, but what is most striking is what is missing from the product. It is so intensely bare-bones at the moment, which is exactly how MySQL made inroads: When it first became the first-love of many of the same people and sites that now herald NoSQL (the same people who almost without fail rallied behind PHP which…well…enough said), it was almost comically deficient as a database product, but as it grew those features it grew away from its core contingent.

Exciting times regardless. There are many niches in the technology space, in which the appropriate solutions should be applied, so it is always worth keeping an open mind.

Reference : http://www.yafla.com/dforbes/Getting_Started_with_Apache_Cassandra_a_NoSQL_frontrunner_on_Windows/

Powered by WordPress | Theme: by 85ideas. Editor by Khoanguyen