Comprensión en profundidad de la serie Kafka (cuatro): almacenamiento de replicación de Kafka y proceso de procesamiento de solicitudes

Directorio de artículos de serie

Artículos de la serie de guías autorizadas de Kakfa

Prefacio

Esta serie es mi transcripción y pensamientos después de leer el libro "La guía definitiva de Kafka".

texto

Membresía de clúster

Kafka usa zookeeper para mantener la relación entre los miembros del clúster. Cada corredor tiene un identificador único (es decir, clientId, que también se puede generar automáticamente).

  1. Al iniciar un corredor, el corredor registra su ID creando un nodo temporal en zookeeper. La ruta es: / brokers / ids. Por lo tanto, cuando el corredor se une o sale del clúster, estos miembros recibirán notificaciones relevantes.
  2. Si ha iniciado un corredor con ID A, también debe iniciar un corredor con ID A. Entonces el corredor obtendrá un error. ( No pueden existir dos corredores con el mismo ID al mismo tiempo )
  3. Si el corredor mencionado anteriormente con ID A se cierra por completo y luego se inicia un nuevo corredor (ID también A), el nuevo corredor se unirá inmediatamente al clúster y tendrá la misma partición y tema que el corredor anterior.

Controlador

El controlador es esencialmente un corredor, pero en comparación con otros corredores ordinarios, también tiene la función de elección de líder de partición.

¿Cuál es el estándar producido por el controlador?

El primer inicio será un dispositivo de control de broker kafka exitoso , creará un nodo / controlador temporal en el guardián del zoológico.

Cuando se inicien los intermediarios posteriores, también intentarán crear nodos / controladores temporales en zookeeper, pero recibirán una excepción de "nodo ya existe", y luego se darán cuenta de que ya hay un controlador en el clúster, y luego Zookeeper Watch Los objetos se crearán en el nodo del controlador para que puedan ser notificados de los cambios en este nodo.

Si el controlador y el cuidador del zoológico están desconectados, ¿qué pasará después?

1. Luego, el nodo temporal de zookeeper desaparecerá.
2. A continuación, se notificará a otros corredores del clúster de la desaparición del nodo controlador a través del objeto de observación. Intentarán convertirse en el nuevo controlador.
3. Luego siga los estándares anteriores, el primer intermediario que cree exitosamente un nodo temporal en zookeeper se convertirá en el nuevo controlador. Una vez que el nodo temporal se haya creado exitosamente, otros intermediarios que intenten convertirse en un nuevo controlador recibirán las excepciones correspondientes.

¿Habrá dos controladores? Si es así, ¿qué debo hacer?

El primero es sí.
Ejemplo: Supongamos que se considera que el controlador original está inactivo debido a la congestión de la red y, una vez que el nodo temporal desaparece, otros corredores no comenzarán a competir para convertirse en el controlador. Cuando se crea un nuevo controlador, la red del controlador anterior vuelve a la normalidad. Entonces hay un problema típico:
problema de cerebro dividido

¿Cómo resuelve Kafka el problema del cerebro dividido?

1. Regrese a los pasos anteriores Si un controlador cuelga y otros corredores eligen un nuevo controlador, deben crear un nuevo objeto de vigilancia en el nuevo controlador.

2. Luego, el nuevo controlador obtendrá una nueva época de controlador con un valor mayor a través de la operación de incremento condicional de zookeeper , que puede entenderse como la clave principal de la base de datos.

3. Luego, si otros corredores reciben posteriormente un mensaje que contiene la época anterior del controlador después de conocer la última época actual del controlador, serán ignorados.


Replicación de Kafka

La función de replicación de Kafka puede considerarse un núcleo de la arquitectura de Kafka.
A continuación se ofrece un breve resumen de la estructura organizativa de Kafka.

  1. Utilice temas para organizar los datos.
  2. Cada tema se divide en varias particiones. (La partición puede entenderse como compartir la cantidad de datos y almacenarlos por separado)
  3. Hay varias copias de cada partición. (Copiar puede entenderse como copiar datos, utilizado para una alta fiabilidad)
  4. La copia se guarda en el corredor.

Tipo de copia:

  1. Copia de jefe

1. Como se mencionó anteriormente, cada partición puede tener varias copias.
2. Pero solo una copia es la copia del jefe.
3. Todas las solicitudes de productores y consumidores pasan por la copia líder.

  1. Copia de seguidor

1. Todas las copias que no sean la copia del líder son copias de los seguidores.
2. La copia del seguidor no procesa ninguna solicitud.
3. Su única función es copiar los mensajes de la copia del líder para mantener la coherencia. Y cuando la copia del jefe colapse, elige una nueva copia del jefe.


Aquí hay una explicación de por qué la copia del seguidor no procesa ninguna solicitud.

