Why You Should Use Amazon DynamoDB

Yesterday I went to PHP meetup in New York City to learn about Amazon DynamoDB (NoSQL). The presenter was Siva Raghupathy – an AWS Enterprise Solutions Architect. He guides developers and architects to build DynamoDB at Amazon. It was cool to learn about DynamoDB from one of the team lead on the project. It was a very informative meeting and I hope I can get presentation slides later on.

Here are the main reasons why I would consider using DynamoDB for my projects – as long as I am ok with NoSQL limitations as well as some tips and tricks of using it:

  • Zero Administration. Database provisioning, installation, configuration and tuning now done by Amazon. All you care about is to specify number of read/writes per second you may need. Everything else will be taken care of. I was able to create database and be ready to work with it in couple minutes. No army of ops and DB Admin needed
  • Reliability. When write operation happens, the system automatically writes into couple to servers located at different data centers. In case one data center lost connectivity, you are safe to get data from another.
  • Predictable, small latency. If you hosting your application on AWS infrastructure, then latency is very small, 10 ms or so. Make perfect sence for applications hosted on AWS infrastructure.
  • You can backup you data to Amazon S3
  • It is cheaper to delete the whole table that to delete individual records. Delete operation count toward your write allowances. Let say you want to hold log data for each month for a year. At the end of the months you want to process all month data and remove it from the database. It would be cheaper to create for example 12 tables to hold month’s worth of data, code to use use new table every month, and when you done with the table, simply delete it.
  • Ability to increase scalability almost on the fly. When you read/writes counter is about 80%, system will issue alert so you can increase capacity by simply dial up the numbers. System will provision additional resources for you
  • SDK available for all major programming languages. System respond to HTTPS REST API calls, but language SDK make it more convenient to program against DynamoDB.

Amazon DynamoDB Overview, a fully managed NoSQL database service.

To start with dynamoDB you can create table using AWS Console.
Provisioning table step 1.


Provisioning table step 2.

Provisioning table step 3.

Let see how we can accomplish simple database manipulation with DynaoDB and amazon AWS SDK for Java.
If you use maven, here is simple pom file to bootstrap your project. Spock is a groovy BDD framework for testing only:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
        http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>DynamoDB</groupId>
    <artifactId>DynamoDB</artifactId>
    <version>1.0</version>

     <dependencies>

             <dependency>
             	<groupId>com.amazonaws</groupId>
             	<artifactId>aws-java-sdk</artifactId>
             	<version>1.3.2</version>
             </dependency>

         <dependency>
         	<groupId>org.spockframework</groupId>
         	<artifactId>spock-maven</artifactId>
         	<version>0.6-groovy-1.8</version>
             <scope>test</scope>
         </dependency>

     </dependencies>
</project>

Below is a simple test cases I wrote using Spock framework to check out Amazon Dynamo DB. I left them as a java code in case you want to copy it into JUnit or other Java test framework or into main method:

package dynamo;
import spock.lang.Specification
import com.amazonaws.auth.PropertiesCredentials
import com.amazonaws.auth.AWSCredentials
import com.amazonaws.services.dynamodb.AmazonDynamoDBClient
import com.amazonaws.services.dynamodb.model.DescribeTableRequest
import com.amazonaws.services.dynamodb.model.DescribeTableResult


import com.amazonaws.services.dynamodb.model.PutItemRequest
import com.amazonaws.services.dynamodb.model.PutItemResult
import com.amazonaws.services.dynamodb.model.AttributeValue
import com.amazonaws.services.dynamodb.model.GetItemResult
import com.amazonaws.services.dynamodb.model.Key
import com.amazonaws.services.dynamodb.model.GetItemRequest
import com.amazonaws.services.dynamodb.model.AttributeValueUpdate
import com.amazonaws.services.dynamodb.model.AttributeAction
import com.amazonaws.services.dynamodb.model.UpdateItemRequest
import com.amazonaws.services.dynamodb.model.ReturnValue
import com.amazonaws.services.dynamodb.model.UpdateItemResult


