スケーラビリティを学ぶ10のバックエンドプロジェクト
概要¶
スケーラビリティを実践的に学べるバックエンドプロジェクトを10個紹介した投稿。実際に手を動かしながらシステム設計の感覚を身につけるための教材として使える。
詳細¶
投稿で紹介されている10プロジェクト:
0. Notification system
1. Video processing queue
2. Search autocomplete
3. Real-time leaderboard
4. Payment retry engine
5. Email delivery service
6. Analytics event pipeline
7. Collaborative text editor
8. Distributed job runner
9. (投稿の「さらに表示」部分)
また引用ポストでは週末プロジェクト10アイデアも紹介:
0. Reverse proxy
1. API Gateway
2. Simple cron scheduler
3. KV store
4. Consistent hashing
5. Redis clone over TCP
6. Auth System
7. Server-sent events (SSEs)
8. Message Queue system
9. Distributed lock service
なぜ重要か / いつ使うか¶
各プロジェクトで学べるスケーラビリティの概念¶
| プロジェクト | 学べる概念 |
|---|---|
| Notification system | Fan-out パターン、Push/Pull、WebSocket vs SSE |
| Video processing queue | 非同期処理、Worker Pool、S3 + FFmpeg |
| Search autocomplete | Trie、Redis Sorted Set、キャッシュ戦略 |
| Real-time leaderboard | Redis Sorted Set (ZADD/ZRANK)、WebSocket |
| Payment retry engine | 冪等性、指数バックオフ、デッドレターキュー |
| Email delivery service | レートリミット、SMTP、非同期キュー |
| Analytics event pipeline | Kafka、バッチ処理 vs ストリーム処理 |
| Collaborative text editor | CRDT / OT (Operational Transformation)、WebSocket |
| Distributed job runner | cron、分散スケジューリング、リース |
Real-time leaderboard の実装例(Redis)¶
import redis
r = redis.Redis()
# スコア追加・更新
def update_score(user_id: str, score: float):
r.zadd("leaderboard", {user_id: score})
# 上位10人を取得
def get_top10():
return r.zrevrange("leaderboard", 0, 9, withscores=True)
# 特定ユーザーの順位
def get_rank(user_id: str):
return r.zrevrank("leaderboard", user_id)
Payment retry engine の冪等性設計¶
// 冪等キーを使ってダブル課金を防ぐ
func ProcessPayment(idempotencyKey string, amount int) error {
// 既に処理済みか確認
if _, exists := processedKeys[idempotencyKey]; exists {
return nil // 成功として扱う(重複リクエスト)
}
err := chargeCard(amount)
if err != nil {
return err
}
processedKeys[idempotencyKey] = true
return nil
}
指数バックオフ + ジッター(リトライ戦略)¶
import random, time
def retry_with_backoff(fn, max_retries=5, base_delay=1.0):
for attempt in range(max_retries):
try:
return fn()
except Exception as e:
if attempt == max_retries - 1:
raise
# 指数バックオフ + ジッター(同時リトライの回避)
delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
time.sleep(delay)