0Pricing
Erlang OTP: Distributed & Fault-Tolerant Systems Programming · 课时

分布式共识模式

了解并实现分布式共识算法和模式,掌握维护分布式系统一致性的关键方法。

分布式共识模式 是 CoddyKit 上的免费 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 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.

常见问题解答

「分布式共识模式」课时是免费的吗?

是的 — 「分布式共识模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 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 导师会在你学习这节课的过程中回答你的问题。

学习 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Erlang OTP: Distributed & Fault-Tolerant Systems Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 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