Design Distributed Message Queue

ν˜„λŒ€ μ†Œν”„νŠΈμ›¨μ–΄ μ•„ν‚€ν…μ²˜λŠ” μž‘κ³  독립적인 μ„œλΉ„μŠ€λ‘œ κ΅¬μ„±λ˜λ©°, λ©”μ‹œμ§€ νλŠ” μ„œλΉ„μŠ€ μ‚¬μ΄μ˜ 톡신과 μ‘°μœ¨μ„ λ‹΄λ‹Ήν•˜κ²Œ λ˜λ©΄μ„œ λ‹€μŒκ³Ό 같은 이점을 μ œκ³΅ν•œλ‹€.

  • 결합도 μ™„ν™”(decoupling): μ»΄ν¬λ„ŒνŠΈ 사이 κ°•ν•œ 결합을 μ œκ±°ν•˜κ³ , 각 μ»΄ν¬λ„ŒνŠΈλ“€μ„ λ…λ¦½μ μœΌλ‘œ κ°±μ‹  κ°€λŠ₯

  • 규λͺ¨ ν™•μž₯μ„± κ°œμ„ : λ©”μ‹œμ§€ 큐에 데이터λ₯Ό μƒμ‚°ν•˜λŠ” μƒμ‚°μžμ™€ νμ—μ„œ λ©”μ‹œμ§€λ₯Ό μ†ŒλΉ„ν•˜λŠ” μ†ŒλΉ„μž μ‹œμŠ€ν…œ 규λͺ¨λ₯Ό νŠΈλž˜ν”½ λΆ€ν•˜μ— 맞게 μ‘°μ • κ°€λŠ₯

  • κ°€μš©μ„± κ°œμ„ : νŠΉμ • μ»΄ν¬λ„ŒνŠΈμ— μž₯μ• κ°€ λ°œμƒν•΄λ„ λ‹€λ₯Έ μ»΄ν¬λ„ŒνŠΈλŠ” 큐와 계속 톡신 κ°€λŠ₯

  • μ„±λŠ₯ κ°œμ„ : μƒμ‚°μžλŠ” 응닡을 기닀리지 μ•Šκ³  λ©”μ‹œμ§€λ₯Ό 전솑 ν•  수 있고, μ†ŒλΉ„μžλŠ” λ©”μ‹œμ§€κ°€ μžˆμ„ λ•Œλ§Œ μ²˜λ¦¬ν•˜κ²Œ λ˜μ–΄ 비동기 톡신을 μ›ν™œν•˜κ²Œ 함

μš”κ΅¬ 사항

  • λ©”μ‹œμ§€ ν˜•νƒœ: ν…μŠ€νŠΈ

  • λ©”μ‹œμ§€ 평균 크기: 수 KB

  • ν•˜λ‚˜μ˜ λ©”μ‹œμ§€κ°€ ν•˜λ‚˜μ˜ μ†ŒλΉ„μž / μ—¬λŸ¬ μ†ŒλΉ„μžμ—κ²Œ 전달 μ„€μ • κ°€λŠ₯

  • μƒμ‚°λœ μˆœμ„œλŒ€λ‘œ μ†ŒλΉ„

  • 데이터 지속성 2μ£Ό 보μž₯

  • λ©”μ‹œμ§€ 전달 방식 μ΅œμ†Œ ν•œ 번(at-least-once) / μ΅œλŒ€ ν•œ 번(at-most-once) / μ •ν™•νžˆ ν•œ 번(exactly-once) μ„€μ • κ°€λŠ₯

λ©”μ‹œμ§€ λͺ¨λΈ

κ°€μž₯ 널리 μ“°μ΄λŠ” λ©”μ‹œμ§€ λͺ¨λΈμ€ μΌλŒ€μΌ(point-to-point)κ³Ό λ°œν–‰-ꡬ독(publish-subscribe)이 μ‘΄μž¬ν•œλ‹€.

  • μΌλŒ€μΌ λͺ¨λΈ

    • 각 λ©”μ‹œμ§€λŠ” 였직 ν•œ μ†ŒλΉ„μžμ—κ²Œλ§Œ 전달

    • μ–΄λ–€ μ†ŒλΉ„μžκ°€ λ©”μ‹œμ§€λ₯Ό κ°€μ Έκ°”λ‹€λŠ” 사싀을 큐에 μ•Œλ¦¬λ©΄(acknowledge) ν•΄λ‹Ή λ©”μ‹œμ§€λŠ” νμ—μ„œ μ‚­μ œ

    • 큐에 μ €μž₯됐던 데이터 보관을 μ§€μ›ν•˜μ§€ μ•ŠμŒ

  • λ°œν–‰-ꡬ독 λͺ¨λΈ

    • ν•΄λ‹Ή 토픽을 κ΅¬λ…ν•˜λŠ” λͺ¨λ“  μ†ŒλΉ„μžμ—κ²Œ 전달

    • λ©”μ‹œμ§€λ₯Ό μ£Όκ³  받을 λ•Œ 토픽에 보내고 λ°›λŠ” 방식(ν† ν”½ = λ©”μ‹œμ§€μ˜ 주제 κ°œλ…)

