RedisGears JVM quick start
A quick start to learn how to use RedisGears with Java.
Prerequisites
For this quick start, you need:
- A Redis Enterprise cluster with the RedisGears module and JVM plugin installed and enabled on a database
redis-cli
with connectivity to a Redis database
Tutorial
Create a Maven project
-
Create a new Maven project.
-
Add the following sections to the pom.xml file:
<repositories> <repository> <id>snapshots-repo</id> <url>https://oss.sonatype.org/content/repositories/snapshots</url> </repository> </repositories> <dependencies> <dependency> <groupId>com.redislabs</groupId> <artifactId>gear_runtime</artifactId> <version>0.0.3-SNAPSHOT</version> </dependency> </dependencies>
-
Add example code for either batch processing or event processing to your project's
main
function.
Build a JAR
Use the Maven command-line tool or an IDE plugin to compile and package your code into a JAR file:
$ mvn package
Upload the JAR
Upload your JAR file to a node in the Redis Enterprise cluster. You will need to use the destination filepath when you run your code.
Run RedisGears Java code
Use the RG.JEXECUTE
command to run your code:
$ redis-cli -x -h {host} -p {port} RG.JEXECUTE {package.MainClass} < {filepath}/{JAR name}.jar
GearsBuilder.run()
, RG.JEXECUTE
runs your code immediately.
However, if you use
GearsBuilder.register()
, RG.JEXECUTE
only outputs an OK
message if it registers successfully. Your registered code will run whenever certain database events occur.Example code
You can use these code examples with your own Maven project to try out batch processing or event processing with the RedisGears JVM plugin.
Batch processing
If you use the GearsBuilder.run()
function within your code, then the functions you add to the pipeline will run exactly once when you use RG.JEXECUTE
with your JAR file.
The following example calculates the average rating of all restaurant reviews stored in your database.
Add data to the database
-
Connect to your database with
redis-cli
:$ redis-cli -h <host> -p <port>
-
Add a few review hashes to the database with the
HSET
command:127.0.0.1:12000> HSET review:1 user "Alex L" message "My new favorite restaurant!" rating 5 (integer) 3 127.0.0.1:12000> HSET review:2 user "Anonymous user" message "Kind of overpriced" rating 2 (integer) 3 127.0.0.1:12000> HSET review:3 user "Francis J" message "They have a really unique menu." rating 4 (integer) 3 127.0.0.1:12000> exit
Example code
import java.io.Serializable;
import gears.GearsBuilder;
import gears.readers.KeysReader;
import gears.records.KeysReaderRecord;
public class Reviews implements Serializable
{
private static final long serialVersionUID = 1L;
int count; // Total number of reviews
int ratingsSum; // Sum of all review ratings
// Reviews constructor
public Reviews(int count, int ratingsSum) {
this.count = count;
this.ratingsSum = ratingsSum;
}
public static void main(String args[])
{
// Create the reader that will pass data to the pipe
KeysReader reader = new KeysReader();
// Create the data pipe builder
GearsBuilder<KeysReaderRecord> gb = GearsBuilder.CreateGearsBuilder(reader);
gb.filter(r->{
// Filter out any keys that are not reviews
return r.getKey().startsWith("review:");
}).map(r->{
// Extract the rating field
return r.getHashVal().get("rating");
})
.accumulate(new Reviews(0, 0), (accumulator, record)-> {
// Count the reviews and add up all of their ratings
accumulator.count++;
accumulator.ratingsSum += Integer.parseInt(record);
return accumulator;
}).map(r->{
// Calculate the average rating
return Double.valueOf(((double) r.ratingsSum) / r.count);
});
// Run the data through the pipeline immediately
gb.run();
}
}
Example output
$ redis-cli -x -h {host} -p {port} \
RG.JEXECUTE com.domain.packagename.Reviews < /tmp/rgjvmtest-0.0.1-SNAPSHOT.jar
1) 1) "3.6666666666666665"
2) (empty array)
Event processing
If you use the GearsBuilder.register()
function in your code, then the functions you add to the pipeline will run every time a certain database event occurs.
The following example registers a pipeline of functions to automatically update the maximum age every time you add a new person hash to your database.
Example code
import gears.GearsBuilder;
import gears.readers.KeysReader;
import gears.records.KeysReaderRecord;
public class App
{
public static void main(String args[])
{
// Create the reader that will pass data to the pipe
KeysReader reader = new KeysReader();
// Create the data pipe builder
GearsBuilder<KeysReaderRecord> gb = GearsBuilder.CreateGearsBuilder(reader);
// Only process keys that start with "person:"
gb.filter(r->{
return r.getKey().startsWith("person:");
});
// Compare each person's age to the current maximum age
gb.foreach(r->{
String newAgeStr = r.getHashVal().get("age");
int newAge = Integer.parseInt(newAgeStr);
// Get the current maximum age
String maxAgeKey = "age:maximum";
String maxAgeStr = (String) GearsBuilder.execute("GET", maxAgeKey);
int maxAge = 0; // Initialize to 0
if (maxAgeStr != null) {
// Convert the maximum age to an integer
maxAge = Integer.parseInt(maxAgeStr);
}
// Update the maximum age if a new age is higher
if (newAge > maxAge) {
GearsBuilder.execute("SET", maxAgeKey, newAgeStr);
}
});
// Store this pipeline of functions and
// run them when a new person key is added
gb.register(ExecutionMode.SYNC);
// Note: ExecutionMode defaults to ASYNC
// if you call register() without any arguments
}
}
Example event processing
After you register your code with the RG.JEXECUTE
command, add some data to the database and check the value of age:maximum
to verify that it runs correctly.
-
Connect to your database with
redis-cli
:$ redis-cli -h <host> -p <port>
-
Add a hash that represents a person with
HSET
:127.0.0.1:12000> HSET person:1 name "Alex" age 24 (integer) 2
-
The current value of
age:maximum
should match Alex's age:127.0.0.1:12000> GET age:maximum "24"
-
Add another person with a higher age and then check that
age:maximum
updated automatically:127.0.0.1:12000> HSET person:2 name "Morgan" age 45 (integer) 2 127.0.0.1:12000> GET age:maximum "45"
-
Add a person with a lower age and verify that
age:maximum
did not change:127.0.0.1:12000> HSET person:3 name "Lee" age 31 (integer) 2 127.0.0.1:12000> GET age:maximum "45"