Redis data types and use cases

Redis data types and use cases with examples in nodejs.

String

// Caching API response
await redis.set("user:123:profile", JSON.stringify({ name: "Andy", age: 30 }), "EX", 60); // expire in 60s
const profile = JSON.parse(await redis.get("user:123:profile"));
console.log(profile);

// Counter
await redis.incr("page:views");
const views = await redis.get("page:views");
console.log("Views:", views);

// Fixed Window Rate Limiting
async function isAllowed(userId) {
  const key = `rate:${userId}:${Math.floor(Date.now() / 60000)}`; // per minute window
  const count = await redis.incr(key);
  if (count === 1) {
    await redis.expire(key, 60); // expire after 60s
  }
  return count <= 5; // allow max 5
}

// Distributed Lock
async function lock(key, ttl) {
  const lockKey = `lock:${key}`;
  const lockValue = Date.now() + ttl;
  const acquired = await redis.set(lockKey, lockValue, "EX", ttl, "NX");
  return acquired === "OK";
}

// Transaction
await redis.multi()
  .set("key1", "value1")
  .set("key2", "value2")
  .exec();

// Optimistic Locking
async function transfer(from, to, amount) {
  let success = false;

  while (!success) {
    await redis.watch(from, to); // watch keys
    const balance = parseInt(await redis.get(from), 10);
    if (balance < amount) {
      await redis.unwatch();
      throw new Error("Insufficient balance");
    }
    const tx = redis.multi();
    tx.decrby(from, amount);
    tx.incrby(to, amount);
    const results = await tx.exec(); // will return null if watched keys changed
    if (results) {
      success = true;
      console.log("Transfer complete:", results);
    } else {
      console.log("Retrying due to race condition...");
    }
  }
}

List

// Message queue
await redis.lpush("queue:emails", JSON.stringify({ to: "andy@example.com", subject: "Hello" }));
const job = JSON.parse(await redis.rpop("queue:emails"));
console.log("Processing job:", job);

// Activity feed
await redis.lpush("feed:user:123", "liked post 456");
await redis.lpush("feed:user:123", "commented on post 456");
await redis.lpush("feed:user:123", "shared post 456");
const activities = await redis.lrange("feed:user:123", 0, 9); // latest 10
console.log("Recent activities:", activities);

Set

// Unique visitors
await redis.sadd("visitors:2024-02-06", "user1", "user2", "user3", "user1");
const uniqueCount = await redis.scard("visitors:2024-02-06");
console.log("Unique visitors today:", uniqueCount);

// Tags
await redis.sadd("post:42:tags", "redis", "database", "nosql");
const tags = await redis.smembers("post:42:tags");
console.log("Tags:", tags);

Hash

// User profile
await redis.hset("user:a", { name: "Andy", age: "30" });
const name = await redis.hget("user:a", "name");
console.log("Name:", name);
const user = await redis.hgetall("user:a");
console.log("User profile:", user);
const all = await redis.hmget("user:a", ["name", "age"]);
console.log("All:", all);
await redis.hdel("user:a", "age");

Zset

// Leaderboard
await redis.zadd("game:leaderboard", 100, "andy", 250, "bob", 180, "charlie");
const topPlayers = await redis.zrevrange("game:leaderboard", 0, 2, "WITHSCORES");
console.log("Top players:", topPlayers);

// Priority queue (lowest score = highest priority)
await redis.zadd("tasks", 1, "task-low", 10, "task-high");
const nextTask = await redis.zpopmin("tasks");
console.log("Next task:", nextTask);

// Sliding Window Rate Limiting
async function isAllowedSliding(userId, limit = 5, windowSec = 60) {
  const key = `rate:sliding:${userId}`;
  const now = Date.now();
  await redis.zadd(key, now, `${userId}:${now}`);
  await redis.zremrangebyscore(key, 0, now - windowSec * 1000);
  const count = await redis.zcard(key);
  await redis.expire(key, windowSec);
  return count <= limit;
}

Pub/Sub


// Subscribe to news
await redis.subscribe("news", (channel, message) => {
  console.log(`Received message on ${channel}: ${message}`);
});

// Publish news
await redis.publish("news", "Breaking: Redis is awesome!");

Bitmap

// Mark user active today
await redis.setbit("active:2024-02-06", 123, 1);

// Check if user was active
const isActive = await redis.getbit("active:2024-02-06", 123);
console.log("User active today?", Boolean(isActive));

// Count actives
const activeCount = await redis.bitcount("active:2024-02-06");
console.log("Total actives:", activeCount);

HyperLogLog

// Add visitors
await redis.pfadd("unique:visitors", "user1", "user2", "user3", "user1");
const estimate = await redis.pfcount("unique:visitors");
console.log("Estimated unique visitors:", estimate);

Stream

// Add event
await redis.xadd("mystream", "*", "user", "123", "action", "login");

// Read event
const events = await redis.xrange("mystream", "-", "+", "COUNT", 10);
console.log("Events:", events);

// Consumer group
await redis.xgroup("CREATE", "mystream", "group1", "0", "MKSTREAM").catch(() => {});
await redis.xreadgroup("GROUP", "group1", "consumer1", "COUNT", 1, "STREAMS", "mystream", ">");

redis nodejs