Redis集群分类及Redis功能简介

person 蓝猫    watch_later 2024-08-08 22:01:04
visibility 160    class Redis    bookmark 分享

Redis 的功能介绍及应用场景

1. 缓存

应用场景

Redis 作为缓存,可以极大地提高应用程序的响应速度,适用于存储会话数据、热点数据、频繁访问的数据等。

示例

Node.js 实现用户会话存储

const redis = require("redis");
const client = redis.createClient();

client.on("error", (err) => {
  console.error("Redis client not connected to the server:", err);
});

client.on("connect", () => {
  console.log("Redis client connected to the server");
});

const sessionId = "session:123456";
const sessionData = { userId: 1, username: "john_doe" };

// 设置会话数据,并设置过期时间为 3600 秒
client.hmset(sessionId, sessionData, (err, res) => {
  if (err) console.error(err);
  else console.log("Session data set:", res);

  client.expire(sessionId, 3600);
});

// 获取会话数据
client.hgetall(sessionId, (err, obj) => {
  if (err) console.error(err);
  else console.log("Session data retrieved:", obj);

  client.quit();
});

Java 实现用户会话存储

import redis.clients.jedis.Jedis;
import java.util.HashMap;
import java.util.Map;

public class RedisSessionExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");

        String sessionId = "session:123456";
        Map<String, String> sessionData = new HashMap<>();
        sessionData.put("userId", "1");
        sessionData.put("username", "john_doe");

        // 设置会话数据,并设置过期时间为 3600 秒
        jedis.hmset(sessionId, sessionData);
        jedis.expire(sessionId, 3600);

        // 获取会话数据
        Map<String, String> retrievedData = jedis.hgetAll(sessionId);
        System.out.println("Session data retrieved: " + retrievedData);

        jedis.close();
    }
}

2. 排行榜/计分板

应用场景

利用 Redis 的有序集合来实现排行榜,例如游戏积分榜、社交应用的粉丝排名。

示例

Node.js 实现游戏积分排行榜

const redis = require("redis");
const client = redis.createClient();

client.on("error", (err) => {
  console.error("Redis client not connected to the server:", err);
});

client.on("connect", () => {
  console.log("Redis client connected to the server");
});

const leaderboardKey = "game:leaderboard";

// 添加用户分数
client.zadd(leaderboardKey, 100, "alice");
client.zadd(leaderboardKey, 200, "bob");
client.zadd(leaderboardKey, 150, "charlie");

// 获取排行榜前两名
client.zrevrange(leaderboardKey, 0, 1, "WITHSCORES", (err, members) => {
  if (err) console.error(err);
  else console.log("Top players:", members);

  client.quit();
});

Java 实现游戏积分排行榜

import redis.clients.jedis.Jedis;
import java.util.Set;

public class RedisLeaderboardExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");

        String leaderboardKey = "game:leaderboard";

        // 添加用户分数
        jedis.zadd(leaderboardKey, 100, "alice");
        jedis.zadd(leaderboardKey, 200, "bob");
        jedis.zadd(leaderboardKey, 150, "charlie");

        // 获取排行榜前两名
        Set<String> topPlayers = jedis.zrevrange(leaderboardKey, 0, 1);
        System.out.println("Top players: " + topPlayers);

        jedis.close();
    }
}

3. 分布式锁

应用场景

在分布式系统中,Redis 可用于实现分布式锁,确保共享资源的互斥访问。

示例

Node.js 实现简单的分布式锁

const redis = require("redis");
const client = redis.createClient();
const lockKey = "lock:resource";
const lockTimeout = 10;

client.on("error", (err) => {
  console.error("Redis client not connected to the server:", err);
});

client.on("connect", () => {
  console.log("Redis client connected to the server");
});

function acquireLock(callback) {
  client.set(lockKey, "locked", "NX", "EX", lockTimeout, (err, res) => {
    callback(err, res === "OK");
  });
}

function releaseLock() {
  client.del(lockKey);
}

// 获取锁
acquireLock((err, acquired) => {
  if (err) {
    console.error(err);
  } else if (acquired) {
    console.log("Lock acquired, performing operation...");
    setTimeout(() => {
      releaseLock();
      console.log("Lock released.");
      client.quit();
    }, 5000);
  } else {
    console.log("Unable to acquire lock.");
    client.quit();
  }
});

Java 实现简单的分布式锁

import redis.clients.jedis.Jedis;

public class RedisLockExample {
    private static final String LOCK_KEY = "lock:resource";
    private static final int LOCK_TIMEOUT = 10;

