redis : delex 를 사용하고 lua 스크립트를 쓰지 않기
redis 에 저장된 동일한 값(예를 들어 ‘item_a’)을 여러 프로세스가 업데이트할 때, ‘lock:item_a’ 와 같은 값을 key로 사용하여 lock 메카니즘으로 순차접근하게 합니다.
그런데 이 lock을 다음 프로세스가 사용할 수 있도록 삭제할 때 DEL 명령을 쓰는데, “내 프로세스가 만든 lock 인 경우에만 삭제한다” 라는 가이드를 지키기 위해 다음과 같은 lua script를 사용합니다.
// 스크립트 정의 : client 생성시에 만들어 넣음
unlock: defineScript({
NUMBER_OF_KEYS: 1,
SCRIPT: ` <--- 정의
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('DEL', KEYS[1])
end
`,
parseCommand(parser: CommandParser, key: string, token: string) {
parser.pushKey(key);
parser.push(token);
},
transformReply(reply: any) {
return reply
}
}),
// 스크립트 사용
try {
const result = await cb();
return result;
} finally {
await client.unlock(lockKey, token) <--- 사용
}그런데 DEL command가 조건을 지원하면 굳이 lua 스크립트를 사용할 필요가 없습니다. 올해 나온 redis 8.4 이후에서 DELEX 명령이 등장했습니다. 이것을 자바스크립트에서 사용하기 위해서는 node-redis 5.12.1 이후의 클라이언트 라이브러리를 사용해야 합니다.
DELEX 명령을 사용하면 위의 구현이 다음과 같이 간단해 집니다.
try {
const result = await cb();
return result;
} finally {
await client.delEx(lockKey, { <-- 이걸로 해결
condition: 'IFEQ',
matchValue: token
});
}