Redis Data Types

Redis supports multiple data types, including strings, lists, sets, and hashes. Each data type has its own set of operations that can be performed on it, making Redis a fast and versatile data store for high-performance applications. Redisson makes it easy for Java developers to interact with Redis by implementing familiar interfaces for Redis data types.

Redisson also features extra methods not provided by the Redis API, which are implemented via custom Lua scripts executed on the Redis side. Some Redis data types are even implemented in more than one Redisson interface, giving developers flexibility in how their apps work with Redis.

Here's a look at Redis data types and the corresponding Redisson interfaces available to Java developers. 

String: RBucket and RBinaryStream

A string is a sequence of bytes and the most fundamental Redis data type. Strings can store text in various encodings, raw binary data, and serialized objects, with a maximum length of 512 megabytes per string. Common uses for strings are caching, counters, storing session data associated with user IDs, and basic key-value storage.

Redisson's RBucket is a Java implementation of the ObjectHolder class, which is suitable for working with strings. Thanks to the many codecs provided with Redisson, it can serialize any type of object into the binary-safe strings used by Redis. RBucket provides methods to set, get, and delete strings. In this example, the string "anyObject" is set to the bucket named "anyObject" and then retrieved:

RBucket bucket = redisson.getBucket("anyObject");
bucket.set(new AnyObject(1));
AnyObject obj = bucket.get();

RBucket also supports asynchronous and reactive interfaces for setting, getting, and deleting strings. RBuckets can also be used to store multiple key-value pair strings at once.

The Redisson RBinaryStream interface extends the RBucket interface and provides methods to set, get, and update a stream of bytes. RBinaryStream is suitable for larger amounts of string data, such as a log file or an image. This Java code example sets a string value with RBinaryStream:

RBinaryStream stream = redisson.getBinaryStream("anyStream");
byte[] content = "This is a string".getBytes();
stream.set(content);

List: RList, RQueue, RDeque

In Redis, a list is a collection of strings sorted by insertion order. Lists maintain their order, but elements can be inserted or removed from both ends of a list. This makes lists flexible enough to be used for last-in-first-out (LIFO) or first-in-first-out (FIFO) operations. It's also possible to access and manipulate ranges within a list.

Redisson offers multiple interfaces for working with lists, including the RList class. Here's how RList can retrieve the elements in a list of key-value pairs:

RList myList = redisson.getList("myList");
myList.add("item1");
myList.add("item2");
myList.add(0, "item0"); // Add at the beginning

String firstItem = myList.get(0); 

RQueue implements distributed queues in Redisson, making it ideal for the FIFO principle where processing order is critical:

RQueue taskQueue = redisson.getQueue("taskQueue");
taskQueue.add("task1");
taskQueue.add("task2");

String nextTask = taskQueue.poll(); // Retrieves and removes the head

RDeque refers to the concept of a double-ended queue. This implementation has features of both stacks and queues, making it easy to add or remove elements from either end of a list:

RDeque messageDeque = redisson.getDeque("messageDeque");
messageDeque.addFirst("message1"); // Add to the head
messageDeque.addLast("message2"); // Add to the tail

String latestMessage = messageDeque.pollFirst(); // Remove from the head
String oldestMessage = messageDeque.pollLast(); // Remove from the tail

Set: RSet

Whereas a list is an ordered group of elements, a set is an unordered collection of unique strings. Since each element within a set must be unique, duplicates are automatically discarded. Redis supports a number of standard data set operations like union, intersection, and difference, making this data type a powerful way to filter or combine data.

RSet is Redisson's implementation for working with Redis sets. It seamlessly integrates all the Redis set operations within a familiar Java interface. For example, here's how you can create a set and add elements to it with RSet:

RSet mySet = redisson.getSet("mySet");
mySet.add("apple");
mySet.add("banana");
mySet.add("orange");

Here's how to see if an element is a member of the set, and check the element's size:

boolean containsApple = mySet.contains("apple"); // true
int setSize = mySet.size(); // 3

Redisson and RSet simplify set operations like union and intersection like this:

RSet otherSet = redisson.getSet("otherSet");
otherSet.add("orange");
otherSet.add("grape");

RSet unionSet = redisson.getSet("unionSet");
unionSet.union("mySet", "otherSet"); // apple, banana, orange, grape

RSet intersectionSet = redisson.getSet("intersectionSet");
intersectionSet.intersection("mySet", "otherSet"); // orange

Sorted Set: RSortedSet and RLexSortedSet

The Redis sorted set data type, also known as a zset, is a collection of unique strings associated with floating-point scores. The set is ordered based on the scores of each set member, making sorted sets perfect for working with ranked data, including leaderboards and priority queues. Among the many ways Redis can work with sorted sets, you can perform queries to retrieve set members within a specific range of scores or rankings.

Redisson's RSortedSet mirrors the standard Java SortedSet interface. For example, this Java code could be used to create a leaderboard set with members and scores:

RSortedSet leaderboard = redisson.getSortedSet("leaderboard");
leaderboard.add(100.5, "Alice");
leaderboard.add(85.2, "Bob");
leaderboard.add(92.8, "Charlie");

