"Análisis de código fuente de Elasticsearch y optimización de combate real" Capítulo 5: Proceso de selección principal

"Análisis de código fuente de Elasticsearch y optimización de combate real" Capítulo 5: Proceso de selección principal - Motianlun

1. Introducción

El módulo Discovery es responsable de descubrir los nodos en el clúster y elegir el nodo maestro. ES admite una variedad de tipos de descubrimiento, la implementación integrada se llama Zen Discovery
, y otros incluyen EC2 de Amazon en la plataforma de nube pública, GCE de Google, etc.

Este capítulo trata sobre la implementación integrada de Zen Discovery. Zen Discovery encapsula el proceso de implementación del descubrimiento de nodos (Ping), la elección del maestro, etc. Ahora analizaremos primero el proceso de elección del maestro y presentaremos el módulo Discovery como un todo en los siguientes capítulos.

2. Pensamiento de diseño

Todos los sistemas distribuidos necesitan lidiar con la consistencia de alguna manera. En general, las estrategias se pueden dividir en dos grupos :

  • trate de evitar inconsistencias

  • y cómo reconciliarlos después de que ocurran inconsistencias en las definiciones . Este último es muy poderoso en escenarios aplicables, pero tiene restricciones relativamente estrictas en el modelo de datos. Así que aquí hay un vistazo a lo primero y cómo lidiar con las fallas de la red.

3. ¿Por qué usar el modo maestro-esclavo?

Además del modo maestro-esclavo (Líder/Seguidor), otra opción es la tabla hash distribuida (DHT), que puede soportar la salida y unión de miles de nodos por hora, que puede usarse en redes heterogéneas que no entienden la topología de red subyacente En medio del trabajo, el tiempo de respuesta de la consulta es de aproximadamente 4 a 10 saltos (tiempos de tránsito), por ejemplo, Cassandra usa este esquema. Pero en una red peer-to-peer relativamente estable, el modo maestro-esclavo será mejor.

Otra simplificación en el escenario típico de ES es que no hay tantos nodos en el clúster. Por lo general, la cantidad de nodos es mucho menor que la cantidad de conexiones que un solo nodo puede mantener, y el entorno de red no tiene que lidiar con la unión y salida de nodos con frecuencia. Esta es la razón por la que el modo maestro-esclavo es más adecuado para ES.

4. Algoritmo de elección

En la selección del algoritmo de elección del nodo maestro, el principio básico es no reinventar la rueda. Es mejor implementar un algoritmo conocido, donde se conozcan las ventajas y desventajas. La selección del algoritmo de elección de ES considera principalmente los siguientes dos tipos.

4.1 Algoritmo de intimidación

Uno de los algoritmos básicos para la elección de Líder. Asume que todos los nodos tienen una identificación única y usa esa identificación para ordenar los nodos. El Líder actual en cualquier momento es el nodo de ID más alto que participa en el clúster.  La ventaja de este algoritmo es que es fácil de implementar. Sin embargo, existen problemas cuando el nodo con el ID más grande se encuentra en un estado inestable . Por ejemplo, el maestro está sobrecargado y se suspende la animación, y el nodo con el segundo ID más grande en el clúster se elige como el nuevo maestro. En este momento, el maestro original se recupera, se elige como el nuevo maestro nuevamente y luego muere en animación suspendida...

ES resuelve el problema anterior posponiendo la elección hasta que el Maestro actual falle. Mientras el nodo maestro actual no cuelgue, el maestro no será reelegido. Sin embargo, es fácil causar split brain (maestros duales) Por esta razón, el problema de split brain se resuelve con "más de la mitad de los votos estatutarios".

4.2 Algoritmo de Paxos

Paxos es muy poderoso, especialmente la flexibilidad en cuándo y cómo realizar elecciones tiene una gran ventaja sobre el simple algoritmo Bully, porque en la vida real, hay más modos de falla que anomalías en la conexión de red. Pero Paxos es muy complicado de implementar.

Cinco, configuración relacionada

Las configuraciones importantes relacionadas con el proceso de elección de maestro incluyen las siguientes, pero no todas las configuraciones.

