신규고객이 쿠폰을 받는 논리
신규고객인지 확인
신규고객이라면 이미 받으셨는지 데이터베이스를 확인해보세요
사용자에게 쿠폰을 발급한 적이 없습니다.
동일 사용자가 동시에 쿠폰을 받을 경우 데이터베이스에 동시 조회 시 쿠폰을 받은 기록이 없기 때문에 초과 수령 상황이 발생합니다
그리고 일부 쿠폰은 사용자가 여러 개의 쿠폰을 받을 수 있도록 허용하기 때문에 사용자 및 쿠폰에 대한 고유한 인덱스를 수행하는 것이 불가능합니다.
그래서 동일한 사용자가 동시에 쿠폰을 받는 것을 방지하기 위해 redis 계산을 사용하기로 했습니다.
신규 고객이 쿠폰을 받는 로직이 다음과 같이 변경되었습니다.신규고객인지 확인
신규고객인 경우 사용자ID를 기준으로 집계 incr {user_id}_receive_count
갯수가 1보다 크면 동일한 사용자가 동시에 쿠폰을 받고 바로 반품할 수 있다는 의미입니다
count == 1이면 처음으로 받았다는 뜻
데이터베이스에서 수신 여부를 확인하세요
사용자에게 쿠폰을 발급한 적이 없습니다.
위 논리에는 문제가 없지만 카운팅 키의 만료 시간을 어떻게 설정해야 할지 고민입니다
만료 시간을 1分钟
으로 설정 기본적으로 대부분의 동시 작업은 동일한 초에 수행됩니다. 만료 시간은 1분이면
만료 시간을 1小时
으로 설정합니다. Double Eleven과 같이 데이터베이스 부하가 높아 쿠폰 거래 작업을 1분 내에 완료할 수 없는 경우에는 어떤 경우에도 더 길고 안전하게 설정하는 것이 더 안전합니다. 뭐, 1시간이면 쿠폰 수집 거래 작업을 완료할 수 있을까요? 그런데 시간을 너무 길게 설정하면 다른 이유로(예: 네트워크 시간 초과) 쿠폰 수집이 실패하고 사용자는 롤백을 위해 1시간을 기다려야 합니다. ? 그래야만 쿠폰을 다시 받으실 수 있습니다
동시 수집을 방지할 수 있는 다른 솔루션이 있나요? 만료 시간 설정에 대해 걱정할 필요가 없습니다.
과잉 동시성을 방지하는 판단과 신규 고객인지 여부를 판단하는 판단은 분리하여 진행하는 것이 좋습니다
으아악동시성 방지 슈퍼 칼라는 다음(잠금)을 사용할 수 있습니다. 각 작업이 완료된 후 키를 삭제(잠금 해제)해야 합니다.
신규 고객인지(이전 수신 여부, 유효 시간은 이벤트 종료 시점으로 설정) 사용자의 수신 상태를 새로운 KEY로 설정하면 됩니다. 할인을 받은 사용자에게 직접 반환됩니다. (동시 수행을 위해 데이터베이스 쿼리가 연결되지 않음)
쿠폰 받기(쿠폰을 미리 대기열에 넣고 데이터베이스가 아닌 대기열에서 가져옵니다. 여기서 장점은 대기열 데이터를 검색하면 사라지고, 초과 수신 상황 없음), Enter redis queue
백그라운드 프로세스 소비 큐, 소비를 위해 연결된 목록 차단 유형을 사용합니다(수집 정보를 데이터베이스에 저장하고 데이터베이스에 들어가기 전에 사용자가 쿠폰을 받았는지 쿼리하고 확인합니다)
사업에 따라 구체적인 계획을 실행해야 합니다
비즈니스가 100%를 요구하지 않는 경우 각 사람은 하나의 쿠폰만 받을 수 있으며 Redis 클러스터의 가용성은 높습니다. 그러면
Redis
, 특정 키 만료 시간 등으로 차단하면 충분합니다. . 이는 라이브러리에 속하지 않는 솔루션이므로 활동 다운로드가 전체적으로 유효하지 않으므로 요청을 반복할지 여부를 결정해야 하는 경우 Redis의 데이터에 의존해야 합니다(Redis가 중단되면 어떻게 됩니까?) Redis에는 불완전한 지속성 기능이 있지만 데이터 양은 상대적으로 적으므로 비즈니스에서 허용하는 경우 여전히 허용되지만 많은 비즈니스 시나리오에는 로깅이 필요합니다비즈니스 요구 사항에 따라 한 사람이 하나의 쿠폰을 보유해야 하므로(쿠폰의 액면가가 매우 클 수 있음) 처음이라는 판단 후 해당 주제의
Redis
솔루션을 사용하겠습니다. 데이터베이스를 직접 삽입/업데이트합니다(여기에는 비동기 솔루션이 있지만 비동기 솔루션도 나타날 것입니다. 비동기 솔루션에도 1: 데이터 손실과 유사한 문제가 있습니다). 이 솔루션에 따르면 각 사람은 수신만 가능하다는 것을 보장할 수 있습니다. 하나의 쿠폰(데이터베이스에 의해 결정됨)은 데이터 일관성을 보장합니다. 질문자님 말씀대로 사실 Redis에 있는 것들을 무효화할 필요는 없습니다. 사용자가 반복적으로 쿠폰 추첨을 악의적으로 요청하면 Redis가 데이터베이스에 조회하지 않고 바로 차단할 수 있기 때문입니다. (여기서 또 다른 문제가 있는데, 해결 방법은 먼저 캐시를 업데이트하는 것입니다. 데이터베이스를 다시 업데이트하므로 캐시 업데이트는 성공하지만 데이터베이스 업데이트가 실패하는 비정상적인 상황을 고려해야 합니다. 데이터베이스가 비정상적인 경우 키에 해당하는 캐시를 삭제해야 합니다.정말로 처리할 수 없는 경우(하드웨어가 따라잡을 수 없는 경우) 대기열을 사용하여 문제를 해결하고 대기열을 사용하여 피크를 줄일 수 있습니다
@大woo의 솔루션도 가능하지만
Redis
특정 시점에서 이러한 비정상적인 상황@大woo님이 말씀하신 기능은 사실 제가 예전에 글을 썼던 플래시세일과 비슷합니다. 살펴보세요:
전자상거래 제품의 필수 기능: 반짝 세일 및 경매
큐 작성은 안되나요?
이런 일에 감히 nosql 데이터베이스를 사용한다면 저는 취한 것입니다.
먼저 트랜잭션의 개념, 트랜잭션의 여러 격리 수준, 행 잠금 및 테이블 잠금에 중점을 두고 데이터베이스 이론을 학습한 후 이를 위해 전통적인 관계형 데이터베이스를 사용하는 것이 좋습니다.
데이터베이스 서버의 성능이 충분하지 않은 경우 각 서버가 사용자 데이터의 일부를 담당하는 다양한 서버를 갖춘 수평 테이블 아키텍처를 설계하세요. 레벨 테이블의 이론적 소스는 학부 수준 데이터 구조의 해시 장에서 살펴보실 수 있습니다.