And then to retrieve ranked members:

Collection top3Players = leaderboard.range(0, 2); // Alice, Charlie, Bob

The RLexSortedSet interface is a variant of RSortedSet where members are ordered lexicographically (as in a dictionary) instead of by scores. Here's how to create this type of sorted set and retrieve members that fall within a specific lexicographic range:

RLexSortedSet words = redisson.getLexSortedSet("words");
words.add("apple");
words.add("banana");
words.add("orange");

Collection range = words.lexRange("banana", "orange"); // banana, orange

Hash: RMap

In Redis, a hash stores a collection of field-value pairs. In this data type, both fields and values are strings. You can think of a hash as a dictionary, where each field maps to a corresponding value. Hashes store data as key-value pairs, similar to how maps work in programming languages.

RMap is Redisson's map implementation that seamlessly interfaces with Redis hashes via the familiar Java Map interface. For example:

RMap users = redisson.getMap("users");
users.put("user123", new User("Alice", 30));
users.put("user456", new User("Bob", 25));

This code establishes an RMap linked to the Redis key "users." Each entry is a key-value pair, where the key (for example, "user123") is the field in the Redis hash, and the value is a User object representing the data associated with that field.

To retrieve values with RMap:
User alice = users.get("user123");
System.out.println(alice.getName()); // "Alice"
System.out.println(alice.getAge());  // 30

And to update values:

alice.setAge(31);
users.put("user123", alice); // Update Alice's age in the hash

Stream: RStream

Redis streams are designed to handle real-time event data. A stream functions much like an append-only log but with added features. In fact, it's common to use the stream data type as an append-only log. However, streams are also perfect for scenarios where each event is automatically assigned a unique ID, such as a combination of a timestamp and a sequence number.

RStream is Redisson's Java-friendly interface for Redis streams. It provides methods for adding, reading, grouping, and acknowledging stream events. To establish an RStream with "chat" as the stream's key in Redis:

RStream chatStream = redisson.getStream("chat");
chatStream.add(new StreamMessageId("0-1"), Map.of("user", "Alice", "message", "Hello!"));
chatStream.add(new StreamMessageId("0-2"), Map.of("user", "Bob", "message", "Hi Alice!"));

Events are added to the stream using the standard Java add(). To read stream events:

// Read all events from the beginning
Map> allEvents = chatStream.read(StreamMessageId.NEWEST);

// Read from a specific group  
StreamReadGroupArgs args = StreamReadGroupArgs.of("group1", "consumer1").count(2);
Map> groupEvents = chatStream.readGroup(args);

Geospatial Indexes: RGeo

A geospatial index isn't technically a data type. But as a feature based on sorted sets, it provides unique functionality and can be considered an unofficial data type. Geospatial indexes allow developers to store, manipulate, and query spatial data based on geographic coordinates expressed in longitude and latitude. Each entry in the index is a combination of a name (such as a city or location ID) and the geographic coordinates.

RGeo is Redisson's interface that streamlines geospatial indexes for Java developers. To add a location in Java:

RGeo cities = redisson.getGeo("cities");
cities.add(37.7749, -122.4194, "San Francisco");
cities.add(40.7128, -74.0060, "New York");

RGeo also provides intuitive options for searching geospatial data. For example, this Java code will find locations within the specified radius, 500 kilometers around San Francisco:

GeoRadiusArgs args = GeoRadiusArgs.inKilometers(500).withCoordinates();
GeoResults> results = cities.radius("San Francisco", args);

for (GeoEntry entry : results) {
  System.out.println(entry.getMember() + ": " + entry.getDistance());
}

You can also calculate distances, such as the distance in kilometers between San Francisco and New York:

double distance = cities.dist("San Francisco", "New York", GeoUnit.KILOMETERS);
System.out.println("Distance: " + distance + " km");

Bitmap: RBitSet

Strictly speaking, bitmaps also aren't Redis data types. However, since they provide a specialized way to work with strings in Redis, they serve the same function as official data types. A bitmap essentially treats a string as an array of bits — 0s and 1s. Bitmaps are thus very efficient with system memory and storage space, making them perfect for boolean (true/false) data at large scales. You can also perform the standard bitwise operations on multiple bitmaps: AND, OR, XOR, and NOT.

RBitSet is Redisson's implementation of the Java BitSet class, providing developers with Java's familiar bitwise operations. Here's a simple bitmap with user flags, which can track logins and other activity:

RBitSet userFlags = redisson.getBitSet("userFlags");
userFlags.set(5);   // Set the 6th bit (index 5) to 1
userFlags.set(100); // Set the 101st bit to 1

Here's an example of how RBitSet makes it easy to perform bitwise operations on a Redis bitmap in Java code:

// ... set bits in otherFlags
RBitSet otherFlags = redisson.getBitSet("otherFlags");

userFlags.and(otherFlags); // Bitwise AND
userFlags.or(otherFlags);  // Bitwise OR
userFlags.xor(otherFlags); // Bitwise XOR

To learn more about Redisson and how it simplifies working with Redis data types in Java, visit the Redisson website today.

Similar terms