카프카 토픽을 생성했다가 지우고 같은 이름으로 다시 재 생성을 시도했다.
그러자, “Topic Already Exist”
라는 오류가 발생하였다.
나중에 알게된 사실이지만, 놀랍게도 기본 기능이라고 생각되는 카프카의 토픽 삭제는 종종 발생하는 에러이며, 때문에 카프카 토픽 삭제는 공식 문서에도 권고하지 않는다고 한다.
https://jusunglee.tistory.com/entry/토픽-삭제-Topic-delete
분명 카프카 토픽 리스트를 조회 할때는 지워져 있었는데 귀신이 사는건지 다시 생성하려고 하니 이런 에러 문구가 발생한다. 처음 삭제가 안됬을때, 당황하여 주키퍼에 직접 들어가 온라인 상황에서 메타데이터를 직접 지워줬다. 그리고 다시 토픽을 같은 이름으로 재생성 해주었다.
먼저 어떻게 왜 이런일이 생길 수 있었는지 궁금해서 추후에 찾아본 내용이다.
패스트 캠퍼스 카프카 강의를 참조한 내용 이다.
위의 그림에서와 같이 토픽삭제 명령어를 날리면,
delete queue에 들어가서 삭제가 됬다고 사용자에게 보여주는 시간(log marked as to be deleted)과 실제로 디스크에서 물리적으로 삭제 하는 시간(log deleted) 간에 차이가 있다.
삭제로 표시가 된 시간부터, 토픽 리스트로 조회가 불가능하기 때문에 완전히 지워진 것 처럼 보였던 것이다.
실제로 당시 서버에 남긴 로그를 확인 해보니, delete queue에 쌓인 파티션이 restart를 하면서 무한 루프에 빠져있었다. 하지만, log segment는 그대로 남아있었다. 또한 모든게 안지워진건 아니고 한 토픽의 몇몇 파티션만 부분적으로 안지워졌다는 사실도 발견했다.
추후에 재현 테스트를 통해서 알게된 사실...
주키퍼에 있는 정보만 제거 되면 토픽을 재생성 할수 있었다. 즉, 브로커는 주키퍼의 매타데이터만을 기준으로 동작한다. 실제로 자기의 디스크에 그게 있다는 사실은.. 확인을 안한다.. (멍청..해..)😱내가 기대 했던 카프카는 주키퍼와 브로커 간에 계속해서 서로 정보를 완전히 새로업데이트 해서 받는 것이였다. 하지만,,, 카프카는 그렇게 동작하지 않는다. 바뀐 정보만 업데이트 해서 부분적으로 메타데이터를 받아오고, 무조건 주키퍼 기준으로 그냥 맞춰버린다..
앞서서 Zookeeper 에서 토픽 정보를 지우고, 온라인 중에 같은 이름으로 다시 토픽을 생성했다고 했다.
그리고 log-segment는 수동으로 지우려고 시도했으나 지워지지 않는 이상한 현상이 있었다.
추후에 재현 테스트를 통해서 원인을 알게 되었다.
토픽을 삭제하고 같은 이름으로 재생성 할때, 제대로 삭제가 되지 않아서 주키퍼 메타 데이터를 강제로 지우게 되면, log-segment가 지워지지 않은 채로 남아 있다. 이때 나는 당연히 이미 있는 파일이니까 에러가 나겠지 라고 생각을 했었는데, 에러가 나지 않고 그렇다고 파일을 덮어 씌우고 새로 만들어 주지도 않는다는것을 알게 되었다.
원래 첫번째 만들었을때 같은 이름 토픽의 log-segment가 안지워지고 이미 있다면, 두번째 같은 이름으로 생성한 토픽은 이 log-segment를 그대로 사용한다. 파일의 생성일을 확인하여 알 수 있었다.
즉, 위에 log-segment는 이미 새로 만든 같은 이름의 토픽이 점유하여 사용중이기 때문에 지울수 없던것이다.
그리고 Out of Sync Replica
라는 에러 메세지가 몇일간 지속됬다.
아래는 고승범님의 카프카 책을 참조한 내용이다.
Out of Sync Replica: Observer는 리더로 부터 최신 정보를 요청한다. 리더는 최신 정보 요청이 일정시간 없으면 Out Of Sync Replica 처리.
Replication: 리더에게 팔로워가 요청. 일정시간동안 요청이 없으면 리더에게 요청 x. isr그룹 탈락.
즉, 이 메세지는 팔로워가 리더에게 일정시간동안 요청이 없어서 발생한 것이다.
왜 발생했을까 고민을 해보니..
온라인 중에 작업이 이루어 졌기 때문에, 카프카 페이지 캐시에 계속해서 그 전에 토픽에 대한 정보가 남아있었기 때문이다. 옵져버들은 주키퍼 메타 데이터를 최신화 해서 받지 못했고, 새로 바뀐 리더에게 요청을 보내지 못하고 있던 것이다.
추후에 재현 테스트를 통해서 이런 문제를 확인하였다.
재기동 전까지는 페이지 캐시 된(전 주키퍼) 상태이다. 즉, topic list를 조회하면, 디스크에만 있고 주키퍼에 없는데도 topic list가 조회가 된다. 심지어는 주키퍼 정보를 지웠어도 재기동 전까지는 topic list가 조회 되기도 한다. 이 모든 메타데이터의 차이는 재기동시 모든걸 불러오면서 맞춘다. 그래서 해소 된다. flush buffer가 되기 때문에...
1) OS가 자체 최적화를 하는 시간
2) 브로커를 재기동 할 때
이후, 다른 토픽의 파티션을 2개에서 3개로 증가 시키는 작업을 했다. 즉, 파티션 개수 정보를 주키퍼에게 보내고 새로운 주키퍼 매타데이터를 받아서 싱크를 맞추는 일이 일어난 것이다.
이때는 위에서 말한것 처럼, 전체 매타 데이터를 업데이트 하는게 아니라 부분적으로 파티션 정보만 교환을 한다.
아파치 카프카 공식문서의 에러에 메세지 설명 참조한 내용이다.
ISR Expiration: 주키퍼에 metadata는 ISR그룹에 포함되었다고 하는 브로커가 사실은 죽어 있는 경우
NotLeaderOrFollower: 리더나 팔로워가 없을 경우
두가지 에러의 발생 원인에 대해서 고민해 보았다.
1. “ISR Expiration”의 경우는 3번의 문제 상황처럼 브로커의 메타데이터가 옛날 버전이라면 이미 없는 리더를 참조하기 때문에 실제로 메세지를 보내니 리더가 없어(죽어있다고 판단) ISR Expiration에러 생길 여지가 있었다.
2. “NotLeaderOrFollower”의 경우 역시, 옛날 버전의 메타데이터를 가지고 있는 브로커라면 그 세그먼트는 리더도 팔로워도 아니기 때문에 발생 할 수가 있었다.
추후에 재현 테스트를 통해서 원인을 알게 되었다.
이 메세지는 브로커들끼리의 메타데이터 정보가 다르면 발생이 되기 시작한다.
즉, 하나의 브로커를 재기동 하면서 1대는 정상적인 상태가 되었는데 나머지 브로커들은 아직 옛날 메타정보를 가지고 있으면서 싱크가 맞지 않아서 발생하는것이다. 내 입장에서는 이미 지워지고 없어야 하는 토픽이 왜있니? 라는 메세지 이다.
1. 토픽을 삭제하고 깉은 이름으로 재생성은 되도록이면 하지 말자.
2. 꼭 해야 한다면, 반드시 브로커 전체 재기동을 염두해 두어야 한다.
3. 명령어로 삭제가 안되어 위와 같은 이슈가 생긴다면 주키퍼메타 데이터를 삭제하고, pub과 sub을 때고, 브로커를 내리고 log-segment를 깔끔하게 지우고 다시 전체 재기동을 해야만 페이지 캐시가 플러시 되고 주키퍼 정보에 맞춰서 다시 정상적인 상태로 브로커가 세팅이 되어 올라오고 카프카를 문제 없이 사용할 수 있다.
4. 주키퍼 메타데이터는 우리가 조회가 가능하니 모두가 잘 알고 있다. 하지만, 브로커에도 캐시되는 메타데이터가 존재한다. 도데체 어디서 확인 할수 있는지는 모르겠지만.. 그리고 브로커끼리 메타데이터가 싱크가 안맞아도 문제가 생기는것 같다.
이렇게까지 파고들어 본 이유?
사실 그냥 해결됬으니까 하고 넘어갈수도 있었겠지만, 학부 과정 중 시간이 없다는 핑게로 당장 일이 바쁘다는 이유로 해결만 하고 원인을 모른체 검색한대로 복사 붙여넣기 식의 debugging을 한 문제들이 수두룩 했다. 그리고 나중에 돌이켜 보니 원인을 모르고 해결만 하고 넘어간 문제들이 참 남는게 없다는 생각이 들었다. 그래서 같은 실수를 반복하지 말자라는 시작으로 앞으로는 문제의 원인을 정확히 알고 넘어가 하루 하루 성장하는 내가 되고 싶다.