    public static void main(String[] args) {
        try (Jedis jedis = new Jedis("localhost")) {
            if (acquireLock(jedis)) {
                System.out.println("Lock acquired, performing operation...");
                try {
                    Thread.sleep(5000); // 模拟操作时间
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                releaseLock(jedis);
                System.out.println("Lock released.");
            } else {
                System.out.println("Unable to acquire lock.");
            }
        }
    }

    public static boolean acquireLock(Jedis jedis) {
        String result = jedis.set(LOCK_KEY, "locked", "NX", "EX", LOCK_TIMEOUT);
        return "OK".equals(result);
    }

    public static void releaseLock(Jedis jedis) {
        jedis.del(LOCK_KEY);
    }
}

4. 消息队列

应用场景

Redis 的列表和发布/订阅机制适用于构建简单的消息队列系统。

示例

Node.js 实现生产者-消费者模式

const redis = require("redis");
const client = redis.createClient();
const queueKey = "task:queue";

client.on("error", (err) => {
  console.error("Redis client not connected to the server:", err);
});

client.on("connect", () => {
  console.log("Redis client connected to the server");
});

// 生产者
function producer() {
  for (let i = 0; i < 5; i++) {
    const task = `task_${i}`;
    client.lpush(queueKey, task, (err) => {
      if (err) console.error(err);
      else console.log(`Produced ${task}`);
    });
  }
}

// 消费者
function consumer() {
  client.brpop(queueKey, 5, (err, task) => {
    if (err) {
      console.error(err);
    } else if (task) {
      console.log(`Consumed ${task[1]}`);
      consumer();
    } else {
      console.log("No task, consumer is waiting...");
      setTimeout(consumer, 1000);
    }
  });
}

// 启动生产者和消费者
producer();
consumer();

Java 实现生产者-消费者模式

import redis.clients.jedis.Jedis;
import redis.clients.jedis.ListPosition;
import redis.clients.jedis.resps.Tuple;

public class RedisQueueExample {

    private static final String QUEUE_KEY = "task:queue";

    public static void main(String[] args) {
        new Thread(RedisQueueExample::producer).start();
        new Thread(RedisQueueExample::consumer).start();
    }