discovery.zen.minimum_master_nodes
: El número mínimo de nodos maestros, que es un parámetro extremadamente importante para evitar la pérdida de datos y el cerebro dividido. El efecto real de este parámetro ya ha superado su significado superficial. Además de usarse para determinar la "mayoría" al elegir un líder, también se usa para muchos juicios importantes, incluidos al menos los siguientes tiempos:

  • Activar elección de líder:  antes de ingresar al proceso de elección de líder, la cantidad de nodos participantes debe alcanzar un quórum.

  • Determinar el maestro:  después de seleccionar el maestro temporal, el maestro temporal debe juzgar que la cantidad de nodos que se unen ha alcanzado un quórum antes de confirmar el éxito de la elección del maestro.

  • Metainformación de elección de puerta de enlace:  Inicia una solicitud a un nodo con calificación de Maestro para obtener metadatos, y la cantidad de respuestas obtenidas debe alcanzar un quórum, es decir, la cantidad de nodos que participan en la elección de metainformación.

  • Maestro libera el estado del clúster:  el número de lanzamientos exitosos es la mayoría.

Para evitar split-brain, su valor debe ser más de la mitad (quórum):(master_eligible_nodes 2)+1

例如:如果有3个具备Master资格的节点,则这个值至少应该设置为(3/2) + 1=2。

该参数可以动态设置:
PUT _cluster/settings
{
    "persistent" : {
        "discovery.zen.minimum master_nodes" : 2
    }
}

discovery.zen.ping.unicast.hosts
: **La lista de nodos semilla del clúster. Al crear un clúster, este nodo intentará conectarse a esta lista de nodos. Luego, los hosts de la lista verán qué hosts están en todo el clúster. **Se puede configurar para algunos o todos los nodos del clúster. Se puede especificar así:

discovery.zen.ping.unicast.hosts:
    -192.168.1.10:9300
    -192.168.1.11
    -seeds.mydomain.com

De manera predeterminada, se usa el puerto 9300. Si necesita cambiar el número de puerto, puede especificar manualmente el puerto después de la IP. También es posible configurar un nombre de dominio para que el nombre de dominio se pueda resolver en varias direcciones IP, y ES intentará conectarse a todas las direcciones en la lista de IP.

  • discovery.zen.ping.unicast.hosts.resolve_timeout: DNS
    Tiempo de espera de análisis, el valor predeterminado es 5 segundos.

  • discovery.zen.join_timeout
    : el período de tiempo de espera cuando el nodo se une al clúster existente, el valor predeterminado es 20 veces de ping_timeout.

  • discovery.zen.join_retry_attemptsjoin_timeout
    : el número de reintentos después del tiempo de espera, el valor predeterminado es 3 veces.

  • discovery.zen.join_retry_delayjoin_timeout
    : Después del tiempo de espera, el tiempo de retraso antes de volver a intentarlo, el valor predeterminado es de 100 milisegundos.

  • discovery.zen.master_election.ignore_non_master_ pings
    : cuando se establece en verdadero, la fase de elección de maestro ignorará las solicitudes de ping de los nodos que no tienen calificaciones de maestro (nodo.maestro: falso), y el valor predeterminado es falso.

  • discovery.zen.fd.ping_interval
    : Período de intervalo de detección de fallas, el valor predeterminado es 1 segundo.

  • discovery.zen.fd.ping_timeout
    : Tiempo de espera de solicitud de detección de fallas, el valor predeterminado es 30 segundos.

  • discovery.zen.fd.ping_retries
    : El número de reintentos después del tiempo de espera de detección de fallas, el valor predeterminado es 3 veces.

6. Análisis de procesos

6.0 Resumen del proceso

6.0.1. El proceso de selección de maestros de ZenDiscovery es el siguiente:

  • Cada nodo calcula el ID de nodo más pequeño conocido , que es el maestro temporal . Envíe un voto de liderazgo a este nodo .

  • Si un nodo recibe suficientes votos y el nodo también vota por sí mismo, asume el rol de líder y comienza a publicar el estado del clúster .

  • Todos los nodos participarán en la elección y votarán, pero solo los votos de los nodos que sean elegibles para convertirse en Maestro (node.maste es verdadero) son válidos.

Cuantos votos se pueden obtener para ganar una elección es el llamado quórum. En ES, el tamaño del quórum es un parámetro configurable. Elemento de configuración:  discovery.zen.minimum master_ nodes
. Para evitar el cerebro dividido, el valor mínimo debe ser el número de nodos calificados como maestro n/2+1
.

6.0.2 El proceso general puede resumirse como sigue:

  • Elección de Maestro interino;

  • Votación: confirme el maestro, si se elige el nodo, espere el establecimiento del maestro, si se eligen otros nodos, intente unirse al clúster y luego inicie el detector de fallas del nodo;

  • Detección de nodos de fallas;

