Erlang OTP: Distributed & Fault-Tolerant Systems Programming · บทเรียน

รูปแบบฉันทามติแบบกระจาย

ทำความเข้าใจและใช้งานอัลกอริทึมและรูปแบบฉันทามติแบบกระจาย ซึ่งมีความสำคัญต่อการรักษาความสอดคล้องในระบบแบบกระจาย

บทเรียน 2 จาก 412 ขั้นตอน

รูปแบบฉันทามติแบบกระจาย เป็นบทเรียน Erlang OTP: Distributed & Fault-Tolerant Systems Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 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.

เริ่มต้นได้ฟรี

เรียนรู้ Erlang ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
12
บทเรียน
48

คำถามที่พบบ่อย

บทเรียน “รูปแบบฉันทามติแบบกระจาย” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “รูปแบบฉันทามติแบบกระจาย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 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 ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 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 ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การออกแบบเพื่อความพร้อมใช้งานสูง
  2. รูปแบบฉันทามติแบบกระจาย
  3. กรณีศึกษาของ Erlang OTP
  4. รูปแบบแรงดันย้อนกลับและการควบคุมภาระงาน
← กลับไปที่ Erlang OTP: Distributed & Fault-Tolerant Systems Programming