    // 生产者
    public static void producer() {
        try (Jedis jedis = new Jedis("localhost")) {
            for (int i = 0; i < 5; i++) {
                String task = "task_" + i;
                jedis.lpush(QUEUE_KEY, task);
                System.out.println("Produced " + task);
                Thread.sleep(1000); // 模拟生产间隔
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    // 消费者
    public static void consumer() {
        try (Jedis jedis = new Jedis("localhost")) {
            while (true) {
                String task = jedis.brpop(5, QUEUE_KEY).get(1);
                if (task != null) {
                    System.out.println("Consumed " + task);
                } else {
                    System.out.println("No task, consumer is waiting...");
                    Thread.sleep(1000);
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

5. 实时统计

应用场景

使用 Redis 的计数器和 HyperLogLog,可以实现实时统计功能,如网站访问量、在线

用户数等。

示例

Node.js 实现网站访问量统计

const redis = require("redis");
const client = redis.createClient();
const pageViewsKey = "page:views";

client.on("error", (err) => {
  console.error("Redis client not connected to the server:", err);
});

client.on("connect", () => {
  console.log("Redis client connected to the server");
});

function incrementPageViews() {
  client.incr(pageViewsKey, (err, newValue) => {
    if (err) console.error(err);
    else console.log("Page views:", newValue);
  });
}

// 模拟页面访问
setInterval(incrementPageViews, 2000);

Java 实现网站访问量统计

import redis.clients.jedis.Jedis;

public class RedisPageViewsExample {

    private static final String PAGE_VIEWS_KEY = "page:views";

    public static void main(String[] args) {
        try (Jedis jedis = new Jedis("localhost")) {
            while (true) {
                incrementPageViews(jedis);
                Thread.sleep(2000); // 模拟页面访问间隔
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void incrementPageViews(Jedis jedis) {
        long pageViews = jedis.incr(PAGE_VIEWS_KEY);
        System.out.println("Page views: " + pageViews);
    }
}

Redis 集群的分类及使用

1. 主从复制(Master-Slave)

主从复制是一种简单的高可用方案,通过配置多个从节点来分担读负载,并在主节点故障时进行故障切换。

示例

Node.js 配置主从复制

  1. 配置主节点
const redis = require("redis");
const master = redis.createClient({ port: 6379 });

master.set("key", "value", (err, res) => {
  if (err) console.error(err);
  else console.log("Set in master:", res);
});

master.quit();
  1. 配置从节点
const redis = require("redis");
const slave = redis.createClient({ port: 6380 });

slave.get("key", (err, value) => {
  if (err) console.error(err);
  else console.log("Retrieved from slave:", value);

  slave.quit();
});

Java 配置主从复制

  1. 配置主节点
import redis.clients.jedis.Jedis;

public class RedisMasterExample {
    public static void main(String[] args) {
        try (Jedis master = new Jedis("localhost", 6379)) {
            master.set("key", "value");
            System.out.println("Set in master");
        }
    }
}
  1. 配置从节点
import redis.clients.jedis.Jedis;

public class RedisSlaveExample {
    public static void main(String[] args) {
        try (Jedis slave = new Jedis("localhost", 6380)) {
            String value = slave.get("key");
            System.out.println("Retrieved from slave: " + value);
        }
    }
}

2. 哨兵模式(Sentinel)

哨兵模式用于自动故障转移和系统监控。

示例

Node.js 配置 Redis 哨兵

  1. 启动 Redis 主节点和从节点
redis-server --port 6379
redis-server --port 6380 --slaveof 127.0.0.1 6379
redis-server --port 6381 --slaveof 127.0.0.1 6379
  1. 启动 Redis 哨兵
redis-sentinel sentinel.conf
  1. 使用哨兵进行故障转移
const Redis = require("ioredis");
const sentinel = new Redis({
  sentinels: [{ host: "localhost", port: 26379 }],
  name: "mymaster"
});

sentinel.get("key", (err, value) => {
  if (err) console.error(err);
  else console.log("Value from sentinel:", value);

  sentinel.quit();
});

Java 配置 Redis 哨兵

import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.Jedis;

import java.util.HashSet;
import java.util.Set;

public class RedisSentinelExample {
    public static void main(String[] args) {
        Set<String> sentinels = new HashSet<>();
        sentinels.add("localhost:26379");

        try (JedisSentinelPool sentinelPool = new JedisSentinelPool("mymaster", sentinels);
             Jedis jedis = sentinelPool.getResource()) {

            String value = jedis.get("key");
            System.out.println("Value from sentinel: " + value);
        }
    }
}

3. Redis 集群(Redis Cluster)

功能

  • Redis Cluster 是 Redis 的原生分布式解决方案,支持数据的分片和自动故障转移。
  • 数据分片存储在不同的节点上,每个节点可以包含多个数据槽(slot),Redis Cluster 将所有的键分布在 16384 个槽中。

示例配置

Node.js 配置 Redis 集群

const Redis = require("ioredis");

const cluster = new Redis.Cluster([
  { host: "127.0.0.1", port: 7000 },
  { host: "127.0.0.1", port: 7001 },
  { host: "127.0.0.1", port: 7002 }
]);

cluster.set("key", "value", (err, res) => {
  if (err) console.error(err);
  else console.log("Set in cluster:", res);

  cluster.get("key", (err, value) => {
    if (err) console.error(err);
    else console.log("Retrieved from cluster:", value);

    cluster.quit();
  });
});

Java 配置 Redis 集群

import redis.clients.jedis.JedisCluster;

import java.util.HashSet;
import java.util.Set;
import redis.clients.jedis.HostAndPort;

public class RedisClusterExample {
    public static void main(String[] args) {
        Set<HostAndPort> jedisClusterNodes = new HashSet<>();
        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7000));
        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7001));
        jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7002));

        try (JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes)) {
            jedisCluster.set("key", "value");
            String value = jedisCluster.get("key");
            System.out.println("Retrieved from cluster: " + value);
        }
    }
}

Redis 云服务

除了自建 Redis 集群之外,还有许多云服务提供商提供托管的 Redis 服务,如 AWS ElastiCache for Redis、Azure Redis Cache、Google Cloud Memorystore 等。这些服务通常提供更简单的管理和监控工具,可以方便地实现高可用和自动扩展。

总结

Redis 以其高性能、多数据结构支持和丰富的功能,成为许多应用程序中不可或缺的缓存和存储方案。通过主从复制、哨兵模式和 Redis 集群等机制,Redis 提供了可靠的高可用性和扩展性,适用于各种规模和复杂性的应用场景。了解并合理应用 Redis 的这些特性,可以显著提高系统的性能和稳定性。

如果有其他具体问题或示例需要解释,请随时告诉我!

评论区
评论列表
menu