-
Notifications
You must be signed in to change notification settings - Fork 157
Storing data in riak
Unless you're already familiar with CAP Theorem and eventual consistency, taking the time to read through at least The Riak Fast Track would be well worth your while.
It's ok, we'll wait.
Ok! Now that you've read through that and understand that Riak is a system that favors AP with eventual C, this might make some sense to you.
In Riak data is stored in buckets. Those buckets have a number of options and tunable parameters, one of which is whether or not to allow sibling records. By default, a bucket does not allow sibling creation. The Riak Java client is somewhat built around this in that at the most basic level, you can simply say "store this data using this key" and anything that is currently in Riak referenced by that key will be overwritten. There are, however, some issues with attempting to do that.
If you have any type of contention where multiple threads or processes are doing read/modify/write operations on those key/values, you are likely to lose writes if the operations interleave. One will overwrite the other.
With that in mind, the following basic examples illustrate using Riak with the default bucket options and just storing some data.
Basic Example #1: Store a String
Basic Example #2: Store a POJO
Basic Example #3: Changing query parameters
For a more detailed example of how you would store data in Riak in a real environment, jump down to the Advanced Examples section.
## Basic Store, data is a StringUsing the Bucket.store(String, String) method, your String is stored in Riak as bytes representing UTF-8 text
public class App
{
import com.basho.riak.client.IRiakClient;
import com.basho.riak.client.IRiakObject;
import com.basho.riak.client.RiakException;
import com.basho.riak.client.RiakFactory;
import com.basho.riak.client.bucket.Bucket;
public static void main(String[] args) throws RiakException
{
String myData = "This is my data";
riakClient = RiakFactory.httpClient();
Bucket myBucket = riakClient.fetchBucket("TestBucket").execute();
myBucket.store("TestKey", myData).execute();
riakClient.shutdown();
}
}
import com.basho.riak.client.IRiakClient;
import com.basho.riak.client.IRiakObject;
import com.basho.riak.client.RiakException;
import com.basho.riak.client.RiakFactory;
import com.basho.riak.client.bucket.Bucket;
public static void main(String[] args) throws RiakException
{
Pojo myPojo = new Pojo();
myPojo.foo = "My foo data";
myPojo.bar = "My Bar data";
myPojo.foobar = 5;
riakClient = RiakFactory.httpClient();
Bucket myBucket = riakClient.fetchBucket("TestBucket").execute();
myBucket.store("TestKey", myPojo).execute();
riakClient.shutdown();
}
}
<a name="basicexample3"/>
## Store data, changing query parameters for just this request
To override the default parameters in the Bucket, you can specify them prior to calling the execute() method.
```java
public class App
{
import com.basho.riak.client.IRiakClient;
import com.basho.riak.client.IRiakObject;
import com.basho.riak.client.RiakException;
import com.basho.riak.client.RiakFactory;
import com.basho.riak.client.bucket.Bucket;
import com.basho.riak.client.cap.Quora;
import com.basho.riak.client.operations.StoreObject;
public static void main(String[] args) throws RiakException
{
riakClient = RiakFactory.httpClient();
Bucket myBucket = riakClient.fetchBucket("TestBucket").execute();
StoreObject<IRiakObject> storeObject = myBucket.store("TestKey", "TestData");
storeObject.w(Quora.ONE).pw(Quora.ONE).execute();
riakClient.shutdown();
}
}
# The Hard Way ## Eventual Consistency; Resolvers, Mutators, and Converters
In most environments, you're going to configure your buckets to allow siblings and write the code that deals with them. There are three Interfaces you're going to be using:
-
ConflictResolver<T>
This Interface is used to resolve sibling records returned by Riak -
Mutation<T>
This interface is used to modify an object in Riak -
Converter<T>
This interface is used to serialize/deserialize data to/from Riak
One thing worth noting is that the current IRiakClient and its various interfaces aren't what you're likely used to if you've used other datastores' APIs. When using the above classes the current Java client design expects your entire read/modify/write cycle to be encapsulated entirely within the store operation. For more details see the Houston, we have a problem section on the fetching data from Riak page. If you do not wish to completely encapsulate the read/modify/write inside the store operation, see Storing data previously fetched and modified below.
The following diagram outlines the anatomy of a read/modify/write cycle using the Bucket interface and the StoreObject it returns:
### Figure 1  ## Storing data previously fetched and modified _(more to come)_