使用Node.js中的ioredis库处理Redis Cluster
最近でNode.jsで Redis Clusterを触る機会があったのですが
意外とRedis Cluster × Node.jsの日本語記事が無かったため、備忘録を兼ねて記事に起こしておきます。
今回利用するパッケージはこちら。
GitHub – luin/ioredis: ?A robust, performance-focused and full-featured Redis client for Node.js.
如果使用TypeScript的话,让我们一起导入类型吧。
npm i ioredis
npm i -D @types/ioredis
构造函数
如果是以cluster形式来使用的话,需要用数组形式指定要使用的node。如果不需要指定任何其他选项,那么基本上只需进行这个设置即可。
const driver: IORedis.Cluster = new IORedis.Cluster([
{ port: 6380, host: '127.0.0.1'},
{ port: 6381, host: '127.0.0.1'},
]);
Redis选项
可能性最大的触及点可能会是以下命名方法。它是用来设置与 Redis 相关的选项。例如,如果需要密码,可以通过 redisOption 进行指定。
const driver: IORedis.Cluster = new IORedis.Cluster([],
redisOptions: {
password: config.password
}
);
在可設定的選項中,可以通過API – ioredis / new Redis([port], [host], [options]來確認,這裡將列出我覺得可能會用到的項目。
其他选项
redisOption以外にも幾つか指定できるオプションがあるため、こちらも記載。
こちらも同様にAPI – ioredis / new Cluster(startupNodes, options) に設定項目が載っています。
我挑选了一些可能会用到的物品。
ノードに到達できない場合に呼び出されるcallback。 returnした数値分待機して再接続を試みるscaleReadsmaster読み取り対象のnodeを指定する。指定可能なのは master, slave, all のいずれかmaxRedirections16ターゲット nodeからエラー(MOVED, CLUSTERDOWN等)が返った場合に他のnodeにリダイレクトする回数retryDelayOnFailover100ターゲット nodeが切断されている場合に指定秒後にコマンドを再送信する
const driver: IORedis.Cluster = new IORedis.Cluster([],
redisOptions: {},
retryDelayOnFailover: 50
);
然而,与redisOptions不同,很少有情况需要指定此选项。
命令
以基本的的Command为中心。
尤其是在写入(write)时需要注意写入的数据类型。
阅读
await redis.get('key');
写
await redis.set('key', 'value');
如果要指定 expire ,则如下所示指定为 EX 和有效期(秒)。
redis.set('key', 'value', 'EX', 10);
请注意,如果将Object类型设置为value,则会以[Object object]的形式保存,因此在保存Object类型时,请确保使用JSON.stringify将其转换为字符串并放入。
删除
await this.redis.del('key');
钥匙
使用正则表达式匹配进行提取。
当没有匹配时,使用”get” 会返回 null,而这里将返回一个空数组。
await this.redis.keys('regExp');
事件
根据与Redis的连接状态相对应,将触发事件。
触发的事件如下。
可以通过以下方式来处理发生异常的事件。
this.redis.on('connect', () => {
console.log('trigger connect');
});
其他的技巧
这是我实际处理过的细节内容。
我想要减轻主节点的负载。
基本上,在ioredis中,所有的命令都会发送到主节点。
因此,可能会导致主节点的CPU消耗过大,进而降低性能。
因此,通过构造函数选项scaleRead,将读取命令的目标更改为从设备。
const driver: IORedis.Cluster = new IORedis.Cluster([],
redisOptions: {},
scaleReads: 'slave'
);
这样一来,read命令就会指向从库,减轻了主库的负担。
但是需要注意的是,由于复制延迟的存在,主库和从库之间可能会发生数据差异。
我想压缩要写入的数据。
使用API缓存等将大量数据写入Redis时,预计会出现一些问题。
-
- ネットワーク帯域を圧迫して帯域詰まりを起こす
-
- レイテンシが悪化する
- Redisの容量を圧迫する
有一个解决这些问题的方法是通过压缩数据,但是 ioredis 不会压缩数据,因此需要自己准备压缩机制。
虽然有几个可以进行压缩和解压缩的库可供选择,但这次我们将使用速度快的 lz-string 库。在 GitHub 上可找到:pieroxy/lz-string:用于 JavaScript 的基于 LZ 的压缩算法。
npm i lz-string
npm i -D @types/lz-string
import * as IORedis from 'ioredis';
import {compress, decompress} from 'lz-string'
//
// 省略
//
/**
* 読み込み
* @param {string} key
*/
async function get(key: string): Promise<string | null> {
const buf: string | null = await redis.get(key);
if (buf == null) return null;
return decompress(buf);
}
/**
* 書き込み
* @param {string} key
* @param {string} value
* @param {number} expireSec
*/
async function set(key: string, value: string, expireSec: number): Promise<void> {
await redis.set(key, compress(value), 'EX', expireSec);
}
请注意,压缩和解压会消耗CPU资源,有可能降低性能。
因此,在引入时需要测量CPU的消耗,并重新调整资源。
为了解决延迟恶化的问题,需要根据数据大小进行测量并做出判断。
提供的参考
Redis Cluster的工作原理非常清晰易懂。