토픽에 데이터가 λΆ€μ‘±ν•œ 경우

λ°œν–‰-ꡬ독 λͺ¨λΈμ€ λ©”μ‹œμ§€κ°€ 토픽에 μ €μž₯λ˜λŠ”λ°, λ³΄κ΄€λ˜λŠ” λ°μ΄ν„°μ˜ 양이 μ»€μ§€κ²Œ 되면 νŒŒν‹°μ…˜μ„ λ‚˜λˆ„μ–΄ ν•΄κ²°ν•  수 μžˆλ‹€.

  1. ν•˜λ‚˜μ˜ 토픽을 μ—¬λŸ¬ νŒŒν‹°μ…˜μœΌλ‘œ λΆ„ν• 

  2. λ©”μ‹œμ§€λ₯Ό λͺ¨λ“  νŒŒν‹°μ…˜μ— κ· λ“±ν•˜κ²Œ λ‚˜λˆ„μ–΄ 전솑

νŠΈλž˜ν”½μ΄λ‚˜ 데이터 양이 λ§Žμ•„μ§ˆ 수둝 νŒŒν‹°μ…˜μ΄ μ¦κ°€ν•˜κ²Œ λ˜λŠ”λ°, νŒŒν‹°μ…˜μ„ μœ μ§€ν•˜λŠ” μ„œλ²„λ₯Ό 보톡 브둜컀라고 λΆ€λ₯Έλ‹€.

개랡적 μ„€κ³„μ•ˆ

      메타데이터 μ €μž₯μ†Œ    μ‘°μ • μ„œλΉ„μŠ€
            ↕             ↕
μƒμ‚°μž -> 브둜컀 (데이터 μ €μž₯μ†Œ, μƒνƒœ μ €μž₯μ†Œ) -> μ†ŒλΉ„μž (μ†ŒλΉ„μž κ·Έλ£Ή)
  • μƒμ‚°μž: λ©”μ‹œμ§€λ₯Ό νŠΉμ • ν† ν”½μœΌλ‘œ 전솑

  • μ†ŒλΉ„μž κ·Έλ£Ή: 토픽을 κ΅¬λ…ν•˜κ³  λ©”μ‹œμ§€ μ†ŒλΉ„

  • 브둜컀: νŒŒν‹°μ…˜ μœ μ§€

  • 데이터 μ €μž₯μ†Œ: λ©”μ‹œμ§€λ₯Ό νŒŒν‹°μ…˜ λ‚΄ 데이터 μ €μž₯μ†Œμ— 보관

  • μƒνƒœ μ €μž₯μ†Œ: μ†ŒλΉ„μžμ˜ μƒνƒœ 보관

  • 메타데이터 μ €μž₯μ†Œ: ν† ν”½ μ„€μ • / ν† ν”½ 속성 λ“± μ €μž₯

  • μ‘°μ • μ„œλΉ„μŠ€

    • μ„œλΉ„μŠ€ 탐색: μ–΄λ–€ λΈŒλ‘œμ»€κ°€ μ‚΄μ•„μžˆλŠ”μ§€ 감지

    • 리더 μ„ μΆœ: 브둜컀 κ°€μš΄λ° ν•˜λ‚˜λ₯Ό 컨트둀러 μ—­ν• λ‘œ μ„ μΆœ(ν•œ ν΄λŸ¬μŠ€ν„°μ—λŠ” ν•˜λ‚˜ μ΄μƒμ˜ μ»¨νŠΈλ‘€λŸ¬κ°€ ν•„μš”)

데이터 μ €μž₯μ†Œ

λ©”μ‹œμ§€ 큐의 νŠΈλž˜ν”½ νŒ¨ν„΄μ€ λ‹€μŒκ³Ό κ°™λ‹€.

  • 읽기와 μ“°κΈ° 빈번

  • 순차적 읽기/μ“°κΈ°κ°€ λŒ€λΆ€λΆ„

  • κ°±μ‹ /μ‚­μ œ μ—°μ‚° λ°œμƒ X

