MESI 프로토콜
MESI 프로토콜은 멀티코어 CPU 환경에서 캐시 일관성(Coherency)을 유지하기 위한 프로토콜이다.
MESI는 각각의 캐시 라인이 4가지 상태 중 하나를 가지도록 해서, 각 CPU 코어가 동일한 메모리에 주소에 접근하더라도 데이터 불일치를 막아주는 방식이다.
MESI의 4가지 상태는 다음과 같다:
Modified (수정) | 이 캐시 라인만 최신 데이터를 가지고 있고, 메모리에는 반영 안 됨 | 다른 캐시에 없음 + dirty 상태 |
Exclusive (배타적) | 이 캐시 라인만 데이터 가지고 있고, 메모리와 동일 | 다른 캐시에 없음 + clean 상태 |
Shared (공유) | 여러 캐시가 동일한 데이터를 가지고 있음 + 메모리와 동일 | 다른 캐시에도 있음 + clean 상태 |
Invalid (무효화) | 더 이상 유효하지 않은 데이터 | 다른 캐시에서 수정됨 등으로 무효 처리됨 |
Read Cache Miss -> 다른 캐시에 데이터가 없으면 E, 있으면 S
Write Cache Miss -> 다른 캐시에 데이터 있으면 그 캐시들은 I로 전환 -> 현재 캐시는 M
Read Hit -> 현재 상태가 E,S,M이면 그냥 읽음
Write Hit -> S 상태에서 쓰면 -> 다른 캐시들 무효화 -> M으로 변환
예시:
CPU1이 메모리 A를 읽음 -> 캐시에 없음 -> 메인 메모리에서 읽어옴 -> 상태는 E
CPU2도 A를 읽음 -> CPU1의 A는 S, CPU2의 A도 S
CPU2가 A를 씀 -> CPU1의 A는 I, CPU2의 A는 M
CPU1이 다시 A를 읽음 -> CPU2로부터 snooping통해 data 받음 -> 둘다 S
(snooping은 cpu끼리 도청(?)해서 캐시 상태를 훔쳐보는.. 그런느낌)
이로써
쓰기 충돌을 방지하고(M상태는 오직 한 개의 캐시 라인만 가질 수 있어서 write-update 필요없음, 나머지는 I상태 됨),
불필요한 메모리 접근을 줄이고(E상태 덕분에 메모리 쓰기 없이 연산 가능),
캐시 일관성을 유지할 수 있다(snooping + 상태 전이).
인텔은 대부분 MESI, AMD는 MOESI이다.
(MOESI는 Owner 상태가 추가된 건데.. 이건 dirty + 공유를 가능하게 해주는 상태다.
CPU 캐시끼리 메모리의 관여 없이 최신 데이터를 주고받는 것이고 버스를 아끼고 메모리 병목을 줄임)
읽기 요청만 있는 경우
MESI 프로토콜 상에서 데이터는 Shared상태로 유지되며, 여러 코어가 동시에 읽는게 허용된다.
캐시 무효화나 동기화 없이 데이터를 빠르게 조회할 수 있으므로 하드웨어 레벨에서는 큰 부하가 없다.
쓰기 요청이 존재하는 경우
하지만 쓰기 요청이 섞이면 상황이 달라진다. 한 코어가 특정 Key값을 수정하는 순간, MESI 프로토콜은 해당 캐시 라인의 상태를 Modified로 바꾸고 동시에 다른 모든 코어의 동일 캐시 라인을 Invalid상태로 만든다. 이게 cache invalidation이다.
만약 여러 코어가 이 데이터를 반복해서 읽고 쓰게 되면, 캐시 라인이 여러 코어 사이에서 계속 이동하며 상태 전환을 반복한다.
이걸 cache line bouncing이라고 한다. 캐시 라인 자체가 여러 코어 간을 바운스볼처럼 오가면서 성능이 급격히 저하된다.
되게 생각해볼 게 많은 주제다. 읽기 요청이 100번, 쓰기 요청이 단 1번만 발생해도 1의 쓰기가 모든 걸 흔들 수 있다.
MESI 프로토콜에서는 단 한번의 쓰기만 발생해도 그 데이터의 모든 Shared 캐시 상태가 Invalid로 바뀌어야 하고, 그러면 다음 읽기는 모두 메모리 접근이나 캐시 재로딩을 필요로 하고, 결국 전체 읽기 처리 성능도 다 같이 끌어내려버리게 된다.
회고
원래는 Redis Hot Key와 연결지어 가볍게 생각해보려 했는데 생각보다 내용이 방대하고 재밌다..
그리고 Hot Key가 발생하면 MESI 프로토콜이 동작할 줄 알고......알았는데
생각해보니 Redis는 단일스레드라 MESI가 필요없다..(아닌가?) 멀티코어 환경에서 간접적으로 트리거될 순 있을 듯
'개인 공부용 > ㅇㅅㅇ' 카테고리의 다른 글
Spring Security에서 JWT를 Stateless하게 사용하기 (0) | 2025.04.20 |
---|---|
알림 구현(3) 확장성을 고려한 리팩토링: 전략패턴 (0) | 2025.04.12 |
알림 구현(2) 웹소켓 세션 다중 클라이언트, 다중 인스턴스 환경 (0) | 2025.04.11 |