In Part 1 of this two-part blog series, we saw how to go beyond basic caching with GridGain 8. Part 1 discussed why people start with Redis and the challenge Redis brings, the Redis and GridGain designs, and then mapping Redis to GridGain 8. Since GridGain version 8 and 9 differ significantly in their architecture and classes, it’s best to have these in two separate blogs.
GridGain 9: Modern Table-Centric API
Now, GridGain 9 introduces a modern table-centric API which consists of the “Tuple” type at the core. A Tuple is a lightweight container for representing a row in a table as a collection of key-value pairs, where each entry corresponds to a column name and its value. You can think of Tuple as the universal data representation in GridGain 9 where every record in a table can be accessed as a Tuple. GridGain 9 gives you the flexibility to work with data at different abstraction levels:
KeyValueView: It lets you split a Tuple into key and value parts, useful for Redis-like key-value semantics.
KeyValueView<Tuple, Tuple> kv = client.tables().table("users").keyValueView();
kvView.put(null, key, value);
value = kvView.get(null, key);RecordView: It gives you direct access to the whole row as a Tuple. Consider it as row-level, relational-style operations
RecordView<Tuple> recordView = client.tables().table("users").recordView();
recordView.insert(null, newUser);
Tuple userTuple = recordView.get(null, newUser);Wondering what these null parameters are? It is the transaction context parameter in GridGain 9 API. By passing null, each operation is auto-committed. When an operation is a part of a bigger transaction, you pass a Transaction object instead of null. All the operations tied to that transaction are grouped together and committed/rolled back atomically.
POJO mappings: It lets you bypass generic Tuple objects by binding rows directly to your Java classes, providing compile-time type safety.
You may also want to try out this GitHub repo that brings Redis-style commands to Apache Ignite 3. It provides functions named after the corresponding Redis operations, with GridGain 9 functionality neatly wrapped inside - so you can experiment using familiar Redis syntax while working with GridGain.
String Operations
Let us see how we can model Redis String operations. In this blog, I will use GridGain (or SQL!) kinds of nomenclature for keys now.
// Redis SET user:123 equivalent
Tuple key = Tuple.create().set("key", "u123");
Tuple value = Tuple.create().set("val", "John Doe");
kvView.put(null, key, value);
// Redis GET equivalent
Tuple retrievedValue = kvView.get(null, key);
String result = retrievedValue.stringValue("val");
// Redis EXISTS equivalent
boolean exists = kvView.contains(null, key);
// Redis DEL equivalent
boolean removed = kvView.remove(null, key);Hashing
While simple strings cover the most basic key-value use cases, Redis hash lets you store multiple field-value pairs under a single key. In GridGain 9, this maps neatly onto a table row where the key identifies the hash, and the fields map either to columns in a Tuple or properties of a POJO. By moving from SET/GET to HSET/HGET, we can see how GridGain’s KeyValueView with POJO mapping provides a clean, type-safe way to model Redis hashes.
// Redis HSET equivalent: HSET user:123 name "John Doe"
Tuple nameKey = Tuple.create()
.set("hash_name", "u123")
.set("field", "name");
Tuple nameValue = Tuple.create().set("value", "John Doe");
kvView.put(null, nameKey, nameValue);
// Redis HGET equivalent: HGET user:123 name
Tuple retrievedName = kvView.get(null, nameKey);
String name = retrievedName.stringValue("value");
// Redis HEXISTS equivalent: HEXISTS user:123 name
boolean nameExists = kvView.contains(null, nameKey);
// Redis HDEL equivalent: HDEL user:123 age
boolean ageRemoved = kvView.remove(null, ageKey);Ordered Collections
Redis also supports ordered collections where insertion order matters. That’s where lists come in. Lists are widely used for queues, logs, and task pipelines because they preserve ordering and allow operations like LPUSH, RPUSH, and LRANGE. In GridGain 9, this structure maps well onto a RecordView, where each list element is stored as a row with an index or sequence column to maintain order. By using range queries, we can efficiently retrieve list slices just like Redis’ LRANGE.
You can model a list or queue in GridGain 9 using a table with a sequence number:
CREATE SEQUENCE IF NOT EXISTS ascendingSequence INCREMENT BY 1 START 0;
CREATE SEQUENCE IF NOT EXISTS descendingSequence INCREMENT BY -1 START 1;
CREATE TABLE IF NOT EXISTS Person (
id bigint default NEXTVAL('ascendingSequence') primary key ,
city_id bigint,
name varchar,
age int,
company varchar
);
--RPUSH
INSERT INTO Person (city_id, name, age, company) values (1, 'John', 30, 'newCorp'), (2, 'Jane', 24, 'oldCorp')Since id is bound to ascendingSequence, if we don’t explicitly provide id, the ascendingSequence will be used. We need to explicitly call NEXTVAL('descendingSequence') for LPUSH inserts.
--LPUSH
INSERT INTO Person (id, city_id, name, age, company)
VALUES (NEXTVAL('descendingSequence'), 2, 'Bob', 35, 'CorpB');LPOP and RPOP can be modelled using MIN(id) and MAX(id) respectively in the WHERE clause in the DELETE query.
Redis Set
Modelling Redis Set is very straightforward. The PRIMARY KEY constraint prevents duplicate entries, so you can use simple INSERT to add items to the set.
CREATE TABLE set_entries (
entry STRING PRIMARY KEY
);
-- SADD
INSERT INTO set_entries VALUES ('entry1'), ('entry2');
-- SMEMBERS
SELECT entry FROM set_entries;
-- SISMEMBER
SELECT 1 FROM set_entries WHERE entry = 'entry1';You can extend the same table to hold multiple sets by simply adding one more column as set_name and all the WHERE clauses to have set_name.
Sorted Set
Redis SortedSet can be implemented similarly, with an additional field of score.
CREATE TABLE zset_entries (
entry STRING PRIMARY KEY
score Double
);
CREATE INDEX idx_zset_score ON zset_entries(score);
-- ZADD key score member
INSERT INTO zset_entries VALUES (200, 'entry1'), (100,'entry2');
-- ZSCORE key member
SELECT score FROM zset_entries WHERE entry = 'entry1';
-- ZRANGE 0 -1 WITHSCORE
SELECT * FROM zset_entries ORDER BY score DESC';Redis Streams
Redis Streams (commands like XADD, XREAD) act more like Kafka-style event logs, where events are persisted and can be replayed. We can model them in GridGain 9 in the same way as we did in GridGain 8, using Continuous Query. GridGain also provides Kafka-style functionality through the Data Streamer API. The Data Streamer lets you ingest large amounts of data into your cluster quickly and reliably, distributing it across the cluster while supporting batching, retries, and auto-flush intervals through configuration options like DataStreamerOptions. This makes it suitable for high-throughput ingestion pipelines, ETL jobs, or real-time analytics.
Conclusion
As seen in this blog series, the functionality of Redis data structure can be achieved in GridGain, even though it is not a mere data structure server. The architectural shift provides a foundation for massive scalability. When your use case evolves to require complex SQL queries, real-time analytics on joined datasets, or distributed ACID transactions, GridGain offers an expanded set of tools to meet those demands. It’s not just an alternative for a few commands; it’s a platform that takes your data structures and empowers them with the full capabilities of a truly distributed, in-memory computing platform.