0Pricing
Erlang OTP: Distributed & Fault-Tolerant Systems Programming · Leçon

Schémas de consensus distribué

Comprenez et mettez en œuvre des algorithmes et des schémas de consensus distribué, essentiels au maintien de la cohérence des systèmes distribués.

Schémas de consensus distribué est une leçon Erlang OTP: Distributed & Fault-Tolerant Systems Programming gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Erlang OTP: Distributed & Fault-Tolerant Systems Programming, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Erlang OTP: Distributed & Fault-Tolerant Systems Programming comprend 4 leçons au total.

Certaines parties de cette leçon n'ont pas encore été traduites et s'affichent en anglais.

Agreeing in a Distributed World

Imagine multiple computers (nodes) needing to agree on a single outcome, even if some nodes fail or messages get lost. This challenge is called Distributed Consensus.

It's vital for maintaining data consistency and ensuring all parts of a system see the same "truth". Without it, your system might end up in a confused, inconsistent state.

The Hard Problem of Coordination

Achieving consensus is difficult because:

  • Network Delays: Messages don't arrive instantly or in order.
  • Node Failures: A computer might crash at any moment.
  • Message Loss: Messages can be dropped by the network.

How do you ensure everyone agrees when communication is unreliable and participants can vanish?

Where Consensus Shines

Distributed consensus patterns are foundational for many critical system features:

  • Leader Election: Deciding which node is the primary coordinator.
  • Atomic Commits: Ensuring a transaction either fully completes on all nodes or completely fails on all.
  • State Machine Replication: Keeping identical copies of data or application state across multiple nodes.

CAP and Consensus Trade-offs

The CAP Theorem states that a distributed system can only guarantee two out of three properties: Consistency, Availability, or Partition Tolerance.

Consensus algorithms typically prioritize Consistency and Partition Tolerance. This means during a network partition, the system might become unavailable for writes to prevent inconsistencies.

A Simple Agreement Protocol: 2PC

The Two-Phase Commit (2PC) protocol is a basic way to achieve atomic transactions across distributed nodes. It's often used in databases.

While not fully fault-tolerant (it can block if the coordinator fails), it's a great conceptual stepping stone to understanding more complex consensus algorithms.

The Coordinator: Orchestrating the Vote

In 2PC, one node acts as the Coordinator. Its job is to:

  1. Phase 1 (Prepare): Send a "prepare" or "vote request" message to all participating nodes.
  2. Phase 2 (Commit): Based on the votes, send a "commit" message if all voted "yes", or an "abort" message if any voted "no" (or timed out).

Participants: Deciding & Acting

Each Participant node in 2PC has these responsibilities:

  1. Phase 1 (Vote): When receiving "prepare", perform necessary checks. If ready to commit, reply "yes" and lock resources. Otherwise, reply "no".
  2. Phase 2 (Act): When receiving "commit", finalize the transaction. If "abort", roll back any changes and unlock resources.

Erlang Coordinator: Voting Process

Let's simulate a basic 2PC coordinator in Erlang. It spawns participants, sends a message, and collects their replies. This example simplifies error handling for clarity.

Note: This isn't production-ready 2PC, just an illustration of the message flow.

-module(coordinator).
-behaviour(gen_server).