생각해 λ³Ό 수 μžˆλŠ” μ„ νƒμ§€λ‘œλŠ” κ΄€κ³„ν˜•/λΉ„κ΄€κ³„ν˜• λ°μ΄ν„°λ² μ΄μŠ€κ°€ μ‘΄μž¬ν•˜μ§€λ§Œ, 읽기/μ“°κΈ°κ°€ λŒ€κ·œλͺ¨λ‘œ λΉˆλ²ˆν•˜κ²Œ λ°œμƒν•˜κΈ° λ•Œλ¬Έμ— μ ν•©ν•˜μ§€ μ•Šλ‹€.

μ“°κΈ° μš°μ„  둜그(Write-Ahead Log, WAL)

WAL은 μƒˆλ‘œμš΄ ν•­λͺ©μ΄ μΆ”κ°€λ˜κΈ°λ§Œ ν•˜λŠ” 일반 파일둜, λ©”μ‹œμ§€ 큐에 μ ν•©ν•œ 데이터 μ €μž₯μ†Œλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€.

  • μƒˆλ‘œμš΄ λ©”μ‹œμ§€κ°€ νŒŒν‹°μ…˜ 꼬리 뢀뢄에 μΆ”κ°€λ˜λŠ” 방식

  • μ ‘κ·Ό νŒ¨ν„΄μ΄ 순차적이기 λ•Œλ¬Έμ— λ””μŠ€ν¬ I/O μ΅œμ†Œν™”

  • 순차 접근이기 λ•Œλ¬Έμ— νšŒμ „μ‹ λ””μŠ€ν¬ ν™˜κ²½μ—μ„œλ„ λΉ λ₯Έ 데이터 μ ‘κ·Ό κ°€λŠ₯

λ©”μ‹œμ§€ 자료 ꡬ쑰

λ©”μ‹œμ§€ κ΅¬μ‘°λŠ” μƒμ‚°μžμ™€ λ©”μ‹œμ§€ 큐, μ†ŒλΉ„μž μ‚¬μ΄μ˜ 계약이라고 λ³Ό 수 μžˆλ‹€.

ν•„λ“œλ°μ΄ν„° μžλ£Œν˜•μ„€λͺ…

key

byte[]

νŒŒν‹°μ…˜μ„ μ •ν•˜λŠ” ν‚€

value

byte[]

λ©”μ‹œμ§€μ˜ λ‚΄μš©(=payload)

topic

string

λ©”μ‹œμ§€κ°€ μ†ν•œ ν† ν”½

partition

integer

λ©”μ‹œμ§€κ°€ μ†ν•œ νŒŒν‹°μ…˜

offset

long

νŒŒν‹°μ…˜ λ‚΄ λ©”μ‹œμ§€μ˜ μœ„μΉ˜

timestamp

long

λ©”μ‹œμ§€ 생성 μ‹œκ°„

size

integer

λ©”μ‹œμ§€ 크기

crc

integer

μˆœν™˜ 쀑볡 κ²€μ‚¬μ˜ μ•½μžλ‘œ, 데이터 무결성 보μž₯에 μ‚¬μš©

일괄 처리

μƒμ‚°μž / μ†ŒλΉ„μž / λ©”μ‹œμ§€ νλŠ” λ©”μ‹œμ§€λ₯Ό 가급적 일괄 μ²˜λ¦¬ν•˜κ²Œ λ˜λŠ”λ°, 일괄 μ²˜λ¦¬λŠ” μ‹œμŠ€ν…œ μ„±λŠ₯에 λ§Žμ€ 영ν–₯을 λ―ΈμΉœλ‹€.

  • ν•œ 번의 λ„€νŠΈμ›Œν¬ μš”μ²­μœΌλ‘œ μ²˜λ¦¬ν•˜μ—¬ λ„€νŠΈμ›Œν¬ 왕볡 λΉ„μš© μ™„ν™”

  • μ—¬λŸ¬ λ©”μ‹œμ§€κ°€ ν•œ λ²ˆμ— λ‘œκ·Έμ— 기둝되면, 큰 규λͺ¨μ˜ 순차 μ“°κΈ° 연산이 λ°œμƒν•˜μ—¬ λ””μŠ€ν¬μ— μ—°μ†λœ κ³΅κ°„μœΌλ‘œ 기둝됨(λŒ€μ—­ν­ μƒμŠΉ)