1. Suponga que un usuario realiza la misma solicitud de consumo dos veces seguidas. Hay dos copias secundarias, una A y una B, y A se ha sincronizado con la copia maestra, pero B no.
2. Por primera vez leído de la copia del seguidor A, el mensaje leído es hola.
3. La segunda lectura de la copia del seguidor B, el mensaje leído es hola mundo.
4. Entonces viene el problema, los datos leídos por segunda vez son datos sucios, y los datos reales son A, lo que causa inconsistencia en los datos. Por lo tanto, Kafka permite directa y simplemente que todas las solicitudes de los consumidores pasen por la réplica maestra.


Entonces vuelve el problema: si una copia maestra falla y se eligen las otras copias esclavas, ¿cómo garantizar que los datos guardados en la copia elegida estén completos?

Antes de responder a esta pregunta, permítanme hablarles de dos conceptos, copias sincrónicas o no sincronizadas.

  1. Copia no sincronizada

1. En primer lugar, la siguiente premisa, para mantener la sincronización con la copia del líder, los seguidores deben enviar una solicitud de datos a la copia del líder. (Puede considerarse como una solicitud del consumidor).
2. El líder envía el mensaje de respuesta al seguidor, y estos mensajes de solicitud contienen el desplazamiento que el seguidor desea recibir el mensaje, y el desplazamiento está en orden.
3. Si el seguidor no solicitó ningún mensaje en 10 segundos o no solicitó los datos más recientes en 10 segundos, esta copia se considera desincronizada.
Nota: Este 10 se puede especificar configurando el parámetro replica.lag.time.max.ms

  1. Copia sincronizada

Las noticias obtenidas por la solicitud continua son siempre las más recientes, dicha copia se denomina copia sincronizada.

Luego, volvamos a la pregunta anterior: ¿cómo garantizar que los datos estén completos?

En Kafka, cuando falla el líder, solo se puede seleccionar la copia sincronizada como el nuevo líder.


Solicitud de procesamiento

  1. Cada corredor ejecutará un subproceso de aceptación en cada puerto que supervisa. Este subproceso creará una conexión y entregará la conexión al subproceso del procesador para su procesamiento.
  2. El hilo del procesador es responsable de obtener los mensajes de solicitud del cliente, colocarlos en la cola de solicitudes y luego obtener los mensajes de respuesta de la cola de respuestas y enviarlos al cliente.

El proceso general es el siguiente:
Inserte la descripción de la imagen aquí
Hay dos tipos comunes de subprocesos de E / S en la figura: (los subprocesos de E / S son responsables de procesar los mensajes en cola)

  1. Solicitud de producción: la solicitud enviada por el productor, incluido el mensaje que el cliente desea escribir al corredor.
  2. Solicitud de obtención: la solicitud enviada cuando las copias del consumidor y seguidor necesitan leer el mensaje del corredor.

Aquí debemos tener en cuenta que las dos solicitudes anteriores deben enviarse a la copia líder de la partición.

Pregunta 1: ¿Qué sucede si un corredor recibe una solicitud para una partición específica, pero el líder de la partición está en otro corredor ?

Respuesta: Entonces, el cliente que envió la solicitud recibirá una respuesta de error "líder sin partición".

Por lo tanto, el cliente de Kafka debe ser responsable de enviar la solicitud al corredor correcto.

Pregunta 2: ¿Cómo sabe el cliente dónde enviar la solicitud?

Respuesta: El cliente usa el tipo de solicitud de la solicitud de metadatos .
El contenido de la solicitud incluye una lista de temas en los que está interesado el cliente. Generalmente, el mensaje de respuesta del lado del servidor especificará las particiones incluidas en el tema, la distribución de las particiones, qué copia es la líder, etc.
Además, las solicitudes de metadatos se pueden enviar a cualquier corredor, porque todos los corredores han almacenado esta información en caché.


Solicitud de producción

Mirando hacia atrás en el contenido anterior, el productor tiene una configuración de parámetros llamada acks

  1. acks = 1: Siempre que el líder reciba el mensaje, el mensaje se considera escrito con éxito.
  2. acks = all: todas las réplicas sincronizadas deben recibir el mensaje para que se consideren correctas.
  3. acks = 0: después de que el productor envía un mensaje, no es necesario esperar a que el corredor responda.

Luego, cuando el corredor que contiene una copia del líder recibe una solicitud de producción, tomará los siguientes pasos para la solicitud:

  1. Verificación de permisos: ¿El usuario que envía los datos tiene permiso para escribir el asunto?
  2. Verificación de parámetros: ¿Es válido el valor de acks? (Solo 0, 1, todos)
  3. Verificación de réplicas: si acks = all, ¿hay suficientes réplicas sincronizadas para garantizar que el mensaje se haya escrito de forma segura? (Si el número es insuficiente, Kafka puede negarse a escribir)
  4. Escritura de mensaje: escribe en el disco local.
  5. Verifique los parámetros: después de que el mensaje se escriba en el líder de la partición , verifique el parámetro acks. Si acks = 0 o 1, el corredor devuelve una respuesta de inmediato. Si acks = all, guarde la solicitud en un búfer del purgatorio , hasta que el líder encuentre que todas las copias de los seguidores han copiado el mensaje, la respuesta será devuelta al cliente.

