The Beginner’s Guide to Hazelcast Part 5

Standard

This is a continuation of a series of posts I have written about Hazelcast.  I highly suggest you read the other ones: Part 1, Part 2, Part 3 and Part 4.

Things That Makes One Go “Huh?”

This post will have no Hazelcast specific code in it.  Let me repeat that.  This post will have no Hazelcast specific code in it.  That is because the fine folks at Hazelcast produced a product that implements different standards.  This allows for a choice of clients.  One of those standards that Hazelcast implements is memcached.

What about JCache?

JCache (JSR 107) is just for Java.  Memcached protocol clients have been implemented across several languages so one is not nailed down to one language.  Implementing the memcached protocol was a smart move in my opinion because it makes Hazelcast more than a “Java thing.”

Why Use Hazelcast?

Excellent question!  If one can use any memcached server, why use Hazelcast.  Well, to tell you the truth, unless one is sharing a database between several servers, one may not even need caching!  If one does need a caching solution, here is why I would choose Hazelcast:

  1. Automatic, real time backups – I have not read of one Hazelcast datatype that is not backed up at least once.  Just stand up two instances, one off machine from the other, to get the full benefit.
  2. Security – If the servers that need to cache are across different networks, then the firewall rules can be easier with Hazelcast.  Lets say n servers are needing to cache data and n/2 of them are on the 192.168.1.x network and the other n/2 are on the 10.10.1.x network.  By setting one Hazelcast instance on either network, all n machines can be sharing a cache.  The Hazelcast instances can be configured to talk to just the instance on the other side.  That makes the firewall rule writer job easier because there only has to be a rule made for two servers rather than n machines  then the 192.168.1.x machines just talk to their Hazelcast node and the 10.10.1.x machines just talk to their Hazelcast node and let the Hazelcast instances do the rest of the work.

Example

I never like to show just a “ho hum” kind of example so I am going to show how a Java client can share data with a Python client.

Setup

I am using Java 1.7 and Python 3.4.  Unfortunately, neither language has memcached support out of the box so I went looking for already written clients.

Java

I found Spymemcached for Java.  I will be just skimming the surface of its abilities. It can be grabbed from Maven.  Here is the pom.xml file for the project:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <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">
 3     <modelVersion>4.0.0</modelVersion>
 4     <groupId>com.darylmathison</groupId>
 5     <artifactId>Memcache</artifactId>
 6     <version>1.0-SNAPSHOT</version>
 7     <packaging>jar</packaging>
 8     <properties>
 9         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
10         <maven.compiler.source>1.7</maven.compiler.source>
11         <maven.compiler.target>1.7</maven.compiler.target>
12     </properties>
13     <build>
14         <plugins>
15             <plugin>
16                 <groupId>org.apache.maven.plugins</groupId>
17                 <artifactId>maven-compiler-plugin</artifactId>
18                 <version>2.3.2</version>
19                 <configuration>
20                     <showDeprecation>true</showDeprecation>
21                 </configuration>
22             </plugin>
23             <plugin>
24                 <groupId>org.codehaus.mojo</groupId>
25                 <artifactId>exec-maven-plugin</artifactId>
26                 <version>1.3.2</version>
27                 <executions>
28                     <execution>
29                         <goals>
30                             <goal>java</goal>
31                         </goals>
32                     </execution>
33                 </executions>
34                 <configuration>
35                     <mainClass>com.darylmathison.memcache.Main</mainClass>
36                 </configuration>
37             </plugin>
38         </plugins>
39     </build>
40     <dependencies>
41         <dependency>
42             <groupId>net.spy</groupId>
43             <artifactId>spymemcached</artifactId>
44             <version>2.11.5</version>
45         </dependency>
46     </dependencies>
47 </project>

Python

Next, I found python3-memcached for Python. It uses the classic setup.py procedure to install.

Server

Not much of a cache if the server is missing. One can download Hazelcast at hazelcast.org/download, extract the contents, cd into the bin directory and run the server.bat or server script according to one’s OS. As setting up servers go, that is the easiest one I have ever done.

Situation

The “expensive” operation that I am trying to make cheaper is Fibonacci numbers. Because Python and Java can both understand unicode, the values are stored as unicode strings. The key is a unicode string of the number of the sequence or the number of rounds it takes to get there.

Code

Java

package com.darylmathison.memcache;

import java.io.IOException;
import java.net.InetSocketAddress;
import net.spy.memcached.MemcachedClient;

/**
 *
 * @author Daryl
 */
public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        try {
            MemcachedClient client = new MemcachedClient(new InetSocketAddress("localhost", 5701));
            for(int i = 2; i < 20; i++) {
                System.out.println("value of round " + i + " is " + fibonacci(i, client));
            }
            client.shutdown();
        } catch(IOException ioe) {
            ioe.printStackTrace();
        }
    }
    
    private static long fibonacci(int rounds, MemcachedClient client) {
        String cached = (String)client.get(String.valueOf(rounds));
        if(cached != null) {
            System.out.print("cached ");
            return Long.parseLong(cached);
        }
        
        long[] lastTwo = new long[] {1, 1};
        
        for(int i = 0; i < rounds; i++) {
            long last = lastTwo[1];
            lastTwo[1] = lastTwo[0] + lastTwo[1];
            lastTwo[0] = last;
        }
        
        client.set(String.valueOf(rounds), 360, String.valueOf(lastTwo[1]));
        return lastTwo[1];
     }
}

Python

Here is the Python client. As a pythonian, I tried to be as pythonic as possible.

