์คํ๋ง์์ @Transactional์ ์ฐ๋ฆฌ๊ฐ ์๊ฐํ๋ ๊ฒ๋ณด๋ค ๋ ๋ง์ ๊ฑธ ์ฑ
์์ง๊ณ ์์ต๋๋ค.
ํนํ DB ํธ๋์ญ์
๊ณผ ๊ด๋ จ๋ ๋ชจ๋ ์์
์ ํ๋์ ๋จ์๋ก ๋ฌถ์ด ์ฑ๊ณตํ๋ฉด ์ปค๋ฐ, ์คํจํ๋ฉด ๋กค๋ฐฑ์ ๋ณด์ฅํ์ฃ .
๊ทธ๋ฐ๋ฐ Redis ๊ฐ์ ์ธ๋ถ ์ ์ฅ์๋ฅผ ๋ค๋ฃฐ ๋๋ ์ด์ผ๊ธฐ๊ฐ ์กฐ๊ธ ๋ฌ๋ผ์ง๋๋ค.
์๋ํ๋ฉด Redis๋ RDBMS๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ์คํ๋ง์ ํธ๋์ญ์
๊ด๋ฆฌ ๋ฒ์์ ํฌํจ๋์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค.
์ต๊ทผ ํ๋ก์ ํธ์์ ๋ฐ๋ก ์ด ๋ถ๋ถ ๋๋ฌธ์ ๋ฐ์ดํฐ ์ ์ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ณ , ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด TransactionSynchronization์ afterCommit์ ํ์ฉํ์ต๋๋ค.
์ด ๊ธ์์๋ ๊ทธ ๊ณผ์ ์ ์ ๋ฆฌํด๋ณด๊ฒ ์ต๋๋ค.
ํ๋ก์ ํธ์์๋ DB(MySQL)๊ณผ Redis๋ฅผ ํจ๊ป ์ฌ์ฉํ๊ณ ์์์ต๋๋ค.
DB โ ๋ฉ์ธ ๋ฐ์ดํฐ ์ ์ฅ
Redis โ sorted set์ ํ์ฉํ ์์ ํ(๋๊ธฐ์ด) ๋ฐ์ดํฐ ๊ด๋ฆฌ
๋ฌธ์ ๊ฐ ๋ ๋ถ๋ถ์ Redis์์ ๋ฐ์ดํฐ๋ฅผ popํ๋ ์์ ์ด์์ต๋๋ค.
@Transactional
public void processTicket() {
// DB ์ ์ฅ
ticketRepository.save(ticket);
// Redis์์ pop
Ticket ticket = redisQueue.pop();
// ...์ค๊ฐ ์๋ต
// ์์ธ ๋ฐ์ ์ ๋กค๋ฐฑ
}
์ ์ฒญ ๋ฐ์ดํฐ๋ฅผ DB์ ์ ์ฅํ๋ค.
Redis(๋๊ธฐ์ด)์์ ๋ฐ์ดํฐ๋ฅผ pop(์ญ์ )ํ๋ค.
๋ฌธ์ ๊ฐ ์์ผ๋ฉด ํธ๋์ญ์ ์ ๋กค๋ฐฑํ๋ค.
Redis์์ ๋ฐ์ดํฐ๋ฅผ pop โ Redis์๋ ๋ ์ด์ ํด๋น ๋ฐ์ดํฐ๊ฐ ์์ โ
DB ์ ์ฅ ์ค ์์ธ ๋ฐ์ โ DB ํธ๋์ญ์ ๋กค๋ฐฑ
Redis๋ ๋กค๋ฐฑ๋์ง ์์ โ ๊ฒฐ๊ตญ ๋ฐ์ดํฐ ์ ์ค ๋ฐ์ โ ๏ธ
์ฆ, RDBMS์ธ MySQL์ @Transactional๋ก ๊ด๋ฆฌ๊ฐ ๋์ง๋ง Redis๋ ๊ด๋ฆฌ๋์ง ์๊ธฐ ๋๋ฌธ์ ๋ถ์ผ์น ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.
์ฌ๊ธฐ์ ๋ฑ์ฅํ๋ ๊ฒ์ด ๋ฐ๋ก TransactionSynchronization์ ๋๋ค.
์คํ๋ง์์๋ ํธ๋์ญ์
์ ์๋ช
์ฃผ๊ธฐ(lifecycle)์ ๋ง์ถฐ ํน์ ๋์์ ์ฝ๋ฐฑ(callback) ํํ๋ก ๋ฑ๋กํ ์ ์์ต๋๋ค.
์ด๋ฅผ ์ ๊ณตํ๋ ์ธํฐํ์ด์ค๊ฐ TransactionSynchronization์
๋๋ค.
๋ํ์ ์ธ ๋ฉ์๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
beforeCommit() : ์ค์ ์ปค๋ฐ ์ง์ ์ ์คํ
afterCommit() : ํธ๋์ญ์ ์ด ์ฑ๊ณต์ ์ผ๋ก ์ปค๋ฐ๋ ํ ์คํ
afterCompletion(int status) : ํธ๋์ญ์ ์ด ๋๋ ํ(์ฑ๊ณต/์คํจ ํฌํจ) ์คํ
์ฆ, DB ํธ๋์ญ์ ์ด ๋๋ ์์ ์ ๋ง์ถฐ ์ธ๋ถ ๋ฆฌ์์ค ์์ ์ ์์ ํ๊ฒ ์คํํ ์ ์๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํ๋ ๊ฒ์ด์ฃ .
afterCommit
DB ํธ๋์ญ์ ์ด ์ปค๋ฐ์ ์ฑ๊ณตํ์ ๋๋ง ์คํ๋ฉ๋๋ค.
์คํจ(rollback) ์์๋ ํธ์ถ๋์ง ์์ต๋๋ค.
afterCompletion
ํธ๋์ญ์ ์ด ๋๋๋ฉด ๋ฌด์กฐ๊ฑด ์คํ๋ฉ๋๋ค.
์ฑ๊ณต/์คํจ ์ฌ๋ถ๋ฅผ ํ๋ผ๋ฏธํฐ(STATUS_COMMITTED, STATUS_ROLLED_BACK)๋ก ํ์ธํ ์ ์์ต๋๋ค.
๐ Redis์์ pop ์์ ์ afterCommit์ ๋ฃ์ด์ผ ๋ฐ์ดํฐ ์ ์ค์ ๋ง์ ์ ์์ต๋๋ค.
์ค์ ์ฝ๋ ์ ์ฉ
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@Transactional
public void processTicket() {
Ticket ticket = redisQueue.peek(); // ์ผ๋จ peek์ผ๋ก ํ์ธ๋ง
ticketRepository.save(ticket);
// ํธ๋์ญ์
์ด ์ปค๋ฐ๋ ์ดํ์ pop ์คํ
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
redisQueue.pop(ticket.getId());
}
});
}
Redis์์๋ ๋ฐ์ดํฐ๋ฅผ peek๋ง ํ๊ณ โ ์์ง ์์ ํ๊ฒ ๋ณด๊ด
DB ์ ์ฅ ์๋
DB ํธ๋์ญ์ ์ปค๋ฐ ์ฑ๊ณต ์ โ afterCommit() ํธ์ถ โ Redis์์ ์ต์ข pop
DB ํธ๋์ญ์ ์คํจ ์ โ afterCommit() ์คํ๋์ง ์์ โ Redis ๋ฐ์ดํฐ ๊ทธ๋๋ก ์ ์ง
โ ์ด ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ ์ ์ค ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์์ต๋๋ค.
์ฐธ๊ณ
๐ก Redis์์๋ @Transactional์ฒ๋ผ ๋์ํ๊ฒ ๋ง๋๋ ์ต์
(setEnableTransactionSupport)์ด ์กด์ฌํฉ๋๋ค.
์ด ์ต์
์ ์ ์ฉํ๋ฉด @Transactional ์์์ redis๋ ๋กค๋ฐฑ์ด ๋์ด ์ด ์ต์
์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ถ๊ฐ์์
์์ด ๊ฐํธํฉ๋๋ค. (ํ์๋ TransactionSynchronization์์ ์ด ์ต์
์ผ๋ก ๋ฆฌํฉํ ๋ง ํ์์ต๋๋ค)