Obtener solicitud

La forma en que el corredor procesa las solicitudes de recuperación es muy similar a la forma en que se generan las solicitudes. En una frase: el cliente envía una solicitud al corredor de un mensaje con un desplazamiento específico en la partición del tema.

Ponga la imagen primero: los
Inserte la descripción de la imagen aquí
pasos generales son:

  1. La solicitud se envía al líder de partición designado y luego el cliente consulta los metadatos para asegurarse de que la ruta solicitada sea correcta.
  2. Compruebe si la solicitud es válida: si el desplazamiento existe en la partición, etc.
  3. Si existe el desplazamiento solicitado, el corredor lee el mensaje de la partición de acuerdo con el límite superior del número especificado por el cliente y luego lo devuelve al cliente.

Hay varios puntos a tener en cuenta aquí:
1. Kafka utiliza tecnología de copia cero para enviar mensajes al cliente: es decir, el mensaje se envía directamente desde el archivo al canal de red sin pasar por ningún búfer intermedio.
2. El cliente de Kafka generalmente establece los límites superior e inferior de los datos devueltos por el corredor para controlar la cantidad de datos devueltos por el corredor a la vez.
3. Es decir, si la cantidad de datos no alcanza el límite inferior, luego de que se envíe la solicitud del broker, el mensaje no se recibirá hasta que la cantidad de datos sea suficiente.
4. Por supuesto, el cliente no esperará a que el corredor acumule datos durante un cierto período de tiempo. Si el volumen de datos aún no cumple con el estándar, se devolverán los datos.

  1. Los datos devueltos son datos síncronos.

Inserte la descripción de la imagen aquí


Almacenamiento físico

La unidad de almacenamiento básica de Kafka es una partición. Cuando Kafka está configurado, generalmente se especifica una dirección de directorio para la partición de almacenamiento, que es el parámetro log.dirs (server.properties, tenga cuidado de no confundirlo con log.properties)

A continuación, veremos cómo Kafka realiza la asignación de particiones y el almacenamiento de datos.

Asignación de partición

Cuando Kafka crea un tema, decidirá cómo asignar particiones entre corredores.

Ejemplo: tenemos 6 corredores, planeamos crear un tema con 10 particiones, y el factor de replicación es 3 (la cantidad de copia), entonces habrá un total de 10 * 3 = 30 copias de partición, que se asignarán a 6 corredores. Al realizar la asignación de particiones, Kafka necesita lo siguiente:

  1. Las copias de la partición se distribuyen uniformemente en los corredores. (Equivalente a un promedio de 5 copias de partición para cada corredor)
  2. Asegúrese de que se distribuyan diferentes copias de cada partición en diferentes intermediarios. (Cada partición tiene 3 copias, incluida una copia maestra y una copia secundaria), lo que significa que las copias maestra y esclava deben asignarse a diferentes intermediarios, y varias copias de la misma partición no pueden estar en el mismo intermediario. Consulte la imagen a continuación

Inserte la descripción de la imagen aquí

Gestión e indexación de archivos

Hay dos formas de administrar archivos en Kafka: tiempo de almacenamiento y tamaño de almacenamiento. Para obtener más información, consulte los parámetros del artículo del productor.

Generalmente, Kafka divide la partición en varios fragmentos. ** De forma predeterminada, cada fragmento contiene 1 GB o una semana de datos, y prevalecerá el más pequeño. ** Cuando el corredor escribe datos en la partición, si se alcanza el límite de fragmentos, el archivo actual se cierra y se abre un nuevo archivo.

El segmento que actualmente está escribiendo datos se denomina segmento activo y el segmento activo nunca se eliminará.

Entonces, ¿cuál es el formato del archivo escrito?

Sabemos que Kafka guarda el mensaje y el desplazamiento en un archivo, entonces, ¿qué más contiene el archivo?
Inserte la descripción de la imagen aquí
Además de los pares clave-valor y las compensaciones, el mensaje también contiene el tamaño, la suma de comprobación, el número de versión del formato del mensaje, el algoritmo de compresión (Snappy, Gzip, Lz4) y la marca de tiempo del mensaje. La marca de tiempo se refiere a la hora en que el mensaje llega al corredor. Pero puede notar que la esquina inferior derecha de la imagen de arriba es negra, lo que significa que el productor envía un mensaje comprimido. Luego, el mismo lote de mensajes se comprimirá y se enviará como mensajes empaquetados.

