728x90
반응형
source 는 Github 에 있습니다.
목차는 선착순 쿠폰 발급 에 있습니다.
[선착순 쿠폰 발급 2편] Redis 자료 구조 설계 (lua script)
코틀린, Redis 공부를 위해 작성했습니다.
쿠폰 발급 요청 처리 FLOW
- 쿠폰 발급 요청 처리 FLOW 는 다음과 같습니다.
Redis 자료 구조 설계
- 쿠폰 발급 요청이 들어왔을 때 DB 처리 부하를 줄이기 위해 Redis 자료구조를 사용하여 한 번에 처리하지 않고 앞단에 Redis를 두기로 결정했습니다.
- 또한, 여러 단계로 이뤄지는 쿠폰 ID 발급 과정에서 동시성 처리 문제를 해결하기 위해 lua script를 사용하여 처리합니다.
- Redis 자료구조를 설계하는 두 가지 방법은 다음과 같습니다.
Redis 에 한정된 쿠폰 데이터를 미리 생성해서 분배하는 것
설명
- 예를 들어 Redis에 Set 자료구조로 쿠폰 ID를 1000개 미리 생성합니다.
- 사용자 요청이 들어오면 Set에서 SPOP 명령어로 쿠폰 ID를 가져옵니다. (시간 복잡도 O(1))
- 가져온 쿠폰 ID를 가지고 Hash에 key는 userId, value는 쿠폰 ID로 저장합니다. (시간 복잡도 O(1))
- user 중복을 막기 위해 Hash에서 userId가 존재하는지 체크합니다. (중복 방지, 시간 복잡도 O(1))
source (lua script)
"""
-- 체크할 user Id를 매개변수로 받음
local userId = ARGV[1]
-- Hash에서 userId가 있는지 확인하고, 있다면 "exist"를 리턴
local check = redis.call('HEXISTS', KEYS[2], ARGV[1])
if check == 1 then
return "exist"
end
-- Set에서 쿠폰 ID를 가져와서 제거
local couponId = redis.call('SPOP', KEYS[1])
if not couponId or couponId == nil then
return "empty"
end
-- Hash에 쿠폰 ID를 저장
redis.call('HSET', KEYS[2], ARGV[1], couponId)
-- 발급된 쿠폰 ID 리턴
return couponId
""",
요청이 들어올 때마다 쿠폰 발급 요청된 개수를 비교해 발급 요청해줄지를 결정하는 것
설명
- 예를 들면 다음과 같습니다. 쿠폰은 최대 1000개를 발급할 수 있다고 가정하겠습니다.
- 요청이 들어오면 Redis 에 저장된 자료구조에 데이터가 1000개를 넘었는지 체크합니다.
- 어떤 자료구조를 써도 count 해야하기에 시간복잡도가 높게 측정됩니다.
- 1000개가 이미 발급됐다면 더 이상 발급하지 않고, 아니라면 쿠폰을 발급해줍니다.
source (lua script)
"""
-- 체크할 user Id를 매개변수로 받음
local userId = ARGV[1]
-- Hash에서 userId가 있는지 확인하고, 있다면 "exist"를 리턴
local check = redis.call('HEXISTS', KEYS[2], ARGV[1])
if check == 1 then
return "exist"
end
-- Set에서 쿠폰 ID를 가져와서 제거
local couponId = redis.call('SPOP', KEYS[1])
-- Hash에 쿠폰 ID를 저장
redis.call('HSET', KEYS[2], ARGV[1], couponId)
-- 발급된 쿠폰 ID 리턴
return couponId
"""
정리
- 미리 쿠폰을 발급해둔 상태에서 쿠폰이 소진될 때까지 처리하는 방식으로 진행했습니다. 쿠폰이 다 소진됐다면 쿠폰을 발급해주는 화면에서 더 이상 쿠폰 발급 요청을 못하도록 막는 방법으로 진행하면 좋을 것 같습니다.
'토이프로젝트 > 선착순쿠폰발급' 카테고리의 다른 글
[선착순 쿠폰 발급 4편] 동시 요청 테스트 (0) | 2023.03.27 |
---|---|
[선착순 쿠폰 발급 3편] API 설명 (0) | 2023.03.27 |
[선착순 쿠폰 발급 1편] 개요 (0) | 2023.03.04 |
댓글