redis - 防同一用户并发操作方案咨询
滿天的星座
滿天的星座 2017-04-27 09:02:40
0
5
806

新客领取优惠券逻辑

  • 判断是否新客

  • 若为新客 查询数据库是否已领取过

  • 未领取过 给用户发券

同一用户并发领券的情况下 会有超领的情况 因为并发进来时查询数据库均没有领取记录

而又不能针对用户和优惠券做唯一索引 因为有些券允许用户领取多张。

于是决定采用redis计数来防同一用户并发超领 新客领券逻辑改成如下

  • 判断是否新客

  • 若为新客 基于用户ID计数 incr {user_id}_receive_count

  • 如果计数大于1 表示同一用户并发领券 直接返回

  • 如果计数==1 表示第一次领取

  • 查询数据库是否已领取过

  • 未领取过 给用户发券

上述逻辑没有问题 但纠结该如何设置计数key的过期时间

  • 设置过期时间为1分钟 基本上大部分并发操作都是在同一秒 过期时间1分钟能满足要求了

  • 设置过期时间为1小时 万一数据库负载高呢 并不能在一分钟内完成一次领券事务操作 如双十一这种场景 还是设的长一点 更保险一点 不管怎样 1小时足够完成一次领券事务操作了吧 但时间设的长了 会不会因为其他原因(如网络超时)导致领券失败回滚 用户要等一小时后 才能重新领券

有没其他防并发领取方案呢? 可以不用纠结这种过期时间的设置呢。

滿天的星座
滿天的星座

모든 응답(5)
洪涛

과잉 동시성을 방지하는 판단과 신규 고객인지 여부를 판단하는 판단은 분리하여 진행하는 것이 좋습니다

  • 동시성 방지 슈퍼 칼라는 다음(잠금)을 사용할 수 있습니다. 각 작업이 완료된 후 키를 삭제(잠금 해제)해야 합니다.

으아악
  • 신규 고객인지(이전 수신 여부, 유효 시간은 이벤트 종료 시점으로 설정) 사용자의 수신 상태를 새로운 KEY로 설정하면 됩니다. 할인을 받은 사용자에게 직접 반환됩니다. (동시 수행을 위해 데이터베이스 쿼리가 연결되지 않음)

  • 쿠폰 받기(쿠폰을 미리 대기열에 넣고 데이터베이스가 아닌 대기열에서 가져옵니다. 여기서 장점은 대기열 데이터를 검색하면 사라지고, 초과 수신 상황 없음), Enter redis queue

  • 라고 작성하세요.
  • 백그라운드 프로세스 소비 큐, 소비를 위해 연결된 목록 차단 유형을 사용합니다(수집 정보를 데이터베이스에 저장하고 데이터베이스에 들어가기 전에 사용자가 쿠폰을 받았는지 쿼리하고 확인합니다)

黄舟

사업에 따라 구체적인 계획을 실행해야 합니다

  1. 비즈니스가 100%를 요구하지 않는 경우 각 사람은 하나의 쿠폰만 받을 수 있으며 Redis 클러스터의 가용성은 높습니다. 그러면 Redis, 특정 키 만료 시간 등으로 차단하면 충분합니다. . 이는 라이브러리에 속하지 않는 솔루션이므로 활동 다운로드가 전체적으로 유효하지 않으므로 요청을 반복할지 여부를 결정해야 하는 경우 Redis의 데이터에 의존해야 합니다(Redis가 중단되면 어떻게 됩니까?) Redis에는 불완전한 지속성 기능이 있지만 데이터 양은 상대적으로 적으므로 비즈니스에서 허용하는 경우 여전히 허용되지만 많은 비즈니스 시나리오에는 로깅이 필요합니다

  2. 비즈니스 요구 사항에 따라 한 사람이 하나의 쿠폰을 보유해야 하므로(쿠폰의 액면가가 매우 클 수 있음) 처음이라는 판단 후 해당 주제의 Redis 솔루션을 사용하겠습니다. 데이터베이스를 직접 삽입/업데이트합니다(여기에는 비동기 솔루션이 있지만 비동기 솔루션도 나타날 것입니다. 비동기 솔루션에도 1: 데이터 손실과 유사한 문제가 있습니다). 이 솔루션에 따르면 각 사람은 수신만 가능하다는 것을 보장할 수 있습니다. 하나의 쿠폰(데이터베이스에 의해 결정됨)은 데이터 일관성을 보장합니다. 질문자님 말씀대로 사실 Redis에 있는 것들을 무효화할 필요는 없습니다. 사용자가 반복적으로 쿠폰 추첨을 악의적으로 요청하면 Redis가 데이터베이스에 조회하지 않고 바로 차단할 수 있기 때문입니다. (여기서 또 다른 문제가 있는데, 해결 방법은 먼저 캐시를 업데이트하는 것입니다. 데이터베이스를 다시 업데이트하므로 캐시 업데이트는 성공하지만 데이터베이스 업데이트가 실패하는 비정상적인 상황을 고려해야 합니다. 데이터베이스가 비정상적인 경우 키에 해당하는 캐시를 삭제해야 합니다.

  3. 정말로 처리할 수 없는 경우(하드웨어가 따라잡을 수 없는 경우) 대기열을 사용하여 문제를 해결하고 대기열을 사용하여 피크를 줄일 수 있습니다

  4. @大woo의 솔루션도 가능하지만 Redis특정 시점에서 이러한 비정상적인 상황

  5. 을 고려해야 합니다.
滿天的星座

@大woo님이 말씀하신 기능은 사실 제가 예전에 글을 썼던 플래시세일과 비슷합니다. 살펴보세요:
전자상거래 제품의 필수 기능: 반짝 세일 및 경매

滿天的星座

큐 작성은 안되나요?

淡淡烟草味

이런 일에 감히 nosql 데이터베이스를 사용한다면 저는 취한 것입니다.

먼저 트랜잭션의 개념, 트랜잭션의 여러 격리 수준, 행 잠금 및 테이블 잠금에 중점을 두고 데이터베이스 이론을 학습한 후 이를 위해 전통적인 관계형 데이터베이스를 사용하는 것이 좋습니다.

데이터베이스 서버의 성능이 충분하지 않은 경우 각 서버가 사용자 데이터의 일부를 담당하는 다양한 서버를 갖춘 수평 테이블 아키텍처를 설계하세요. 레벨 테이블의 이론적 소스는 학부 수준 데이터 구조의 해시 장에서 살펴보실 수 있습니다.

최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!