스 레 드 를 해결 하고 redisson 에서 만 나 는 구 덩이 를 사용 합 니 다.
배경
업무 상의 구 매 수요 때문에 재 고 를 일정 보호 하고 초과 판매 의 발생 을 방지 해 야 한다(우 리 는 전자상거래 회사 가 아니다).조사 연 구 를 통 해 최종 적 으로 Redission 을 사용 하여 통 제 를 해 야 한다.
주로 Redission 의 풍부 한 API,오픈 소스 프레임 워 크 가 실제 생산 환경 에 널리 활용 되 었 기 때문이다.
문제 설명
Ression 에서 Lock.lock()방법 을 사용 한 후에 스 레 드 와 자주 발생 하 는 상황 이 있 으 면 다음 과 같은 이상 이 발생 합 니 다.
java.lang.IllegalMonitorStateException: attempt to unlock lock, not locked by current thread by node id: 9f178836-f7e1-44fe-a89d-2db52f399c0d thread-id: 22
문제 분석
thread-1 이 아직 끝나 지 않 았 을 때,즉 thread-1 이 자 물 쇠 를 얻 었 으 나 아직 자 물 쇠 를 풀 지 않 았 을 때,'thread-2 는 다른 스 레 드 에 의 해 중단 되 어 lock.try Lock 의 차단 상태 에서 다음 논 리 를 계속 실행 하 기 를 기다 리 고 있 습 니 다.또한 스 레 드 thread-1 에 속 하 는 자 물 쇠 를 풀 려 고 시도 하여 운행 시 이상 을 던 져 서 이 스 레 드 thread-2 가 끝 났 습 니 다.그러나 thread-2 는 일련의 조작 을 완성 한 후에 스 레 드 thread-1 은 자신의 자 물 쇠 를 풀 었 다.
그래서 thread-2 는 자 물 쇠 를 얻 지 못 했 지만 동기 화가 필요 한 내용 을 실 행 했 고 자 물 쇠 를 풀 려 고 시도 했다.
그 해결 방식 을 우 리 는 알 수 있 습 니 다.현재 스 레 드 에 추 가 된 자 물 쇠 는 현재 스 레 드 에서 잠 금 을 풀 수 있 습 니 다.즉,우리 가 lock.unlock 을 사용 할 때 스 레 드 의 판단 을 추가 하면 됩 니 다.
문제 해결
RLock lock = redissonClient.getLock(key);
if(lock.isLocked()){ //
if(lock.isHeldByCurrentThread()){ //
lock.unlock(); //
}
}
redisson 사용 주의사항Redisson 은 Redis 를 바탕 으로 실 현 된 자바 메모리 데이터 그리드 로 바 텀 작업 을 노출 하 는 Jedis 에 비해 Redisson 은 일련의 분포 식 자바 상용 대상 을 제공 하고 분포 식 서 비 스 를 많이 제공 했다.
특성&기능:
redis 자 체 는 상기 분포 식 대상 과 집합 을 지원 하지 않 습 니 다.Redisson 은 redis 의 특성 을 이용 하여 클 라 이언 트 에서 고급 데이터 구조 와 특성 을 실현 합 니 다.예 를 들 어 우선 대기 열의 실현 은 클 라 이언 트 정렬 을 통 해 정리 한 다음 에 redis 에 저장 합 니 다.
클 라 이언 트 가 실 현 된 것 은 클 라 이언 트 가 온라인 에 없 을 때 이러한 모든 데이터 구조 와 특성 이 보존 되 지 않 고 자동 으로 효력 이 발생 하지 않 는 다 는 것 을 의미한다.예 를 들 어 만 료 된 이벤트 의 트리거 나 원래 우선 대기 열의 요소 가 증가 하 는 것 이다.
주의 사항
실시 간성
RMap 에는 키 쌍 의 만 료 시간 을 설정 하고 키 쌍 의 이벤트 모니터 를 등록 할 수 있 는 기능 이 있 습 니 다.
원소 도태 기능(Eviction)
Redisson 의 분포 식 RMapCache Java 대상 은 RMap 을 바탕 으로 한 요소 에 대한 도태 체 제 를 실현 했다.요소 의 삽입 순 서 를 유지 합 니 다.RMapCache 는 RMap 을 기반 으로 이 루어 졌 기 때문에 자바 util.concurrent.Concurrent Map 인터페이스 와 자바 util.Map 인 터 페 이 스 를 동시에 계승 하 였 습 니 다.Redisson 이 제공 하 는 Spring Cache 통합 과 JCache 는 바로 이러한 기능 을 바탕 으로 이 루어 진 것 이다.
현재 Redis 자체 가 해시(Hash)의 요소 탈락 을 지원 하지 않 기 때문에 모든 만 료 요 소 는 org.redisson.EvictionScheduler 인 스 턴 스 를 통 해 정기 적 으로 청 소 됩 니 다.자원 의 효율 적 인 이용 을 위해 매번 운행 할 때마다 최대 300 개의 만 료 요 소 를 정리 합 니 다.작업 의 시작 시간 은 지난번 실제 청소 수량 에 따라 자동 으로 조정 되 며 간격 은 1 초 에서 1 시간 사이 입 니 다.예 를 들 어 이번 청소 때 300 개의 요 소 를 삭 제 했 으 면 다음 청소 시간 은 1 초 이후(최소 간격)입 니 다.이번 청소 수량 이 지난번 청소 수량 보다 적 으 면 시간 간격 이 1.5 배 증가한다.
공식 위 키 에서 말 한 바 와 같이 이 기능 은 백 스테이지 스 레 드 를 통 해 정 해진 시간 에 정리 되 기 때문에 이것 은 비 실시 간(issue-1234:on expired event is not executed in real-time)이 고 5 초 에서 2 시간 사이 지연 되 기 때문에 실시 간 요구 가 높 은 장면 은 스스로 평가 해 야 한다.
만 료 시간의 비 실시 성 으로 인해 만 료 사건 의 발생 도 비 실시 간 입 니 다.해당 하 는 모니터 가 잠시 지연 되 어서 야 통 지 를 받 을 수 있 습 니 다.제 테스트 에서 ttl 은 초 급 오차 가 비교적 크 고 분 급 ttl 은 괜 찮 습 니 다(왼쪽 설정 값,오른쪽 실제 시간 소모).
1s _ 5s
3s _ 5s
4s _ 5s
5s _ 9s
6s _ 10s
10s _ 15s
1m _ 1m11s
서열 화
Redisson 의 기본 인 코더 가 JSonJackson Codec 이 고,JSonJackson 은 양 방향 참조 대상 을 직렬 화 할 때 무한 순환 이상 이 발생 합 니 다.한편,fastjson 은 양 방향 인용 을 검사 한 후 자동 으로 인용 부호$ref 로 교체 하여 순환 을 종료 합 니 다.
제 상황 에서 저 는 service 를 직렬 화 했 습 니 다.이 서 비 스 는 spring 에 의 해 위탁 되 었 고 다른 service 와 도 서로 주입 되 었 습 니 다.fastjson 으로 redis 로 정상적으로 직렬 화 할 수 있 고 Json Jackson 은 무한 순환 이상 을 던 졌 습 니 다.
직렬 화 된 내용 을 볼 수 있 기 때문에 redition 의 다른 바 이 너 리 인 코더 없 이 자체 적 으로 인 코딩 기 를 실현 합 니 다.
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufInputStream;
import io.netty.buffer.ByteBufOutputStream;
import org.redisson.client.codec.BaseCodec;
import org.redisson.client.protocol.Decoder;
import org.redisson.client.protocol.Encoder;
import java.io.IOException;
public class FastjsonCodec extends BaseCodec {
private final Encoder encoder = in -> {
ByteBuf out = ByteBufAllocator.DEFAULT.buffer();
try {
ByteBufOutputStream os = new ByteBufOutputStream(out);
JSON.writeJSONString(os, in,SerializerFeature.WriteClassName);
return os.buffer();
} catch (IOException e) {
out.release();
throw e;
} catch (Exception e) {
out.release();
throw new IOException(e);
}
};
private final Decoder<Object> decoder = (buf, state) ->
JSON.parseObject(new ByteBufInputStream(buf), Object.class);
@Override
public Decoder<Object> getValueDecoder() {
return decoder;
}
@Override
public Encoder getValueEncoder() {
return encoder;
}
}
구독 발표Redisson 이 구독 게시 에 대한 패 키 징 은 RTopic 이 고 이것 은 Redisson 에서 많은 사건 감청 의 실현 원리(예 를 들 어 키 값 이 맞 는 사건 감청)이기 도 합 니 다.
유닛 테스트 를 사용 할 때 이벤트 가 발 표 된 후에 구독 자 는 시간 을 좀 끌 어야 이 벤트 를 받 을 수 있 습 니 다.구체 적 인 원인 은 조사 할 필요 가 있다.
이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
복잡 한 생산자 소비자 - pthread기초 지식 사고 정리http://blog.csdn.net/aganlengzi/article/details/51416461 [1] http://www.cnblogs.com/clover-toeic/p/4029269.ht...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.