-export([start_link/0, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([propose/2]).

start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

init([]) ->
    {ok, []}.

propose(CoordinatorPid, Value) ->
    gen_server:call(CoordinatorPid, {propose, Value}).

handle_call({propose, Value}, _From, _State) ->
    % In a real system, participants would be registered or known
    Pids = [
        spawn(fun participant:start/0),
        spawn(fun participant:start/0)
    ],
    
    io:format("Coordinator: Proposing ~p to participants: ~p~n", [Value, Pids]),
    
    % Phase 1: Prepare
    Responses = [rpc:call(Pid, participant, prepare, [Value]) || Pid <- Pids],
    
    FinalDecision = 
        case lists:all(fun(ok) -> true; (_) -> false end, Responses) of
            true -> commit;
            false -> abort
        end,

    io:format("Coordinator: All participants voted, decision: ~p~n", [FinalDecision]),

    % Phase 2: Commit/Abort
    [rpc:call(Pid, participant, FinalDecision, []) || Pid <- Pids],

    {reply, FinalDecision, _State}.

handle_cast(_Msg, State) -> {noreply, State}.
handle_info(_Info, State) -> {noreply, State}.
terminate(_Reason, _State) -> ok.
code_change(_OldVsn, State, _Extra) -> {ok, State}.

% To run this example:
% 1. Compile both coordinator.erl and participant.erl
% 2. Start Erlang shell: erl
% 3. coordinator:start_link().
% 4. coordinator:propose(whereis(coordinator), "My Transaction").
% You should see output from both coordinator and participants.

Erlang Participant: Voting & Acting

Here's how a participant process might respond to the coordinator. It simulates a "vote" and then acts on the "commit" or "abort" instruction.

This participant always votes 'ok' in this simplified version, but in reality, it would check its own state.

-module(participant).
-behaviour(gen_server).

-export([start_link/0, start/0, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([prepare/1, commit/0, abort/0]).

start_link() ->
    gen_server:start_link(?MODULE, [], []).

start() -> % Used by coordinator to spawn
    {ok, Pid} = start_link(),
    Pid.

init([]) ->
    io:format("Participant ~p: Started.~n", [self()]),
    {ok, #{} % State could hold transaction details
    }.

prepare(_Value) ->
    % In a real system, participant would check resources, lock them etc.
    % For simplicity, always vote 'ok' here.
    io:format("Participant ~p: Received prepare, voting 'ok'.~n", [self()]),
    ok.

commit() ->
    io:format("Participant ~p: Received commit, finalizing transaction.~n", [self()]),
    ok.

abort() ->
    io:format("Participant ~p: Received abort, rolling back transaction.~n", [self()]),
    ok.

handle_call(_Msg, _From, State) ->
    {reply, ok, State}. % Placeholder for any calls

handle_cast(_Msg, State) -> {noreply, State}.
handle_info(_Info, State) -> {noreply, State}.
terminate(_Reason, _State) -> ok.
code_change(_OldVsn, State, _Extra) -> {ok, State}.

The Pitfalls of 2PC

While illustrative, 2PC has significant drawbacks:

  • Single Point of Failure: If the coordinator crashes during Phase 2, participants might be left waiting indefinitely, holding locked resources. This is known as the "blocking problem".
  • Performance: It requires multiple rounds of communication, which can be slow in high-latency networks.

These limitations necessitate more robust, non-blocking consensus algorithms like Paxos or Raft for truly fault-tolerant systems.

Quick Check: Consensus Roles

In the Two-Phase Commit (2PC) protocol, what is the primary responsibility of a Participant node in Phase 1 (Prepare)?

Recap: Agreement is Key

We've explored Distributed Consensus, understanding its importance for consistency in distributed systems and the challenges it presents.

We looked at Two-Phase Commit (2PC) as a basic protocol, understanding the roles of the Coordinator and Participants, and its key limitations. Erlang's message passing is a great foundation for building these patterns, but true fault-tolerant consensus requires more advanced algorithms.

Questions Fréquemment Posées

La leçon « Schémas de consensus distribué » est-elle gratuite ?

Oui — le texte complet de « Schémas de consensus distribué » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Erlang OTP: Distributed & Fault-Tolerant Systems Programming, passe à CoddyKit PRO. Le cours Erlang OTP: Distributed & Fault-Tolerant Systems Programming comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Schémas de consensus distribué » ?

Comprenez et mettez en œuvre des algorithmes et des schémas de consensus distribué, essentiels au maintien de la cohérence des systèmes distribués. Tu pratiques Erlang OTP: Distributed & Fault-Tolerant Systems Programming avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Erlang OTP: Distributed & Fault-Tolerant Systems Programming ?

Aucune expérience préalable n'est requise. Erlang OTP: Distributed & Fault-Tolerant Systems Programming sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Schémas de consensus distribué » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Erlang OTP: Distributed & Fault-Tolerant Systems Programming ?

Oui. Chaque leçon Erlang OTP: Distributed & Fault-Tolerant Systems Programming inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Conception pour une haute disponibilité
  2. Schémas de consensus distribué
  3. Études de cas sur Erlang OTP
  4. Contrôle de pression et régulation de charge
← Retour à Erlang OTP: Distributed & Fault-Tolerant Systems Programming