Los detalles se muestran en la siguiente figura.

Grupo de subprocesos para ejecutar este proceso: genérico.

A continuación analizamos la implementación de cada paso en detalle.

6.1 Elección de Maestro interino

La implementación del proceso electoral se encuentra en ZenDiscovery#findMaster
. Esta función busca el maestro activo del clúster actual o selecciona un nuevo maestro de los candidatos. Devuelve el maestro seleccionado si la selección del maestro es exitosa; de lo contrario, devuelve nulo.

¿Por qué es un Máster temporal? Debido a que aún debe esperar el siguiente paso, el nodo se establecerá como el maestro real cuando tenga suficientes votos.

El proceso de elección del Maestro temporal es el siguiente:

  • "Haga ping" a todos los nodos, obtenga la lista de nodos fullPingResponses, el resultado del ping no incluye este nodo, agregue este nodo a fullPingResponses por separado.

  • Construye dos listas.

    • lista de maestros activos:  la lista maestra activa actual del clúster de almacenamiento.

    • lista masterCandidates:  almacenar la lista de candidatos maestros

lista de maestros activos: la lista maestra activa actual del clúster de almacenamiento.  Recorra todos los nodos obtenidos en el primer paso y agregue el nodo Maestro actual que cada nodo considera a la lista de maestros activos (excluyendo este nodo). Durante el proceso transversal, si la configuración discovery.zen.master_election.ignore_non_master_pings
es verdadera (el valor predeterminado es falso) y el nodo no tiene la calificación de maestro, se omitirá el nodo.

El proceso específico se muestra en la siguiente figura.

inserte la descripción de la imagen aquí

Este proceso es para agregar el Maestro actualmente existente en el clúster a la lista de maestros activos, normalmente solo hay uno. Si el clúster ya tiene un Maestro, cada nodo registra cuál es el Maestro actual, considerando circunstancias anormales, cada nodo puede ver un Maestro actual diferente. En el proceso de creación de la lista ActiveMasters, si el nodo no tiene la calificación de Maestro, puede ignore_non_master_pings
ignorar el Maestro que considera la opción.

lista masterCandidates: Almacena una lista de candidatos maestros.  Recorra el primer paso para obtener la lista, elimine los nodos que no tengan calificación de Maestro y agréguelos a esta lista. Si activeMasters está vacío, la elección se realizará desde masterCandidates y la elección puede tener éxito o fallar. Si no está vacío, elija el más adecuado de activeMasters como Maestro.

El proceso general se muestra en la siguiente figura.

inserte la descripción de la imagen aquí

6.1.1 masterCandidates
Elija el maestro de

La implementación de los detalles específicos de la selección maestra se encapsula en la clase ElectMasterService, por ejemplo, juzgar si hay suficientes candidatos, seleccionar un nodo específico como Maestro, etc.

Al seleccionar un maestro de masterCandidates, primero es necesario determinar si el número actual de candidatos ha alcanzado un quórum; de lo contrario, la elección del maestro fallará.

public boolean hasEnoughCandidates (Collection<MasterCandidate> candidates) {
    //候选者为空,返回失败
    if (candidates.isEmpty()) {
        returnfalse;
    }
    //默认值为-1, 确保单节点的集群可以正常选主
    if (minimumMasterNodes < 1) {
        returntrue;
    }
    return candidates .size () >= minimumMasterNodes;
}

Cuando el número de candidatos alcance el quórum, seleccione uno de los candidatos para ser el Maestro:

public MasterCandidate electMaster (Collection<MasterCandidate> candidates) {
    List<MasterCandidate> sortedCandidates = new ArrayList<> (candidates);
    //通过自定义的比较函数对候选者节点从小到大排序
    sortedCandidates.sort (MasterCandidate :: compare);
    //返回最新的作为Master
    return sortedCandidates.get(0);
}

Se puede ver que aquí solo el nodo más pequeño se selecciona como maestro después de ordenar los nodos. Sin embargo, la función de comparación personalizada MasterCandidate::compare se usa para ordenar. En versiones anteriores, solo se ordenaban los ID de nodo. Ahora, los nodos con números de versión de estado de clúster más altos tendrán prioridad primero.

Cuando se utiliza la función de comparación predeterminada, el resultado de la ordenación se ordena de menor a mayor. Consulte la implementación de la función de comparación del tipo Long:

public static int compare (1ong X,long y) {
    return(x<y)?-1:((x==y)?0:1);
}

