카프카 버전 : 1.1.1
파티션은 폴더, 파일 저장 데이터 세그먼트, 세그먼트 기본 1G에 해당합니다.
구역 폴더 :
세그먼트 파일 :
어떤 이름 세그먼트?
논리의 카프카 롤 세그먼트 : kafka.log.Log 번호 롤
/ ** * 현재 logEndOffset로 시작하는 새 활성 세그먼트에 로그를 통해 롤. * 이것은 현재 포함 항목의 수의 정확한 크기로 인덱스를 손질합니다. * * @ 반환 새롭게 겹쳐서 세그먼트 * / DEF 롤 (expectedNextOffset : 옵션 [롱] = 없음) LogSegment = { maybeHandleIOException (S "중 오류 디렉터리 $에서 $ topicPartition 대한 로그 세그먼트 압연 {dir.getParent}" ) { 브로 시작 =의 time.hiResClockMs을 (를) 잠금 동기화 { checkIfMemoryMappedBufferClosed () 발 newOffset= math.max (expectedNextOffset.getOrElse (0L ) logEndOffset) // 00000000000030898257.log文件 브로 로그 = Log.logFile (DIR, newOffset) 경우 (segments.containsKey (newOffset)) { // 같은 염기 세그먼트는 이미 오프셋 존재하고로드 하는 경우 (activeSegment.baseOffset == newOffset && activeSegment.size == 0 ) { // 우리는 보았다이 발생합니다 (카프카-6388) shouldRoll ()가 true를 반환 한 후 // 크기 제로 인해의 활성 세그먼트 인덱스 중 하나가 (때문에 _maxEntries == 0) "전체"입니다. 경고 (들 + "시작 오프셋 $ newOffset으로 새 로그 세그먼트를 롤 시도" S '= 최대 (LEO = $ logEndOffset = $ expectedNextOffset 오프셋 제공됨) 이미 동안 "+ 들 "이 존재하고 타임 인덱스의 크기를 0으로 크기와 활성 $ {} activeSegment.timeIndex.entries "+ S "사이즈 의 인덱스 오프셋 :. $ {activeSegment.offsetIndex.entries을} " ) deleteSegment (activeSegment) } 다른 { 던져 새로운 KafkaException (들은 "시작 오프셋 $ newOffset와 주제 파티션 $의 topicPartition에 대한 새 로그 세그먼트를 롤하려고"+ 의 동안 "= 최대가 (LEO = $ logEndOffset = $ expectedNextOffset 오프셋 제공) 그것은 이미 존재합니다. 의 "세그먼트 $ {segments.get (newOffset)}." ) } } 다른 경우 (! segments.isEmpty && newOffset < activeSegment.baseOffset) { 던져 새로운 KafkaException을 ( 들 + "로 주제 파티션 $의 topicPartition에 대한 새 로그 세그먼트를 롤 시도" 의 ( "시작 옵셋 $ newOffset는 = 최대 오프셋하여 제공된 = $ expectedNextOffset, LEO = $ logEndOffset) 활성 세그먼트 $의 activeSegment의 시작 옵셋보다 낮은 " ) } 다른 { 브로 offsetIdxFile = offsetIndexFile (DIR, newOffset) 브로 timeIdxFile = timeIndexFile (DIR, newOffset) 발 txnIdxFile = transactionIndexFile (DIR, newOffset) 에 대한 (파일 <- 목록 (로그 파일, offsetIdxFile, timeIdxFile, txnIdxFile) 의 경우 file.exists) { 경고 (들 "새로 출시 세그먼트 파일 $ {파일 .getAbsolutePath}은 이미 존재; "먼저 삭제 ) Files.delete이 (file.toPath) } . 옵션 (segments.lastEntry) .foreach이 (_ getValue.onBecomeInactiveSegment은 ()) } // 회복을 촉진하기 위해 생산자 상태의 스냅 샷을 . 이 스냅 샷을하는 것이 유용하다 //이것은 우리가 시작하여 세그먼트를 복구 할 수 있도록하기 때문에 오프셋 새로운 세그먼트에 맞춰 오프셋 // 해당 스냅 샷 파일과 세그먼트 데이터를 스캔. 오프셋 (offset) 세그먼트 기반하기 때문에 //이 실제로 앞서 (오프셋 로그 말에 해당) 현재의 오프셋 (offset) 생산 상태 말 할 수있다, // 우리는 수동으로 스냅 샷을하기 전에 여기 오프셋 상태를 우선합니다. producerStateManager.updateMapEndOffset (newOffset) producerStateManager.takeSnapshot () 브로 세그먼트 = LogSegment.open (DIR, baseOffset = newOffset, 설정, 시간 =시간은 fileAlreadyExists는 = 거짓 , initFileSize = initFileSize, 미리 할당 = config.preallocate) addSegment (세그먼트) // 우리는 메타 로그 롤의 위치 오프셋 데이터 세그먼트베이스를 추가하고 업데이트해야한다. // 변경하지 마십시오 오프셋 다음. updateLogEndOffset (nextOffsetMetadata.messageOffset는) // 이전 세그먼트의 비동기 플러시 예약 scheduler.schedule (( "플러시 - 로그") => 플러시 (newOffset), 지연 = 0L ) 정보 (들"{) time.hiResClockMs (- 시작} $의 오프셋 (offset) $ newOffset에서 새 로그 세그먼트를 압연 밀리." ) 세그먼트 } } }
당신은 세그먼트 파일 이름으로 현재 logEndOffset를 사용하여 볼 수 있습니다. 파일 이름으로 첫 번째 메시지의 오프셋 (offset)와 그 세그먼트 파일.
동일한 이름의 로그 파일의 인덱스 파일을 인덱스 파일 콘텐츠 / 위치, 2 INT, 총 8 바이트를 포함하는 입력 오프셋이있다.
kafka.log.OffsetIndex 번호의 APPEND
/ ** * 인덱스의 지정된 오프셋 / 장소 쌍에 대한 항목을 추가. 이 항목은 더 큰 모든 후속 항목보다 오프셋이 있어야합니다. * / DEF 추가 (오프셋 : 긴 위치 : INT) { inLock (잠금) { (필요 ! isFull, "전체 인덱스에 추가 할 시도 (크기 ="+ _entries를 + ".)" ) 경우 (_entries == 0 > 오프셋 || _lastOffset) { 추적 (들 "$에 추가 인덱스 항목에 $ 오프셋 => $ 위치 {file.getAbsolutePath을}" ) // 相对偏移量 - mmap.putInt ((오프셋 .toInt) baseOffset를) // 消息在로그文件中的物理地址 mmap.putInt (위치) _entries+ = 1 _lastOffset =는 오프셋 (_entries를 필요 * entrySize == mmap.position () 엔트리 + + mmap.position () + ".", "인덱스 항목이지만 파일 위치는" ) } 다른 { 던져 새로운 InvalidOffsetException을 (들 " 추가하려고 오프셋 $ 엔트리를 위치 시키도록 ($ 오프셋)에는 "+보다 큰 S "마지막 오프셋 첨부 ($ {} _ lastOffset)에 $ {} file.getAbsolutePath. " ) } } } 없다
지도 A의 해적 :
http://rocketmq.cloud/zh-cn/docs/design-store.html
RocketMQ 다른 저장 및 카프카는 commitlog 및 consumequeue으로 구분 :
모든 메시지는 기본 commitlog 1G 세그먼트, 오프셋 물리적으로 지정된 파일 이름, 주제 commitlog 파일에 저장됩니다.
그리고 인덱스 정보는 consumequeue / 주제 / 큐 디렉토리 항목에 저장되어있는 고정 된 20 바이트, 4 바이트, 8 바이트 태그 해시 코드의 메시지 길이의 실제 오프셋을 commitlog 8 바이트.
나는 드문 드문 알고, 또는 항목에 해당 메시지가 없습니다. 메시지는 두 개의 문서로 할 별도로 저장됩니다? 뒷면 봐