class DynamoDBSpec extends Specification {
    File file = new File('/Users/edvorkin/AwsCredentials.properties')
    AWSCredentials credentials = new PropertiesCredentials(file);
    def dynamoDB = new AmazonDynamoDBClient(credentials);


    def "Saving item to DynamoDB"() {
        given: "Table named Sessions exist in DynamoDB and configured with 
                       Hash key named token"
            String tableName = "Sessions";
            String token = "123-13-123";
            String website = "Facebook.com";
    
            DescribeTableRequest request = new DescribeTableRequest()
                    .withTableName("Sessions");
            DescribeTableResult result = dynamoDB.describeTable(request);
            String status = result.getTable().getTableStatus();
            assert status == 'ACTIVE'

        when: "Create and Save Item to dynamoDB"
            Map<String, AttributeValue> sessionRequest = new HashMap<String, AttributeValue>();
            sessionRequest.put("token", new AttributeValue().withS(token));
            sessionRequest.put("targetUrl", new AttributeValue().withS(website));
    
            // Add an item
            PutItemRequest putItemRequest = new PutItemRequest(tableName, sessionRequest);
            PutItemResult putItemResult = dynamoDB.putItem(putItemRequest);
    
            // read item back from Dynamo DB
    
            GetItemRequest getItemRequest = new GetItemRequest()
                    .withTableName(tableName)
                    .withKey(new Key()
                    .withHashKeyElement(new AttributeValue().withS(token)));
    
            GetItemResult results = dynamoDB.getItem(getItemRequest);
            Map<String, AttributeValue> awsMap = results.getItem();


        then:
            awsMap.get("targetUrl").s == website
    }

Updating items in DynamoDB:

def "Testing Updated in DynamoDB"() {
        given: "Item Exist in DynamoDB, add new attributes and update existing"
            String tableName = "Sessions";
            String token = "456-456-456";
            String website = "Amazon.com";
            String visitors="233433"
            String newsite="google.com"
            Map<String, AttributeValue> sessionRequest = new HashMap<String, AttributeValue>();
            sessionRequest.put("token", new AttributeValue().withS(token));
            sessionRequest.put("website", new AttributeValue().withS(website));

            // Add an item
            PutItemRequest putItemRequest = new PutItemRequest(tableName, sessionRequest);
            PutItemResult putItemResult = dynamoDB.putItem(putItemRequest);

        when: "Updating item"
            Map<String, AttributeValueUpdate> updateItems = 
                new HashMap<String, AttributeValueUpdate>();

         // update data
               updateItems.put("visitors",
                 new AttributeValueUpdate()
                        .withAction(AttributeAction.PUT)
                        .withValue(new AttributeValue().withN(visitors)));

        updateItems.put("website",
                         new AttributeValueUpdate()
                                .withAction(AttributeAction.PUT)
                                .withValue(new AttributeValue().withS(newsite)));


        // update items DynamoDB
        UpdateItemRequest updateItemRequest = new UpdateItemRequest()
            .withTableName(tableName)
            .withKey(new Key()
            .withHashKeyElement(new AttributeValue().withS(token)))
            .withReturnValues(ReturnValue.UPDATED_NEW)
            .withAttributeUpdates(updateItems);

        UpdateItemResult updateResult = dynamoDB.updateItem(updateItemRequest);

    // read item back from Dynamo DB
    
            GetItemRequest getItemRequest = new GetItemRequest()
                    .withTableName(tableName)
                    .withKey(new Key()
                    .withHashKeyElement(new AttributeValue().withS(token)));
    
            GetItemResult results = dynamoDB.getItem(getItemRequest);
            Map<String, AttributeValue> awsMap = results.getItem();
        
    then:
        updateResult.attributes.get("website").s==newsite
        awsMap.get("website").s==newsite
        awsMap.get("visitors").n== visitors
    }

There is much more into DynamoDB that this simple samples. Hashing, range querying and other features I will explore in following post as I learn more about DynamoDB. So far I was able to create an application and move it to production with confident that my data is safe, available, redundant and fast.

Where to go from there:

Submit a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>