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();
},