및 데이터 저장 카프카 rocketMQ

카프카 버전 : 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 바이트.

나는 드문 드문 알고, 또는 항목에 해당 메시지가 없습니다. 메시지는 두 개의 문서로 할 별도로 저장됩니다? 뒷면 봐

 

추천

출처www.cnblogs.com/allenwas3/p/11505242.html