Utilice una herramienta que viene con Kafka para ver el contenido del fragmento (contenido del mensaje)

./bin/kafka-run-class.sh kafka.tools.DumpLogSegments --deep-iteration 文件

Los consumidores pueden comenzar a leer mensajes desde cualquier compensación disponible en Kafka, entonces, ¿cómo lo ubican los consumidores?

Respuesta: Utilice el índice.
Kafka mantiene un índice para cada partición, que asigna el desplazamiento al archivo de fragmentos y la posición del desplazamiento en el archivo. Por supuesto, el índice también se dividirá en fragmentos, por lo que al eliminar un mensaje, también se eliminará el índice correspondiente.

Principio de funcionamiento y limpieza de archivos

Cada fragmento de registro de Kafka se puede dividir en dos partes.

  1. Limpiar parte: estos mensajes se han limpiado antes y cada clave tiene solo un valor correspondiente, que se retiene durante la última limpieza.
  2. La parte sucia: estos mensajes son datos escritos después de la última limpieza.
    Como se muestra:
    Inserte la descripción de la imagen aquí

Kafka puede configurar su propia función de limpieza (log.cleaner.enabled). Si se inicia, cada corredor iniciará un hilo de administrador de limpieza y varios hilos de limpieza. Los hilos de limpieza son responsables de realizar las tareas de limpieza. Seleccionarán la tasa de contaminación (sucio mensaje Se limpia la partición con la proporción más alta del tamaño total de la partición).

El hilo de limpieza creará un mapa en la memoria. Cada elemento en este mapa contiene el valor hash y el desplazamiento de la clave del mensaje. El valor hash de la clave es 16B y el desplazamiento es 24B en total. Entonces, si desea limpiar un fragmento de registro de 1 GB, asumiendo que el tamaño de cada mensaje es de 1 KB, entonces este fragmento contiene un millón de mensajes y solo necesitamos un mapa de 24 MB para limpiar este fragmento, lo cual es muy eficiente.

Principio de funcionamiento aproximado :

  1. Una vez que el hilo de limpieza ha creado el mapa de compensación, comienza a leer el mensaje del fragmento más limpio, que es el mensaje más antiguo, y compara su contenido con el contenido del mapa.
  2. Compruebe si la clave del mensaje existe en el mapa. Si no existe, significa que el valor del mensaje es el más reciente y el mensaje se copiará en el fragmento reemplazado. Si existe, el mensaje se ignorará.
  3. Después de copiar todos los mensajes, intercambiamos el fragmento de reemplazo con el fragmento original y luego comenzamos a limpiar el siguiente fragmento.
  4. Después de completar todo el proceso de limpieza, cada tecla corresponde a un mensaje diferente (el valor del mensaje es el último), la imagen es la siguiente:

Inserte la descripción de la imagen aquí


Lo anterior se puede resumir a pequeña escala, solo mantendremos un mensaje reciente para cada tecla.

Pregunta 1: Pero, ¿qué debo hacer si necesito eliminar todos los mensajes correspondientes a una determinada clave? (Por ejemplo, un usuario ya no usa un determinado servicio y necesita eliminar todos los mensajes del cliente)

Respuesta:
1. Para eliminar completamente una clave del sistema, la aplicación debe enviar un mensaje que contenga la clave con un valor de nul.
2. Cuando el hilo de limpieza encuentra el mensaje, primero realizará una limpieza regular y solo mantendrá el mensaje cuyo valor sea nulo. El mensaje con un valor de nulo, lo llamamos mensaje de desecho , se mantendrá durante un período de tiempo.
3. Durante este período, el consumidor puede ver el mensaje de desecho, pero descubrió que su valor ha sido eliminado.
4. Después de este período de tiempo, el hilo de limpieza eliminará el mensaje de desecho y la clave correspondiente también se eliminará de la partición de Kafka.

Pregunta 2: ¿Por qué se retiene el mensaje de la lápida por un período corto de tiempo?

Respuesta: 1. En primer lugar, se puede configurar el tiempo de retención.
2. En segundo lugar, el tiempo de retención está configurado para permitir que los consumidores vean el mensaje de desecho durante este período, de modo que los consumidores comprendan que el valor de este mensaje se ha eliminado y los consumidores profesionales entenderán: Oh, este mensaje ya no es útil ahora , todos los mensajes relevantes deben eliminarse de la base de datos.


para resumir

Este artículo describe los siguientes aspectos:

  1. Membresía y controlador del clúster.
  2. Proceso de replicación y procesamiento de solicitudes de Kafka.
  3. Almacenamiento y formato de archivo de Kafka, principio de compensación.

El próximo artículo hablará sobre la transmisión de datos confiable de Kafka.

Supongo que te gusta

Origin blog.csdn.net/Zong_0915/article/details/109578284
Recomendado
Clasificación