MSA
@Transactional
방금시작한사람
2021. 9. 19. 06:22
트랜잭션을 열때 하지 말아야할 것.. 😢
트랜잭션 사이에 기이이인 무언가을 넣지 말아야함
기이이인 무언가란?
시간이 오래 걸리는 연산 - 이런건 연산을 마치고 결과만 저장할때
외부요청 - 레디스든 msa 구조라서 다른 곳을 다녀와야 한다는 등등..
외부의 장애가 바로 전파된다..
트랜잭션을 열고, 커넥션을 잡고 A 라는 곳에 요청을 보냇는데 죽거나 장애가 있어서타임아웃을기다리게 된다면..
어흑.. 바로 커넥션 풀에 있는거 다 쓰고 모든 요청이 디비만 기다리다가 다 500 ...
그래서 상태처리가 중요한 요청은 request 로 기록을 해두고, 요청을 보낸 다음에 다시 상태를 done 이나 fail 처리한다.
class AService {
fun sendMoney(to: String, from: String, amount: Long) {
val log = moneyRepository.saveRequest(to, from, amount, REQEEST)
val result = moneyService.sendMoney(to, from, amount)
if(result == SUCCESS) {
moneyRepository.save(log.successSendMoney())
} else {
moneyRepository.save(log.failSendMoney())
}
}
}
트랜잭션 어노테이션이 있다고 바로 트랜잭션이 시작되는게 아니고
함수 첫줄부터 적용되는게 아니라, 디비에 무언가를 할때부터 시작된다.
class Service(
private val repo: Repo,
private val redis: RedisService
) {
@Transactional
fun saveSomething(key: String) {
// 트랜잭션은 실제 디비에 무언가를 하기 전까지 열리지 않는다
// 따라서 redis.get 는 영향은 주지 않음
val value = redis.get(key)
repo.save(value)
}
@Transactional
fun getAndSaveRedis(key: String) {
val value = repo.findByKey(key)
// 이친구는 트랜잭션이 닫히지않기 때문에, 영향을 줌
// 이런건 함수 밖에서 하거나, findByKey에 트랜잭션을 걸고, 이 함수에 트랜잭션 어노테이션을 빼자
redis.set(key, value)
}
}