Skip to main content Link Menu Expand (external link) Document Search Copy Copied

stream 을 샤딩할려고 했는데 생각해보니까 kafka 처럼 파티션을 컨슈머에 할당하는 리밸런싱을 직접 해줘야할 것 같습니다. 그러니까 샤딩된 stream 당 하나의 파드내 컨슈머에서 읽을 수 있도록 해야합니다. 이유는 간단한데, 만약 샤딩된 stream 이 100개 있고 pod 가 10개면 각 pod 당 100개씩 다 읽어야합니다. 스레드가 100개면 충분한데 쓸데없이 900개가 추가로 돌아가는거죠. 그래서 사실 샤딩된 stream 개수가 많이 않아도 되고 내부 병렬처리로 일부 돌리면 완화가 되긴 합니다. 예로 100개의 동시성을 원하면 stream 을 10개로 샤딩하고, 각 컨슈머에서 10개의 스레드를 돌려서 처리하는 식으로요.

실패 메세지 처리를 위한 PEL 관리는 더 큰 문제입니다. stream-A 의 실패 메세지 처리를 여기저기에서 순서없이 처리 할 수 있게 되는거죠. 즉, pod-1 에서 stream-A 의 실패 메세지 1번을 처리하고 있을 때, pod-2 에서 이후 stream-A 의 실패 메세지 2번을 처리할 수 있게 됩니다. 이러면 중복처리가 발생합니다. 즉, 실패 메세지 처리를 하나의 스레드에서 처리를 해줘야지만 “순서처리” 가 가능하기때문에 하나의 컨슈머에 정확히 할당해주는게 중요합니다.

즉, 메시지 순차 처리 동시성 향상 을 위한 샤딩은 추천하지 않습니다. sharded-streamKey 별 컨슈머 오너쉽 관리도 설계해줘야합니다. 단 순서가 필요없고 Big Key 이슈해결 & Cluster 에서 Stream 분배 를 위한 샤딩은 적극추천합니다. 전송할 때 어플리케이션에서 HASH(message-id) mod n = 0 ~ n-1 로 해당 streamKey 에 메세지를 전송하도록 설계해주면 됩니다.

1 consumer = 1 sharded stream key 오너쉽 할당은 찾아보니 Redis streams partitioning - Google Group 7년 전 대화에서도 비슷한 논의가 있었네요. 결국 샤딩된 streamKey 별로 컨슈머 할당 관리는 직접 해줘야한다고 하고 아직 변한 건 없는 것 같습니다.

샤딩 한계점을 종합해보면,

  1. 메세지 순차 처리를 위한 샤딩을 설계한다면 -> 샤딩된 streamKey 별로 컨슈머 오너쉽 관리 및 리밸런싱 로직 추가 설계 필요해서 이럴 바엔 kafka 쓰는게 오버헤드가 적습니다.
  2. 필요한 스레드 개수는 (consumer pod 개수) * (stream 샤딩 개수) 라서 stream 개수를 적절히 조절해야합니다. 멀티파드 환경에서는 stream 개수 == 동시성 개수 로 맞추는건 매우 비효율적입니다(stream 개수 적절히 조절 후 내부적으로 병렬 처리하도록 해야함).

일단 샤딩 개수 산출

높은 확률로 3개에 균등하게 streamKey 분배할려면 몇개 stream Key 필요할까?

1

3개 샤드에 99% 로 고르게 분포시킬려면 streamKey 샤딩은 7.9 로 최소 8개 정도면 충분할 것 같습니다. 뭐 만들고 나서 한군데 4개씩 들어가있으면 지우고 다시 셋업하면 되니까 크게 상관은 없긴 합니다.