ν•˜μ§€λ§Œ ν•œ λ²ˆμ— λ§Žμ€ 양을 μ²˜λ¦¬ν• μˆ˜λ‘, λ©”μ‹œμ§€ 큐의 지연 μ‹œκ°„μ΄ μ¦κ°€ν•˜κ²Œ 되기 λ•Œλ¬Έμ— μ μ ˆν•œ κ· ν˜•μ„ μ°Ύμ•„μ•Ό ν•œλ‹€.

ν‘Έμ‹œ vs ν’€

λ©”μ‹œμ§€ νλŠ” ν‘Έμ‹œ(push)와 ν’€(pull) λ°©μ‹μœΌλ‘œ λ©”μ‹œμ§€λ₯Ό μ†ŒλΉ„ν•  수 μžˆλ‹€.

  • ν‘Έμ‹œ λͺ¨λΈ: λΈŒλ‘œμ»€κ°€ μ†ŒλΉ„μžμ—κ²Œ λ©”μ‹œμ§€λ₯Ό μ „λ‹¬ν•˜λŠ” 방식

    • μ¦‰μ‹œ μ†ŒλΉ„μžμ—κ²Œ μ „λ‹¬ν•˜μ—¬ 지연 μ‹œκ°„ κ°μ†Œ

    • μ†ŒλΉ„μž λ©”μ‹œμ§€ 처리 속도가 μƒμ‚°μž 생성 속도보닀 느린 경우 높은 λΆ€ν•˜ κ°€λŠ₯μ„± 쑴재

    • μƒμ‚°μž 생성 속도에 맞좰 μ†ŒλΉ„μžμ˜ μ»΄ν“¨νŒ… μžμ›μ„ μ€€λΉ„ν•΄ 두어야 함

  • ν’€ λͺ¨λΈ: μ†ŒλΉ„μžκ°€ 메세지λ₯Ό κ°€μ Έκ°€λŠ” 방식

    • λ©”μ‹œμ§€ μ†ŒλΉ„ 속도λ₯Ό μ•Œμ•„μ„œ κ²°μ •ν•˜μ—¬ μ‹€μ‹œκ°„ / 일괄 처리 선택 κ°€λŠ₯

    • μ†ŒλΉ„ 속도가 λŠλ¦¬λ”λΌλ„ λΆ€ν•˜κ°€ 생기지 μ•ŠμŒ

    • μŒ“μΈ λͺ¨λ“  λ©”μ‹œμ§€λ₯Ό ν•œ λ²ˆμ— κ°€μ Έκ°€ 일괄 처리 κ°€λŠ₯

    • λΈŒλ‘œμ»€μ— λ©”μ‹œμ§€κ°€ 없어도 λΆˆν•„μš”ν•œ 풀링 μš”μ²­μœΌλ‘œ μžμ› λ‚­λΉ„ κ°€λŠ₯μ„± 쑴재(λ‘± ν’€λ§μœΌλ‘œ 문제 μ™„ν™”)

λ©”μ‹œμ§€ 전달 방식

λ©”μ‹œμ§€ 전달 방식은 μ΅œμ†Œ ν•œ 번(at-least-once) / μ΅œλŒ€ ν•œ 번(at-most-once) / μ •ν™•νžˆ ν•œ 번(exactly-once)으둜 λ‚˜λ‰œλ‹€.

  • μ΅œλŒ€ ν•œ 번: λ©”μ‹œμ§€κ°€ 전달 κ³Όμ •μ—μ„œ μ†Œμ‹€λ˜λ”λΌλ„ λ‹€μ‹œ μ „λ‹¬ν•˜μ§€ μ•ŠμŒ

  • μ΅œμ†Œ ν•œ 번: λ©”μ‹œμ§€κ°€ λΈŒλ‘œμ»€μ—κ²Œ μ „λ‹¬λ˜μ—ˆμŒμ„ λ°˜λ“œμ‹œ ν™•μΈν•˜λŠ” λ°©μ‹μœΌλ‘œ, λ©”μ‹œμ§€ μ†μ‹€λ˜μ§€ μ•ŠμŒ

  • μ •ν™•νžˆ ν•œ 번: μ„±λŠ₯ 및 κ΅¬ν˜„ λ³΅μž‘λ„κ°€ 높은 λ°©μ‹μœΌλ‘œ, μ€‘μš”ν•œ 데이터 전달에 μ‚¬μš©

참고자료

Last updated