Backend/node.js(express)

Redis Key Delete Pattern with Node.js

곤프 2022. 6. 21. 14:19

Redis는 single thread로 동작하기 때문에 long-time 명령 수행시 다른 명령어들을 처리 할 수 없는 상태가 되기 때문에 매우 비효율적으로 동작하게 됩니다.

 

따라서 사용자들은 이 점을 명시하고 될 수 있는 한 long-time 명령의 수행들을 피해야 합니다.

 

Redis에서 주요 명령어들이 O(1)의 성능을 보인다면서 왜 long-time 명령을 수행하지 말라고 하는건지 의문을 가지실수 도 있는데, 일반적으로 오랜 시간이 걸리는 명령은 데이터가 매우 많은 상황에서, 여러개의 키를 다루는 명령어에서 O(N)의 수행시간을 가지면서 성능에 악영향을 끼치게됩니다.

 

일반적으로 Redis에서 Pattern으로  Key를 찾고 찾은결과를 Delete하기 위해,

keys *과 del(key)를 생각할 수 있습니다.

 

하지만 single thread로 동작하는 Redis 특성 상 keys를 검색할 때는 다른 작업이 불가능하게 lock 상태가 되므로 서비스에 지장이 생길 수 있습니다.

 

따라서 keys와 del은 scan과 unlink로 적절히 대체해서 사용하는것을 추천합니다.

 

scan은 key를 찾을 때, count 개수대로 적절히 나눠서 검색을 하고, 중간중간 비는 시간에 다른 요청을 수행할 수 있게 도와줍니다.

unlink는 삭제작업을 background에서 수행하도록 해주며 redis 버전 4.0 이상에서 사용가능합니다.

 

아래는 제가 sample로 구현한 코드이고 적절히 응용하시길 바랍니다.

  delByKeyPattern: async (keys) => {
    await client.connect();

    let cursor = 0;
    for await (let key of keys) { 
      do {
        const reply = await client.scan(cursor, {
          MATCH: key,
          COUNT: 2000,
        })

        await Promise.all(reply.keys.map(async (_key) => {
          await client.unlink(_key);
        }));
  
        cursor = reply.cursor;
      } while (cursor)
    }

    await client.quit();
  },