thumbnail

redisとin-memory-cacheのパフォーマンス調べてみた

2022/04/22

主に以下の違いが知りたくて、実際に時間を測って調べてみました。

  • 複数key保存、単一key保存での処理速度の違い
  • redisとin-memory-cacheの具体的なパフォーマンス差

方法

以下のuserオブジェクトを1000件、10000件、100000件、保存・取得したときの時間をそれぞれ計測してみました。

user.ts
const user = {
  id: i,
  name: 'Takashi',
  location: 'Kyoto',
  company: 'Idutsu',
  age: 30,
  frends: [
    {
      id: 15000,
      name: 'Takashi',
    },
    {
      id: 15001,
      name: 'Takashi',
    },
  ],
}

保存、取得する際には単一key、複数keyに分けての計測をそれぞれ行っています。

※ 計測に使用したcodeのイメージ (Clickで詳細)
test.ts
async function test() {
  const users = [...Array(100000)].map((_, i) => ({
    id: i,
    name: 'Takashi',
    location: 'Kyoto',
    company: 'Idutsu',
    age: 30,
    frends: [
      {
        id: 15000,
        name: 'Takashi',
      },
      {
        id: 15001,
        name: 'Takashi',
      },
    ],
  }));

  // Set Parallel
  console.time('cache-set-para');
  await Promise.all(
    users.map(async (user) =>
      cacheService.setAsync(`user_${user.id}`, JSON.stringify(user)),
    ),
  );
  console.timeEnd('cache-set-para');

  console.time('redis-set-para');
  await Promise.all(
    users.map(async (user) =>
      redisService.setAsync(`user_${user.id}`, JSON.stringify(user)),
    ),
  );
  console.timeEnd('redis-set-para');

  // Get Parallel
  console.time('cache-get-para');
  const keyReg = /user_/;
  const cacheKeys = await cacheService.keysAsync(keyReg);
  await Promise.all(cacheKeys.map(async (key) => cacheService.getAsync(key)));
  console.timeEnd('cache-get-para');

  console.time('redis-get-para');
  const redisKeys = await redisService.keysAsync('user_*');
  await Promise.all(redisKeys.map(async (key) => redisService.getAsync(key)));
  console.timeEnd('redis-get-para');

  // Set Once
  console.time('cache-set-once');
  await cacheService.setAsync('all-users', JSON.stringify(users));
  console.timeEnd('cache-set-once');

  console.time('redis-set-once');
  await redisService.setAsync('all-users', JSON.stringify(users));
  console.timeEnd('redis-set-once');

  // Get Once
  console.time('cache-get-once');
  await cacheService.getAsync('all-users');
  console.timeEnd('cache-get-once');

  console.time('redis-get-once');
  await redisService.getAsync('all-users');
  console.timeEnd('redis-get-once');

  console.log('FINISH');
}

結果

結果は以下のとおりになりました。

method 1000件 10000件 100000件
redis set once 5.422 ms 16.63 ms 109.812 ms
redis set para 24.306 ms 179.134 ms 1146 ms
redis get once 0.671 ms 3.027 ms 66.624 ms
redis get para 15.523 ms 132.765 ms 1064 ms
cache set once 0.763 ms 7.525 ms 98.416 ms
cache set para 4.21 ms 45.129 ms 334.195 ms
cache get once 0.017 ms 0.012 ms 0.023 ms
cache get para 0.906 ms 0.726 ms 0.792 ms

表のmethodはそれぞれ以下を意味しています。

  • set once: 複数オブジェクトを1つのkeyで保存
  • set para: 複数オブジェクトをそれぞれ別のkeyで並列保存
  • get once: 複数オブジェクトを1つのkeyで取得
  • get para: 複数オブジェクトをそれぞれ別のkeyで並列取得

考察

まず、処理速度に関してはネットワーク通信部分がない分in memory cacheのほうがredisより(当たり前ですが)早いです。

また、redis、in-memory-cacheともに同一データであれば複数keyに分けて保存・取得するよりも単一keyで保存・取得したほうが、今回の例では早いことがわかりました。 それなりのデータ量(今回の100000件)でも単一keyのほうが早いので、基本的にはパフォーマンスを考えると単一key運用が良さそうです。

ただし、件数が増えるごとに単一key、複数keyの保存・取得時間比が小さくなっているので、単一keyのほうが早いとはいってもデータ量に限度はありそうです。 データ量が増えると一括保存などにそれなりの時間がかかるようになってくるので、 データ量が大きい、かつ、データ更新頻度が高い場合はkeyを分けて運用したほうがいいかもしれません。

author picture

Mitsuru Takahashi

京都市内にてフリーランスエンジニアとして活動しています。

detail

Profile

author picture

Mitsuru Takahashi

京都市内にてフリーランスエンジニアとして活動しています。

detail

© 2022 mitsuru takahashi