import memcache

client = memcache.Client(['localhost:5701'])

def fibonacci(round):
    f = [1, 1, 1]
    
    for i in range(round):
        f[-1] = sum(f[:2])
        f[0], f[1] = f[1], f[2]
        
    return f[2]

def retrievefib(round):
    fib = client.get(str(round))
    if not fib:
        fib = fibonacci(round)
        client.set(str(round), str(fib))
    else:
        print("cached")
        
    return fib

def main():
    store = [ x for x in range(20) if x % 2 == 0]
    for i in store:
        retrievefib(i)
    
    for i in range(20):
        print(retrievefib(i))

if __name__ == "__main__":
    main()

Conclusion

Well, here is an example of Hazelcast as being the powerhouse behind the scenes. This is a place where I think it shines the most. One doesn’t have to create whole new crafty, distributed applications to take advantage of Hazelcast. All one has to do is use known practices and let Hazelcast do the hard work. The source for this post can be found here for the Java code and here for the Python code.

References

http://en.wikipedia.org/wiki/Fibonacci_number
https://code.google.com/p/spymemcached/
https://pypi.python.org/pypi/python3-memcached/1.51

Advertisements

Three Ways to Solve a Problem

Standard

Introduction

I wanted to show the differences of three different languages.  I made a palindrome detector with Java, Groovy and Python.  Technically the Python I used is CPython so it is not Java but JPython runs in the JVM so I am counting it as a Java related language.  Groovy is Java related because as of Java 1.6 and later, Groovy natively runs on the JVM.  Since this is a Java blog, Java had to be one of the languages used.  I will point out differences and similarities when all of the solutions are posted.  This will not be a explaination of each language.  There are many excellent resources out there.  For example, one place I find myself at a lot is http://www.python.org.  Another site I found myself for this post is http://groovy.codehaus.org/.

Solutions (code)

Requirements

The solution must analyze a string and see if it is a palindrome.  A palindrome is a word or phrase, that spelled the same forwards and backwards.  For example, 123321 is a palindrome.  Two strings will be used to test the solution, “123321” and “1234321.”  This covers the case of a palindrome with an odd number of characters and a even number of characters,  The solution returns the equivalent of a true when a palindrome is detected and the equivalent of false when one is not detected.

Java

public class Palindrome {

private static boolean isPalindrome(String testString) {

String firsthalf;

StringBuilder secondhalf;

int firstHalfIndex;

int secondHalfIndex;

int length = testString.length();

if(length % 2 == 0) {

firstHalfIndex = (int)(length/2);

firsthalf = testString.substring(0, firstHalfIndex);

secondhalf = new StringBuilder(testString.substring(firstHalfIndex));

} else if ( length % 2 == 1) {

firstHalfIndex = (int)(length/2);

secondHalfIndex = firstHalfIndex + 1;

firsthalf = testString.substring(0, firstHalfIndex);

secondhalf = new StringBuilder(testString.substring(secondHalfIndex));

} else {

firsthalf = “”;

secondhalf = new StringBuilder();

}

return firsthalf.equals(secondhalf.reverse().toString());

}

public static void main(String[] argv) {

System.out.println(isPalindrome(“123321”));

System.out.println(isPalindrome(“1234321”));

}

}

Groovy

def isPalindrome(testString){

def firsthalf

def secondhalf

def firstHalfIndex

def secondHalfIndex

if (testString.length() % 2 == 0) {

firstHalfIndex = testString.length()/2

firsthalf = testString[0..<firstHalfIndex]

secondhalf = testString[firstHalfIndex..<testString.length()]

} else if(testString.length() % 2 == 1) {

firstHalfIndex = testString.length()/2

firsthalf = testString[0..<firstHalfIndex]

secondHalfIndex = firstHalfIndex + 1

secondhalf = testString[secondHalfIndex..<testString.length()]

}

firsthalf == secondhalf.reverse()

}

println isPalindrome(“123321”)
println isPalindrome(“1234321”)

Python

def isPalindrome(test_string):

length = len(test_string)

first_half = None

second_half = None

if length % 2 == 0:

first_half_index = int(length/2)

first_half = test_string[:first_half_index]

second_half = test_string[first_half_index:]

elif length % 2 == 1:

first_half_index = int(length/2)

second_half_index = first_half_index + 1

first_half = test_string[:first_half_index]

second_half = test_string[second_half_index:]

return first_half == second_half[::-1]

def main():

print(isPalindrome(“123321”))

print(isPalindrome(“1234321”))

if __name__ == “__main__”:

main()

Thoughts

Similarities

What I found was the same was how easily it was to implement the same solution in three different languages.  Each one did it in their own idiom but it was done.  Each had the ability to figure out the length of the string, split the string by an index and reverse the string.  I am a sucker for slices so Groovy and Python were more fun for me.

Differences

I wasn’t aware of this before I started hitting the blogosphere but one of the complaints of Java is that it is too wordy.  Doing this exercise really exposed me to the wordiness of Java.  Groovy did the same work without having to use a StringBuilder to do a string reverse.  The only reason I did a main on the Python solution is because that is a way to be able to use a file as a library and be a standalone script (It is a Python “idiom” I once read.).  The concept of slices really made the code look neat and tidy for me.  Did I mention I am a sucker for slices? The Groovy reverse extension to Strings was really nice.  Being able to reverse the string with a slice was really cool in Python.

Conclusion

In this post, I compared three languages implementing the same solution.  While the problem was simple, each language succeeded in its own way.