为 Node.js 应用集成 Redis 缓存

随着 Web 应用的发展,前端应用对数据的存储和访问的要求也越来越高,常常需要在后端使用缓存来提高访问速度。Redis 是一种内存缓存数据库,具有高效、可靠、可扩展等优点。本文将介绍如何在 Node.js 应用中集成 Redis 缓存。

安装 Redis

首先,需要在系统中安装 Redis。在 Ubuntu 上可以通过以下命令安装:

在 Windows 上可以通过官方网站下载安装程序, 点击 下载链接

安装成功后,可以通过以下命令启动 Redis:

安装 Redis 模块

要在 Node.js 应用中集成 Redis 缓存,需要使用 Redis 客户端模块。Node.js 有很多 Redis 模块可供选择,如 ioredisnode_redisredis 等,本文使用 ioredis 模块作为示例。

使用 npm 安装 ioredis

连接 Redis

首先,需要在代码中引入 ioredis 模块:

const Redis = require('ioredis');

在 Node.js 应用中连接 Redis 服务器需要配置 Redis 的地址、端口等信息:

const redis = new Redis({
  port: 6379, // Redis 端口
  host: 'localhost', // Redis 地址
  password: 'password', // Redis 密码
});

其中,porthost 是必需配置项,password 是可选的,如 Redis 未设置密码则可省略。

存储和读取缓存

存储缓存

在 Node.js 应用中,通过 set 方法可以向 Redis 中存储缓存,语法如下:

redis.set(key, value, [expiryMode], [time]);

其中:

  • key: 缓存的键名;
  • value: 缓存的值,可以是 JSON 字符串、Buffer、数字、布尔值等;
  • expiryMode(可选): 缓存的过期模式,可以是 EX(秒)、PX(毫秒)、NX(只在键不存在时设置) 或XX(只在键已存在时设置);
  • time(可选): 缓存的过期时间,以 expiryMode 对应的时间单位为准。

例如下面的代码将一个 JSON 字符串存储到 Redis 中,并设置过期时间为 10 分钟:

const user = { name: 'jack', age: 20 };
redis.set('user', JSON.stringify(user), 'EX', 600);

读取缓存

从 Redis 中读取缓存可以通过 get 方法,语法如下:

redis.get(key);

例如下面的代码将刚刚存储的 JSON 字符串从 Redis 中读取出来并解析为对象:

redis.get('user')
  .then(userStr => {
    const user = JSON.parse(userStr);
    console.log(user.name, user.age);
  });

删除缓存

删除 Redis 缓存可以使用 del 方法,可以同时删除多个键名对应的缓存,语法如下:

redis.del(key1, key2, ...);

例如,下面的代码将删除刚刚存储的 user 缓存:

redis.del('user');

高级用法

设备锁

Redis 提供了分布式锁功能,可以用于控制代码的并发执行情况,避免因多个进程同时访问共享资源而产生的问题。在 Node.js 应用中使用 ioredis 来实现设备锁,可以采用以下代码:

async function acquireLock(lockId, timeout, maxTries) {
  const lockKey = `LOCK:${lockId}`;
  let acquired = false;
  const randomId = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
  for (let i = 0; i < maxTries && !acquired; i++) {
    acquired = await redis.set(lockKey, randomId, 'PX', timeout, 'NX');
    if (acquired) {
      return { lockId, value: randomId };
    }
    await new Promise(resolve => setTimeout(resolve, 10));
  }
  throw new Error(`Failed to acquire lock ${lockId}`);
}

该函数尝试获取名为 lockId 的锁,如果锁已经被其他进程占用,则等待一定时间后重试。获取锁后,可以执行临界区代码,然后释放锁:

async function releaseLock(lockId, value) {
  const lockKey = `LOCK:${lockId}`;
  const current = await redis.get(lockKey);
  if (current === value) {
    return redis.del(lockKey);
  }
  return false;
}

发布和订阅

Redis也提供了一种发布和订阅机制,可以用于建立消息队列的功能,使得发送和接收消息的进程解耦。在 Node.js 应用中,可以使用以下代码来发布一条消息:

redis.publish(channel, message);

在订阅同一频道的客户端中,可以监听频道并接收到该消息:

redis.subscribe(channel, (err, count) => {
  if (err) {
    console.error('Redis subscribe error.', err);
  }
});
redis.on('message', (channel, message) => {
  console.log(channel, message);
});

其中,subscribe 方法用于订阅频道,on('message') 方法用于监听消息。在上述代码中,redis.subscribe 只需要执行一次,而 redis.on('message') 就需要执行多次,分别对不同频道的消息进行处理。

总结

本文介绍了如何在 Node.js 应用中集成 Redis 缓存,并展示了一些高级用法,如设备锁和发布订阅。选择恰当的 Redis 模块,结合缓存策略,可以有效提高应用的性能。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65ab33eeadd4f0e0ff4d2646