솔루션: 데이터 중복 삽입을 방지하는 방법은 무엇입니까?
카탈로그
1. 왜 데이터 중복 삽입을 해결해야 합니까?
문제의 기원, 위챗 애플릿 바람 wx.request () 중복 요청 서버에서 데이터를 제출합니다.백엔드 서비스도 간단합니다. 위조 코드는 다음과 같습니다.class SignLogService {
public void saveSignLog(SignLogDO log) { // SignLogDAO.insert(log); } }
데이터베이스에 중복 데이터 줄이 존재하고 제출 시간이 똑같다는 것을 발견했습니다.그러나 업무 수요는 여분의 로그가 나타나지 않는 것이 문제다.
문제는 중복 요청으로 인한 데이터 중복 삽입입니다.이 문제의 결과는 매우 뚜렷하다.
class SignLogService {
public void saveSignLog(SignLogDO log) { // SignLogDAO.insert(log); } }
해결 방법: 같은 요청 A를 삽입하지 않고 이전 요청이 삽입한 데이터를 읽고 되돌려주는 방법입니다.해결 후 절차는 다음과 같습니다.
2. 솔루션 실전
1. 단일 라이브러리 단일 테이블 솔루션
데이터베이스 층은 유일한 색인 형식을 채택하여 데이터 기록의 유일성을 확보한다.즉, 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);
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. 착지 가능한 작은 총결산
해결 방안의 실전에서 구체적인 기술을 이해하다.요약은 다음과 같습니다.
참고 자료
다음 주제 강좌는 아마도 당신에게 흥미가 있을 것입니다
(위챗 공중번호를 팔로우하여 Java 정선 건조물 학습 자료를 수령)
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.