[redisson] 분포식 자물쇠와 데이터베이스 업무

2648 단어
장면: 사용자가 포인트를 소모하여 상품을 교환합니다.
user_point(사용자 포인트):
id
point
1
2000
point_item(포인트 상품):
id
point
num
101
200
10
전통적인 controller, 서비스,dao 3층 구조로 데이터베이스 사무는 서비스 층(데이터베이스 MYSQL)에서 제어된다.
@RestController
@RequestMapping(value = {"point"})
public class UserPointController{
    @Autowired
    private UserPointService userPointService;

    @RequestMapping("/exchange")
    public boolean exchange(HttpServletRequest request, Long userId, Long itemId){

        return userPointService.exchange(userId, itemId);
    }
}
@Service
public class UserPointService {
    @Resource
    private RedissonClient redissonClient;

    @Transaction
    public boolean exchange(Long userId, Long itemId) throws Exception {
        RLock lock = redissonClient.getLock("lock:" + itemId);
        try {
            boolean bool = lock.tryLock(10, 30, TimeUnit.SECONDS);
            if (!bool){
                throw new Exception("    ,     ");
            }

            UserPoint user = "select * from user_point where id = :userId";
            PointItem item = "select * from point_item where id = :itemId";

            if(user.point - item.point > 0 && item.num > 0){
                //     
                >> update user_point set point = point - :item.point where id = :userId; 

                //     
                >> update point_item set num = num - 1 where id = :itemId; 
    
                return true;
            }

            return false;
        } catch (Exception e) {
            throw e;
        } finally {
            if(lock != null && lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

}

상기 코드를 관찰하여 생각하다.
  • lock은 언제 풀렸습니까?호출lock.unlock()은 Redisson-lock를 방출하는 것이다.
  • 사무는 언제 제출했습니까?사무의 제출은 방법UserPointService#exchange()이 집행된 후이다.그래서 예시 코드에서 사실 lock, 이 나온다.
  • 사무는 언제 제출했습니까?트랜잭션 제출에 소요되는 시간
  • lock, 。 mysql repetable-read로 인해 발생한 문제는 현재 2개의 동시 요청{"userId": 1, "itemId": 101}이 있다고 가정하면user 잉여 포인트 201이다.A 요청이 먼저 lock을 받았다고 가정하면 B 요청이 자물쇠를 가져올 때까지 기다립니다.A가 요청한 데이터 정보는userpoint#point=201, 이 때 교환 실행 공제를 허용하고true로 돌아갑니다.true로 돌아가기 전에 lock을 풀고 업무를 제출합니다.
    lock을 풀면 B 요청은 바로 자물쇠를 얻을 수 있습니다.user를 조회하면 남은 포인트를 얻을 수 있습니다:201(정확한 것은 남은 포인트:1). A 요청의 업무가 제출되지 않아서 완료될 수 있습니다!
    해결 방안: 잠시lock을 controller층에 덮어쓰고 사무 제출이 성공한 후에야 자물쇠를 풀 수 있습니다!
    (그림은 손이 아프고, 시차도는 인연이 있으면 다시 만나자)

    좋은 웹페이지 즐겨찾기