어떻게 SpringBoot 를 통 해 상점 의 스톱워치 시스템 을 실현 합 니까?
배우다
1.주요 절차
1.1 데이터베이스:
1.2 환경
window 아래:Zookeeper,Redis,rabbitmq-server.jdk 1.8 이상.
소개
여 기 는 초 살 부분 기능 만 하고 다른 기능 은 언급 되 지 않 습 니 다.프로젝트 실행 후 초살 상품 페이지 방문 가능
사용자 가 로그 인하 지 않 으 면 자세 한 정 보 를 클릭 하면 로그 인 페이지 로 이동 합 니 다.
사용자 가 로그 인 한 후 상품 의 상세 한 상황 을 보고 앞 다 투어 구 매 할 수 있다.
사용자 가 한 상품 에 대해 한 번 만 앞 다 투어 구 매 할 수 있 고 두 번 째 앞 다 투어 구 매 할 때 거절당 할 수 있 음 을 주의 하 세 요.사용자 가 앞 다 투어 구 매 에 성공 하면 비동기 로 사용자 에 게 메 일 을 보 냅 니 다.
주요 논 리 는 이상 이다.다음은 코드 를 보 겠 습 니 다.
1.4 프로젝트 구조,api 는 매 거 진 값 과 반환 값 을 패키지 합 니 다.model 은 주로 실체 류 와 sql 맵 파일 이 고 service 는 업무 논리 코드 를 실현 합 니 다.
1.5 초 살 상품 이 페이지 와 사용자 의 조작 에 사용 되 는 지,아니면 MVC 모드 를 사용 하 는 지 자세히 설명 하지 않 습 니 다.높 고 내 리 는 초 살 을 실현 하 는 것 과 같다.
자세히 말 하려 면 물건 이 너무 많 습 니 다.깊이 알 고 싶 으 면 위의 링크 를 클릭 하 십시오.
기본 적 인 스톱워치 논 리 는 다음 과 같 습 니 다.사용자 가 이미 이 상품 을 앞 다 투어 구 매 한 적 이 있 는 지 판단 하고 없 으 면 스톱워치 상품 의 상세 한 상황 을 조회 하여 이 상품 이 스톱워치 하지 않 고 재고 가 충분 한 지 판단 합 니 다.
만약 조건 에 부합 한다 면 이 상품 의 재 고 는 1 을 줄 이 고 이 어 공제 가 성공 적 인지 다시 한 번 판단 하 며 공제 에 성공 하면 스톱워치 성공 주문 서 를 생 성하 고 사용자 에 게 스톱워치 성공 정 보 를 알려 준다.
public Boolean killItem(Integer killId, Integer userId) throws Exception {
Boolean result=false;
//TODO:
if (itemKillSuccessMapper.countByKillUserId(killId,userId) <= 0){
//TODO:
ItemKill itemKill=itemKillMapper.selectById(killId);
//TODO: canKill=1?
if (itemKill!=null && 1==itemKill.getCanKill() ){
//TODO: -
int res=itemKillMapper.updateKillItem(killId);
//TODO: ? - ,
if (res>0){
commonRecordKillSuccessInfo(itemKill,userId);
result=true;
}
}
}else{
throw new Exception(" !");
}
return result;
}
코드 최적화 1:redis 의 분포 식 자 물 쇠 를 사용 하여 현재 초살 상품 의 id 와 현재 사용자 의 id 를 사용 하여 key 를 구성 하고 StringBuffer 를 사용 하여 연결 하 며 눈꽃 알고리즘 을 사용 하여 value 를 생 성하 여 redis 에 저장 합 니 다.
@Autowired
private StringRedisTemplate stringRedisTemplate;
/**
* -redis
* @param killId
* @param userId
* @return
* @throws Exception
*/
@Override
public Boolean killItemV3(Integer killId, Integer userId) throws Exception {
Boolean result=false;
if (itemKillSuccessMapper.countByKillUserId(killId,userId) <= 0){
//TODO: Redis - -
ValueOperations valueOperations=stringRedisTemplate.opsForValue();
final String key=new StringBuffer().append(killId).append(userId).append("-RedisLock").toString();
final String value=RandomUtil.generateOrderCode();
Boolean cacheRes=valueOperations.setIfAbsent(key,value); //luna “ ”,
//TOOD:redis
if (cacheRes){
stringRedisTemplate.expire(key,30, TimeUnit.SECONDS);
try {
ItemKill itemKill=itemKillMapper.selectByIdV2(killId);
if (itemKill!=null && 1==itemKill.getCanKill() && itemKill.getTotal()>0){
int res=itemKillMapper.updateKillItemV2(killId);
if (res>0){
commonRecordKillSuccessInfo(itemKill,userId);
result=true;
}
}
}catch (Exception e){
throw new Exception(" 、 !");
}finally {
if (value.equals(valueOperations.get(key).toString())){
stringRedisTemplate.delete(key);
}
}
}
}else{
throw new Exception("Redis- !");
}
return result;
}
코드 최적화 2:Boolean cacheRes=lock.tryLock(30,10,TimeUnit.SECONDS);현재 사용자 가 잠 금 밖 에 시간 을 초과 하 였 는 지 30 초 마다 판단 합 니 다.한 번 의 정지 로 인해 전체 프로그램 에 영향 을 주지 않 습 니 다.
@Autowired
private RedissonClient redissonClient;
/**
* -redisson
* @param killId
* @param userId
* @return
* @throws Exception
*/
@Override
public Boolean killItemV4(Integer killId, Integer userId) throws Exception {
Boolean result=false;
final String lockKey=new StringBuffer().append(killId).append(userId).append("-RedissonLock").toString();
RLock lock=redissonClient.getLock(lockKey);
try {
Boolean cacheRes=lock.tryLock(30,10,TimeUnit.SECONDS);
if (cacheRes){
//TODO:
if (itemKillSuccessMapper.countByKillUserId(killId,userId) <= 0){
ItemKill itemKill=itemKillMapper.selectByIdV2(killId);
if (itemKill!=null && 1==itemKill.getCanKill() && itemKill.getTotal()>0){
int res=itemKillMapper.updateKillItemV2(killId);
if (res>0){
commonRecordKillSuccessInfo(itemKill,userId);
result=true;
}
}
}else{
throw new Exception("redisson- !");
}
}
}finally {
lock.unlock();
//lock.forceUnlock();
}
return result;
}
코드 최적화 3:
@Autowired
private CuratorFramework curatorFramework;
private static final String pathPrefix="/kill/zkLock/";
/**
* - ZooKeeper
* @param killId
* @param userId
* @return
* @throws Exception
*/
@Override
public Boolean killItemV5(Integer killId, Integer userId) throws Exception {
Boolean result=false;
InterProcessMutex mutex=new InterProcessMutex(curatorFramework,pathPrefix+killId+userId+"-lock");
try {
if (mutex.acquire(10L,TimeUnit.SECONDS)){
//TODO:
if (itemKillSuccessMapper.countByKillUserId(killId,userId) <= 0){
ItemKill itemKill=itemKillMapper.selectByIdV2(killId);
if (itemKill!=null && 1==itemKill.getCanKill() && itemKill.getTotal()>0){
int res=itemKillMapper.updateKillItemV2(killId);
if (res>0){
commonRecordKillSuccessInfo(itemKill,userId);
result=true;
}
}
}else{
throw new Exception("zookeeper- !");
}
}
}catch (Exception e){
throw new Exception(" 、 !");
}finally {
if (mutex!=null){
mutex.release();
}
}
return result;
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
thymeleaf로 HTML 페이지를 동적으로 만듭니다 (spring + gradle)지난번에는 에서 화면에 HTML을 표시했습니다. 이번에는 화면을 동적으로 움직여보고 싶기 때문에 입력한 문자를 화면에 표시시키고 싶습니다. 초보자의 비망록이므로 이상한 점 등 있으면 지적 받을 수 있으면 기쁩니다! ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.