🔖

Node.jsのioredisを使ってRedisを操作する

2022/09/24に公開

はじめに

Node.jsのRedis Clientsは公式ドキュメントにもある通り node-redis, ioredis, tedis などがあります。今回は ioredis を少し触ってみたので、そのときのコードをメモしておきます。

実装コード

main.ts
import Redis from 'ioredis';

export class RedisClient {
  // デフォルトは 127.0.0.1:6379 に接続する
  constructor(private redis = new Redis()) {}

  /**
   * Redis にキーと値を設定する。
   * 既に重複したキーが存在する場合は、上書きする。
   *
   * @param key キー
   * @param value 値
   */
  public async set(key: string, value: string | Buffer | number): Promise<void> {
    await this.redis.set(key, value);
  }

  /**
   * 引数で指定したキーを削除する。
   *
   * @param key 削除対象のキー
   * @returns 削除できた場合は 1, できなかった場合は 0
   */
  public async delete(key: string): Promise<number> {
    return await this.redis.del(key);
  }

  /**
   * Redis からキーに紐づく値を取得する。
   * キーが存在しない場合は、null を返す。
   *
   * @param key 取得対象のキー
   */
  public async get(key: string): Promise<string | null> {
    return await this.redis.get(key);
  }

  /**
   * Redis へのコネクションを切断する。
   */
  public async quit(): Promise<void> {
    await this.redis.quit();
  }

  /**
   * コマンドを一括して送信する。
   *
   * @param params キーと値の配列
   */
  public async pipeline(params: { key: string; value: string | Buffer | number }[]): Promise<void> {
    const pipeline = this.redis.pipeline();
    params.forEach((param) => {
      pipeline.set(param.key, param.value);
    });

    await pipeline.exec();
  }

  /**
   * list型を追加する。
   *
   * @param key キー
   * @param value 値
   */
  public async listPush(key: string, value: (string | number | Buffer)[]): Promise<void> {
    await this.redis.rpush(key, ...value);
  }

  /**
   * list型の値を取得する。
   *
   * @param key キー
   * @param start 開始位置
   * @param end 終了位置
   */
  public async getList(key: string, start = 0, end = -1): Promise<string[]> {
    return await this.redis.lrange(key, start, end);
  }

  /**
   * すべてのキーを削除する。
   */
  public async flushall(): Promise<void> {
    await this.redis.flushall();
  }
}

使い方(redis serverが起動していることが前提です。)

const redisClient = new RedisClient();

// キーと値を指定して、値を設定できる
await redisClient.set('key1', 'value');
console.log(await redisClient.get('key1')); // value

// 既に同一キーが設定されている場合、値を上書きする
await redisClient.set('key2', 'value');
await redisClient.set('key2', 'newValue');
console.log(await redisClient.get('key2')); // newValue

// キーが存在しない場合、 null を返す
console.log(await redisClient.get('notFound')); // null

// コマンドを一括して送信できる
 await redisClient.pipeline([
  { key: 'pipelineKey1', value: 'pipelineValue1' },
  { key: 'pipelineKey2', value: 'pipelineValue2' },
  { key: 'pipelineKey3', value: 'pipelineValue3' },
]);

// キーを指定して、値を削除できる
await redisClient.set('deleteKey', 'value');
await redisClient.delete('deleteKey');
console.log(await redisClient.get('deleteKey')); // null

// リスト型を作成して値を追加できる
await redisClient.listPush('listKey', ['value1', 'value2', 'value3']);
console.log(await redisClient.getList('listKey')); // [ 'value1', 'value2', 'value3' ]

PubSubの仕組みも構築ができます。

pubsub.ts
import Redis from 'ioredis';

// 接続は同時に両方の役割を果たすことはできないので、それぞれでインスタンスを作成する
const pubRedis = new Redis();
const subRedis = new Redis();

// 一定時間ごとにメッセージを送信する
setInterval(() => {
  const message = { foo: Math.random() };
  const channel = `my-channel-${1 + Math.round(Math.random())}`;

  pubRedis.publish(channel, JSON.stringify(message));
  console.log('Published %s to %s', message, channel);
}, 1000);

// 指定したチャンネルのsubscribeを実施する
subRedis.subscribe('my-channel-1', 'my-channel-2', (err, count) => {
  if (err) {
    console.error('Failed to subscribe: %s', err.message);
  } else {
    console.log(`Subscribed successfully! This client is currently subscribed to ${count} channels.`);
  }
});

// 設定されたsubscribeのメッセージを受信したら、コンソールに出力する
subRedis.on('message', (channel, message) => {
  console.log(`Received ${message} from ${channel}`);
});

pubsub.tsを実行結果

Subscribed successfully! This client is currently subscribed to 2 channels.
Published { foo: 0.8520497965522418 } to my-channel-2
Received {"foo":0.8520497965522418} from my-channel-2
Published { foo: 0.6859509912864634 } to my-channel-1
Received {"foo":0.6859509912864634} from my-channel-1
Published { foo: 0.5970506846840671 } to my-channel-1
Received {"foo":0.5970506846840671} from my-channel-1
Published { foo: 0.6241309846521499 } to my-channel-2
Received {"foo":0.6241309846521499} from my-channel-2

参考

https://chaika.hatenablog.com/entry/2020/06/30/083000
https://github.com/luin/ioredis

Discussion