0Pricing
Erlang OTP: Distributed & Fault-Tolerant Systems Programming · درس

أنماط الإجماع الموزّع

افهم خوارزميات وأنماط الإجماع الموزّع ونفّذها، فهي أساسية للحفاظ على الاتساق في الأنظمة الموزّعة

أنماط الإجماع الموزّع درس مجاني في Erlang OTP: Distributed & Fault-Tolerant Systems Programming على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Erlang OTP: Distributed & Fault-Tolerant Systems Programming، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Erlang OTP: Distributed & Fault-Tolerant Systems Programming 4 دروس في المجموع.

بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.

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.

الأسئلة الشائعة

هل درس «أنماط الإجماع الموزّع» مجاني؟

نعم — نص درس «أنماط الإجماع الموزّع» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Erlang OTP: Distributed & Fault-Tolerant Systems Programming، انتقل إلى CoddyKit PRO. تتضمن دورة Erlang OTP: Distributed & Fault-Tolerant Systems Programming 4 دروس في المجموع.

ماذا ستتعلم في «أنماط الإجماع الموزّع»؟

افهم خوارزميات وأنماط الإجماع الموزّع ونفّذها، فهي أساسية للحفاظ على الاتساق في الأنظمة الموزّعة تتمرن على Erlang OTP: Distributed & Fault-Tolerant Systems Programming مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Erlang OTP: Distributed & Fault-Tolerant Systems Programming؟

لا تُشترط خبرة سابقة. Erlang OTP: Distributed & Fault-Tolerant Systems Programming على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.

كم من الوقت يستغرق درس «أنماط الإجماع الموزّع»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Erlang OTP: Distributed & Fault-Tolerant Systems Programming هذا؟

نعم. كل درس في Erlang OTP: Distributed & Fault-Tolerant Systems Programming يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. التصميم لتحقيق التوافر العالي
  2. أنماط الإجماع الموزّع
  3. دراسات حالة حول Erlang OTP
  4. أنماط التحكم في الضغط وتنظيم الحمل
← العودة إلى Erlang OTP: Distributed & Fault-Tolerant Systems Programming