솔루션: 데이터 중복 삽입을 방지하는 방법은 무엇입니까?

4938 단어
요약: 출처https://www.bysocket.com"공인호: 미장이BYSocket"관심과 전재를 환영합니다. 요약을 보류해 주십시오. 감사합니다!
카탈로그
  • 왜 데이터 중복 삽입을 해결해야 합니까?
  • 솔루션 실전
  • 착지 가능 요약
  • 1. 왜 데이터 중복 삽입을 해결해야 합니까?


    문제의 기원, 위챗 애플릿 바람 wx.request () 중복 요청 서버에서 데이터를 제출합니다.백엔드 서비스도 간단합니다. 위조 코드는 다음과 같습니다.
    class SignLogService {
        public void saveSignLog(SignLogDO log) { //   SignLogDAO.insert(log); } } 

    데이터베이스에 중복 데이터 줄이 존재하고 제출 시간이 똑같다는 것을 발견했습니다.그러나 업무 수요는 여분의 로그가 나타나지 않는 것이 문제다.
    문제는 중복 요청으로 인한 데이터 중복 삽입입니다.이 문제의 결과는 매우 뚜렷하다.
  • 데이터 이중화
  • 일부 업무 수요는 여분의 데이터가 없어서 서비스 문제를 일으킨다
  • 문제는 그림과 같습니다.
    해결 방법: 같은 요청 A를 삽입하지 않고 이전 요청이 삽입한 데이터를 읽고 되돌려주는 방법입니다.해결 후 절차는 다음과 같습니다.

    2. 솔루션 실전


    1. 단일 라이브러리 단일 테이블 솔루션

  • 고유 인덱스 + 고유 필드
  • 멱등
  • 위에서 말한 그런 업무 장면:sign_로그 테이블에 user_id、sign_id、sign_시간 등.그러면 매번 출석체크를 하면 사람마다 매일 출석기록이 하나밖에 없다.
    데이터베이스 층은 유일한 색인 형식을 채택하여 데이터 기록의 유일성을 확보한다.즉, UNIQUE 구속조건입니다. UNIQUE 구속조건은 데이터베이스 테이블의 각 레코드를 고유하게 식별합니다.또한,user_id,sign_id,sign_time 세 개의 조합은 유일한 필드에 적합하다.테이블의 위조 코드는 다음과 같습니다.
    CREATE TABLE sign_log
    (
    id int NOT NULL,
    user_id int NOT NULL, sign_id int, sign_time int, CONSTRAINT unique_sign_log UNIQUE (user_id,sign_id,sign_time) ) 

    중점은 CONSTRAINT unique_sign_log UNIQUE (user_id,sign_id,sign_time).작은 문제가 있습니다. 데이터의 양이 많을 때 모든 기록에 대응하는 유일한 인덱스가 있고 자원을 소모합니다.그럼 이렇게 하면 되나요?
    답은 안 된다. 서비스가 건장하지 못하다.첫 번째 요청은 삽입에 성공했고, 두 번째 요청은 직접 오류를 보고하면 자바 서비스가 던진다DuplicateKeyException.
    간단한 幂等 쓰기 조작을 하면 된다. 위조 코드는 다음과 같다.
    class SignLogService {
        public SingLogDO saveSignLog(SignLogDO log) { //   SignLogDO insertLog = null; try { insertLog = signLogDAO.insert(log); } catch (DuplicateKeyException e) { insertLog = selectByUniqueKeys(userId,signId,signTime); } return insertLog; } } 

    확실히 유량은 그리 크지 않고 높은 병발도 아니다.문제를 반복해서 쓰면 된다.그 큰 유량과 높은 병발 장면은 어떻게 하는가

    2. 라이브러리 분할 솔루션


    유량이 크면 단일 라이브러리 테이블은 분할 라이브러리 테이블로 변한다.그러면 단표의 유일한 색인 형식을 바탕으로 분표를 만나면 보장할 수 없습니다. 삽입된 곳은 두 개의 분표 A1과 A2일 수 있습니다.
    해결 방법: 데이터의 유일한 조건을 다른 저장소에 저장하고 잠금 제어를 한다
    아니면 위의 예에서 매일, 매번 출석체크를 하면 사람마다 출석체크 기록이 하나밖에 없다.그러면 Redis의 분산 잠금 솔루션을 사용합니다.대략적인 위조 코드는 다음과 같다.

    자물쇠를 채우다

    //  
    jedis.set(lockKey, requestId, "NX", "PX", expireTime);
    
  • lockKey 가장 쉬운 것은user_id + sign_id + sign_time
  • expireTime을 하루로 설정
  • b. 잠금 해제

    //  
    jedis.eval(script, lockKey,requestId);
    

    c. 멱등 코드 강화

    class SignLogService {
        public SingLogDO saveSignLog(SignLogDO log) { //   SignLogDO existLog = selectByUniqueKeys(userId,signId,signTime); if(Objects.nonNull(existLog)) { return existLog; } //   jedis.set SignLogDO insertLog = signLogDAO.insert(log); //   jedis.eval return insertLog; } } 

    이 방안은 아직 매우 성숙하지 않으니 여러분이 참고하시면 됩니다.

    3. 착지 가능한 작은 총결산


    해결 방안의 실전에서 구체적인 기술을 이해하다.요약은 다음과 같습니다.
  • 멱등: 여러 차례 동의 요청 후 결과 일치 보장
  • 병렬 제어: 단일 테이블 유일한 인덱스, 분포식 다중 테이블 분포식 자물쇠
  • 디폴트 방안: 분포식 자물쇠 실효 - 낙관적인 자물쇠 자물쇠 고려
  • 참고 자료

  • 반복 삽입 시나리오:http://www.bysocket.com/archives/2266
  • 알리바바 자바 개발 매뉴얼
  • 다음 주제 강좌는 아마도 당신에게 흥미가 있을 것입니다

  • Spring Boot 2.x 시리즈 자습서
  • Java Core 시리즈 자습서
  •  
    (위챗 공중번호를 팔로우하여 Java 정선 건조물 학습 자료를 수령)

    좋은 웹페이지 즐겨찾기