自定义比较函数的实现:
public static int compare(MasterCandidate cl, MasterCandidate c2) {
    //先比较集群状态版本,注意此处c2在前,c1在后
    int ret = Long.compare(c2.clusterStateVersion, c1.clusterStateVersion);
    //如果版本号相同,则比较节点ID
    if(ret==0){
        ret = compareNodes (c1.getNode(),c2.getNode());
    }
    return ret;
}

Implementación de la función de comparación de nodos compareNodes:  para efectos de clasificación

  • Si uno de los dos nodos entrantes tiene la calificación de maestro y el otro no, el nodo calificado como maestro se clasificará en primer lugar.

  • Si ninguno tiene la calificación de Maestro , o si ambos tienen la calificación de Maestro, compare los ID de nodo.

Sin embargo, todos los nodos de la lista masterCandidates son elegibles para Master . Los dos juicios if de la función de comparación compareNodes se deben a que puede haber nodos en la lista de nodos que no tienen calificaciones de maestro en otras llamadas a funciones. Por lo tanto, aquí solo se comparan los ID de nodo.

private static int compareNodes (DiscoveryNode o1, DiscoveryNode o2) {
    //两个if处理两节点中一个具备Master资格而另一个不具备的情况
    if (o1.isMasterNode() && !o2.isMasterNode () ) {
        return -1;
    }
    if (!o1.isMasterNode() && o2.isMasterNode()) {
        return1;
    }
    //通过节点ID排序
    return o1.getId().compareTo(o2.getId());
}

La lista de selección de la lista de maestros activos almacena los maestros actualmente activos en el clúster y uno de estos nodos maestros conocidos se selecciona como resultado de la elección. El proceso de selección es muy simple, tome el valor mínimo en la lista, la función de comparación aún se implementa a través de compareNodes, y los nodos en la lista activeMasters se califican teóricamente como Maestros.

public DiscoveryNode tieBreakActiveMasters (Collection<DiscoveryNode> activeMasters)
    return activeMasters.stream().min(ElectMasterService ::compareNodes).get();
}

6.1.2 Realización de Votaciones y Votaciones

En ES, enviar un voto es enviar una solicitud JoinRequest. Los votos son el número de solicitudes para unirse al nodo. La implementación de recolectar votos y hacer estadísticas está en ZenDiscovery#handleJoinRequest
el método, y las conexiones recibidas se almacenan en ElectionContext#joinRequestAccumulator
. Cuando un nodo comprueba si los votos recibidos son suficientes, comprueba si el número de conexiones que lo unen es suficiente, y los votos de los nodos sin calificación de Maestro serán eliminados.

public synchronized int getPendingMasterJoinsCount() {
    int pendingMasterJoins = 0;
    //遍历当前收到的join请求
    for (DiscoveryNode node : joinReques tAccumulator .keySet()) {
        //过滤不具备master资格的节点
        if (node. isMasterNode()) {
            pendingMasterJoins++;
        }
    }
    return pendingMasterJoins;
}

6.1.3 Establecer un Máster o unirse a un clúster

Hay dos situaciones para el Maestro temporal elegido: el Maestro temporal es el nodo local o un nodo no local. Esto se maneja por separado. Ahora listo para enviarle votos.

6.1.3.1 Si el Maestro temporal es el nodo actual:

  • Espere a que suficientes nodos calificados como maestros se unan a este nodo (la votación alcanza un quórum) para completar la elección. Si el número de solicitudes de unión no se satisface después del tiempo de espera (el valor predeterminado es 30 segundos, configurable), la elección falla y se requiere una nueva ronda de elección.

  • Publique un nuevo clusterState en caso de éxito.

6.1.3.2 Si se seleccionan otros nodos como Maestro:

  • Ya no se aceptan solicitudes de unión de otros nodos.

  • Envíe una solicitud de ingreso al maestro y espere una respuesta. El tiempo de espera predeterminado es de 1 minuto (configurable) y, si se encuentra una excepción, vuelve a intentarlo 3 veces de forma predeterminada (configurable). Este paso se implementa en el método joinElectedMaster.

  • El Master finalmente elegido publicará el estado del clúster antes de confirmar la solicitud de ingreso del cliente, por lo tanto, joinElectedMaster devuelve la confirmación de que se ha recibido la solicitud de ingreso y se ha recibido el estado del clúster. En este paso, verifique si el nodo maestro en el estado del clúster recibido está vacío, o si el maestro elegido no es el nodo seleccionado anteriormente, vuelva a elegirlo.

6.2 Detección de fallos de nodo

