ふくふくHukuhuku Inc.
EP.08Algorithms 11分公開: 2026-05-11

Raft:etcd・Consul・TiDB の中核を支える分散合意アルゴリズム

「複数のサーバが障害を起こしても、全員が同じ値で合意する」分散合意 Raft を Python で実装。Paxos より理解しやすく、Kubernetes / TiDB / CockroachDB が採用。

#Raft#分散合意#etcd#Kubernetes
CO📔 Google Colab で開く(上から順にセルを実行)
シェア

Kubernetes は etcd の上で動き、etcd は Raft の上で動くTiDB / CockroachDB の分散 SQL も Raft が中核。「複数のサーバが障害を起こしても、全員が同じ値に合意する」という難問 (分散合意問題) を解くのが Raft。Paxos より理解しやすく、本番採用が爆発的に増えた。

1. これで何が動いているか

  • etcd (Kubernetes の状態ストア)
  • HashiCorp Consul / Vault
  • TiDB / CockroachDB (分散 SQL の region 合意)
  • MongoDB レプリカセット (リーダー選出)
  • RabbitMQ Quorum Queues
  • Apache Kafka KRaft mode

2. 仕組みのざっくり

  • 3 状態: Follower / Candidate / Leader
  • term (任期): リーダーごとの番号。古い term の通信は無視される
  • ログ: 各ノードが順序付きで操作を記録
  • 過半数 (quorum): ノード数 N の (N/2)+1 以上が ack で commit
  • 安全性: 古い term の Leader が新しい term の commit を上書きすることはない (Leader Completeness)
Election Timeout のランダム化

Election timeout は 150-300ms の範囲で各ノードがランダム に持つ。これにより複数 Candidate が同時に立候補して票が割れる確率を下げる (Liveness の保証)。

3. Python 実装: リーダー選出 (動作確認済)

Raft の核心: Term + RequestVote + 過半数
Python
import random
class RaftNode:    def __init__(self, node_id, n_peers):        self.id = node_id        self.term = 0        self.voted_for = None        self.peers = list(range(n_peers))        self.role = 'follower'
    def request_vote(self, candidate_id, candidate_term):        '''投票要求を受け取った時の判定'''        if candidate_term > self.term and self.voted_for is None:            self.term = candidate_term            self.voted_for = candidate_id            return True        return False
    def become_candidate(self):        '''選挙開始'''        self.role = 'candidate'        self.term += 1        self.voted_for = self.id  # 自分に投票
    def collect_votes(self, peers):        votes = 1  # 自票        for peer in peers:            if peer.request_vote(self.id, self.term):                votes += 1        return votes
# シナリオ: 5 ノードで 1 台が立候補random.seed(42)nodes = [RaftNode(i, 5) for i in range(5)]candidate = nodes[0]candidate.become_candidate()votes = candidate.collect_votes(nodes[1:])
print(f'Term {candidate.term}: candidate {candidate.id} got {votes}/5 votes')print(f'過半数 (3) 以上? {votes >= 3} → 勝者は {candidate.id}')

4. ログ複製の仕組み

AppendEntries の簡略版
Python
class RaftWithLog:    def __init__(self, node_id):        self.id = node_id        self.term = 0        self.log = []  # [(term, command), ...]        self.commit_index = -1
    def append_entries(self, leader_term, prev_log_index, prev_log_term, entries, leader_commit):        '''Leader からのログ複製要求'''        # 古い term は拒否        if leader_term < self.term:            return False
        # ログの整合性チェック        if prev_log_index >= 0:            if prev_log_index >= len(self.log):                return False  # 自分のログが短い            if self.log[prev_log_index][0] != prev_log_term:                return False  # term が合わない
        # ログ追加        self.log = self.log[:prev_log_index + 1] + entries
        # コミット        if leader_commit > self.commit_index:            self.commit_index = min(leader_commit, len(self.log) - 1)
        return True
# シナリオ: Leader → Follower にログ複製follower = RaftWithLog(1)follower.term = 5ok = follower.append_entries(    leader_term=5, prev_log_index=-1, prev_log_term=0,    entries=[(5, 'set x=1'), (5, 'set y=2')], leader_commit=1)print(f'AppendEntries OK: {ok}, log: {follower.log}, commit: {follower.commit_index}')

5. 障害耐性の計算

ノード数過半数 (quorum)停止可能数推奨用途
110開発環境のみ
321小規模本番
532中規模本番 (推奨)
743大規模
954稀 (通信コスト増)

6. 実用ライブラリ

  • hashicorp/raft (Go): Consul / Vault で利用
  • etcd-io/raft (Go): etcd / Kubernetes で利用
  • tikv/raft-rs (Rust): TiKV / TiDB で利用
  • python-raft / raftos: Python 実装 (学習用)

7. Paxos / Raft / ZAB 比較

特徴PaxosRaftZAB
論文発表1989 (Lamport)2014 (Ongaro)2010 (Reed)
理解しやすさ
Leader 選出オプション必須必須
主な実装Google Chubbyetcd / ConsulZooKeeper
強整合性

8. 次の話

EP.09 では Merkle Tree (ハッシュツリー) を扱います。Bitcoin / Git / IPFS / DynamoDB が改ざん検出と分散同期に使う、暗号学的データ構造の実装。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp