Loading...
Page 1 of 6
Data Caching with Redis
Query
- Collection Scan and Index Scan:
Not possible for everything→ Not feasible for all scenarios.- Also, there are fallbacks.
Thus, there should be another way to handle caching efficiently.
Diagram: Query Flow
flowchart LR
Browser -->|Query App| LocalMachine
LocalMachine --> CacheServer
CacheServer --> MongoDB
CacheServer -->|Has this query been executed before?| CacheServer
CacheServer -->|Store result of query| CacheServer
Caching Query Layer
Redis:
- Redis is an in-memory data structure store used as a database cache and message broker.
Diagram: Redis Caching Layer
flowchart LR
Browser -->|Query App| LocalMachine
LocalMachine -->|MongoDB| Server
Server --> Redis
Redis -->|Server| MongoDB
Node-Redis (Node.js Implementation of Redis)
// Setting values in Redis
set('key', 'value');
// Getting values from Redis
get('key', (err, val) => console.log(val));
Page 2 of 6
Storing Objects in Redis
// Example of storing objects
client.set('key', JSON.stringify({ read: 'topic' }));
client.get('key', (err, val) => console.log(JSON.parse(val)));
Key Data Types:
- Strings only.
- Class Sets and Hashes are also allowed.
MongoDB Queries with Redis Cache
const redis = require('redis');
const redisUrl = "redis://127.0.0.1:6379"; // Redis URL
const client = redis.createClient(redisUrl);
const util = require("util");
client.get = util.promisify(client.get);
const cachedBlogs = client.get(req.user.id); // Fetch cached data
if (cachedBlogs) {
return res.send(cachedBlogs);
} else {
const blogs = await Blog.find({ user: req.user.id });
res.send(blogs);
client.set(req.user.id, JSON.stringify(blogs)); }
Page 3 of 6
Caching Issues
-
Integration:
I don't think this is a good idea→ Better integration with Mongoose's query generation and execution processes.
-
Timeout:
- Cache never expires; add timeout to values assigned to Redis.
set('key', 'value', 'EX', 10); // Expires after 10 seconds -
Cache Keys:
- Generate robust keys for caching.
const key = JSON.stringify({ query: this.getQuery(), collection: this.mongooseCollection.name });
Problem 2
- Use a top-level ID to hash keys or anything specific to the application domain.
Page 4 of 6
Redis Commands Overview
Strings
SET key valueAPPENDGETDELMSET key1 value1 key2 value2
Lists
LINSERT
Hashes
HSET key field valueHGET key fieldHMGETALLHDELHEXISTSHVALUES
Options
- NX → Only set if doesn't exist.
- EX → Expire after seconds.
- PX → Expire after milliseconds.
keepTTL→ Keep expiration (default?).
Numbers
DECR,DECRBY,INCRBYFLOAT,INCR,INCRBY.
Sets
SADD key value→ Add.SREM→ Remove.SMEMBERS→ List all members of the set.SSCAN→ Scan the set.
Page 5 of 6
Set Operations: Union, Intersection, Difference
Commands:
-
SUNION:
key1, key2, key3 -
SINTER:
key1, key2, key3 -
SDIFF:
[key1] key2, key3 -
SSTORE:
[newKey] key1, key2, key3
Membership Commands:
-
SISMEMBER:
[key] value 1 if true, 0 if not -
SMISMEMBER:
[key] value1, value2 (array) -
SCARD:
No. of elements in set
Sorted Sets
Structure:
Hash + Sets (Unique)
key → member → score (integer)
Sorted from least to greatest
Example:
| Key | Member | Score |
|---|---|---|
| key | M1 | Integer Score |
| key | M2 | Integer Score |
| key | M3 | Integer Score |
| key | M4 | Integer Score |
Commands:
-
ZADD:
[key] [score] [member] -
ZSCORE:
[key] [member] → output as score -
ZREM:
[key] [member]
Page 6 of 6
Sorted Set Operations:
-
ZCARD:
[key] → No. of elements -
ZCOUNT:
[key] [score1] [score2] No. of elements in range If no equals sign: -inf +inf -
ZPOPMIN:
[key] [count] → No. of elements to pop -
ZPOPMAX:
[key] [count] → No. of elements to pop -
ZINCRBY:
[key] [count] [member] -
ZRANGE:
[key] [index1] [index2] [WITHSCORES] - 0-indexed - Includes [index2]
Additional Options for ZRANGE:
-
REV:
→ reverse order -
LIMIT:
→ skip, output count
References & Related Topics
- Redis Official Documentation
- Node.js Redis Library
- Mongoose Documentation
- Advanced Node.js Techniques for Caching