Hasta el momento, se ha completado el proceso de selección del maestro, se ha confirmado la identidad del maestro y los nodos que no son maestros se han unido al clúster. La detección de fallas del nodo monitoreará si el nodo está fuera de línea y luego manejará la anomalía en él. La detección de fallas es un paso indispensable después del proceso de selección del maestro. Si no se realiza la detección de fallas, puede resultar en un cerebro dividido (maestros duales o múltiples). Aquí necesitamos habilitar dos detectores de fallas:

  • En el nodo principal , inicie  NodesFaultDetection
    , denominado NodesFD. Detectar regularmente si los nodos que se unen al clúster están activos.

  • En nodos que no sean maestros , inicio MasterFaultDetection
    , denominado MasterFD. Detectar regularmente si el nodo maestro está activo.

Tanto NodesFaultDetection como MasterFaultDetection detectan si el nodo es normal a través de la solicitud de ping enviada periódicamente (1 segundo de forma predeterminada) y comienzan a procesar cuando la falla alcanza un cierto número de veces (3 veces de forma predeterminada) o cuando se recibe una notificación de nodo fuera de línea. desde el evento de abandono del nodo del módulo de conexión subyacente.

6.2.1, procesamiento de eventos NodesFaultDetection

Compruebe si el número total de nodos en el clúster actual alcanza el número de nodos reglamentario (más de la mitad), de lo contrario, abandonará el estado de Maestro y se reincorporará al clúster.  ¿Por qué desea hacer esto? Imagine el siguiente escenario, como se muestra en la siguiente figura.

inserte la descripción de la imagen aquí

Suponga que un clúster compuesto por 5 máquinas genera una partición de red, 2 máquinas forman un grupo y las otras 3 máquinas forman un grupo. Antes de que se produzca la partición, el Maestro original es el Nodo1. En este momento, un grupo de 3 nodos volverá a elegir y seleccionará con éxito a Noded3 como maestro. ¿Habrá maestros duales?  NodesFaultDetection
Es para evitar maestros duales en el escenario anterior.

El procesamiento de eventos correspondiente se implementa principalmente de la siguiente manera: ZenDiscovery#handleNodeFailure
Ejecutar en NodeRemoval-ClusterStateTaskExecutor#execute
.

public ClusterTasksResult<Task> execute (final ClusterState currentState, final List<Task> tasks) throws Exception {
    //判断剩余节 点是否达到法定人数
    if (electMasterService.hasEnoughMasterNodes (remainingNodesClusterState.nodes()) == false) {
        finalint masterNodes = electMas terService.countMasterNodes(remainingNodesClusterState.nodes());
        rejoin.accept(LoggerMessageFormat.format("not enough master nodes(has \[{}\], but needed \[{}\])", masterNodes, electMasterService.minimumMasterNodes()));
        return resultBuilder .build (currentState) ;
    } else {
        return resultBuilder.build (allocationService.deassociateDeadNodes(remainingNodesClusterState, true, describeTasks(tasks)));
    }
}

Cuando el nodo maestro detecta que el nodo está fuera de línea, si encuentra que la cantidad de nodos en el clúster actual es insuficiente para el quórum, abandonará el estado de Maestro para evitar los maestros duales.

6.2.2, Procesamiento de eventos MasterFaultDetection


**El proceso de detección de que el Maestro está fuera de línea es muy simple, vuelva a unirse al clúster. **Esencialmente, el nodo vuelve a ejecutar el proceso de elección del maestro. El procesamiento de eventos correspondiente se implementa principalmente de la siguiente manera: ZenDiscovery#handleMasterGone

private void handleMasterGone (final DiscoveryNode masterNode, final Throwable cause, final String reason) {
    synchronized(stateMutex) {
        if (localNodeMaster() == false && masterNode.equals (committedState.get().nodes ().getMasterNode())) {
            pendingStatesQueue.failAllStatesAndClear (new ElasticsearchException("master left\[\[)\]", reason));
            //重新加入集群
            rejoin ("master left (reason = " + reason + ")");
        }
    }
}

resumen

Se inicia el proceso de elección de maestro en el clúster, y se ejecuta desde el estado de no maestro hasta la generación de un nuevo maestro, al mismo tiempo, durante el funcionamiento normal del clúster, el maestro detecta que el nodo se va, y el nodo no maestro detecta que el maestro se va.

Supongo que te gusta

Origin blog.csdn.net/qq_32907195/article/details/131980402
Recomendado
Clasificación