前面 19 天,我們已經學過 Load
Balancer、Database、Index、Cache、Replication、Sharding、CDN、Message
Queue、Rate
Limiter、Consistency、Reliability、Observability、Security,以及 System
Design Interview Process。
Day 20 開始,我們把這些 Building Blocks 真正組合成完整 System。
今天的題目:
Design a URL Shortener
例如:
Long URL:
https://example.com/articles/system-design/day20?user=123
Short URL:
https://sho.rt/aB3x9K
看起來只是「把網址變短」,但當 Scale 變成 Millions of new
URLs/day、Billions of redirects/day,就會出現 Short
Code、Collision、Cache、Replication、Sharding、Hot
Key、Expiration、Analytics、Reliability 與 Security 等問題。
URL = Uniform Resource Locator
可以先理解成:
Internet 上某個 Resource 的地址。
Short URL:
一個較短的 URL,用來代表另一個 Long URL。
System 通常保存:
aB3x9K
→
https://example.com/articles/system-design/day20
這種對應關係叫 Mapping。
Mapping:
建立兩個 Value 之間的對應關係。
URL Shortener 最核心的 Data:
short_code → long_url
User 開啟:
sho.rt/aB3x9K
Shortener 找到 Long URL 後,告訴 Browser 去另一個地址。
這叫:
Redirect
Server 告訴 Client:「你要找的 Resource 在另一個 URL,請去那裡。」
流程:
Browser
↓
GET /aB3x9K
↓
URL Shortener
↓
Find Long URL
↓
Return Redirect Response
↓
Browser visits Long URL
Redirect 常使用 HTTP 3xx Status Code。
301 Moved Permanently:
比較偏向永久 Redirect。
Browser / Cache 可能更積極 Cache,因此可能降低 Shortener Server
Traffic,但也可能讓部分 Click 不再經過你的 Server。
302 Found:
比較偏向暫時 Redirect。
如果希望更多 Click 經過 Shortener 做 Analytics,可能考慮這類 Redirect。
不要死背:
URL Shortener = 301
或:
URL Shortener = 302
要根據:
Caching Requirement
Analytics Requirement
Product Behavior
做 Trade-off。
面試官說:
Design a URL Shortener
第一步不是 Redis,而是先問 System 要做什麼。
Functional Requirement:
System 必須提供哪些功能。
假設:
1. Create Short URL
2. Redirect Short URL
3. Support Expiration
4. Basic Click Analytics
Non-Functional Requirement:
功能需要做到多快、多穩、多大、多安全。
假設:
Low Redirect Latency
High Availability
Durable URL Mapping
Large Read Traffic
Unique Short Codes
In Scope:
- Create URL
- Redirect
- Expiration
- Basic Analytics
- Scaling
- Reliability
- Basic Security
Out of Scope:
- Ads
- Complex dashboard
- Recommendation
- Billing
為了練習 Estimation,假設:
10M new URLs/day
1B redirects/day
500 Bytes/URL record
Peak = 5 × Average
Retention = 5 years
這些只是練習用 Assumptions,不代表任何真實公司的數據。
一天快速估成:
≈ 100K seconds
Create:
10M / 100K
≈ 100 writes/sec
Redirect:
1B / 100K
≈ 10K reads/sec
所以:
Read : Write ≈ 100 : 1
這代表 System 非常 Read-heavy。
Read-heavy:
Read Operations 遠多於 Write Operations。
Average Redirect ≈ 10K RPS
Peak Factor = 5
所以:
Peak ≈ 50K RPS
Architecture 不能只按照 Average 設計。
10M records/day
×
500 Bytes
≈
5 GB/day
一年:
≈ 1.8 TB
五年:
≈ 9 TB Raw Data
Raw Data:
還沒有加入 Index、Replication、Backup、Metadata 等額外 Storage
的原始資料量。
核心 Operations:
Create Short URL
Redirect
POST /urls
Request:
{
"longUrl": "https://example.com/articles/123",
"expiresAt": "2027-01-01T00:00:00Z"
}
Response:
{
"shortCode": "aB3x9K",
"shortUrl": "https://sho.rt/aB3x9K"
}
GET /aB3x9K
Server 找到 Long URL 後回傳 Redirect。
Expiration:
Resource 到某個時間後失效。
expiresAt 表示:
Short URL 什麼時間之後不再有效。
注意:
URL Expiration
和之後的:
Cache TTL
不是同一件事。
URL
├── short_code
├── long_url
├── created_at
├── expires_at
└── user_id
核心 Access Pattern:
short_code → long_url
Access Pattern:
Application 平常最常用什麼方式讀寫 Data。
Primary Key:
唯一識別一筆 Database Record 的 Key。
Unique Constraint:
Database 不允許某欄位出現重複 Value 的規則。
Short Code 如果作為 Identifier:
aB3x9K
不能同時指向兩個不同 Long URLs。
Short Code:
Short URL 中用來找到 Long URL 的短字串。
例如:
https://sho.rt/aB3x9K
↑
Short Code
接下來的問題:
Short Code 到底怎麼產生?
常見思路:
Random Code
Hash-based Code
Unique ID + Base62
Character Set:
允許使用哪些 Characters 的集合。
例如:
a-z = 26
A-Z = 26
0-9 = 10
總共:
62 characters
數字系統中的 Base:
一個位置可以使用多少種不同 Symbols。
Decimal:
Base10
→ 0-9
Binary:
Base2
→ 0, 1
Base62:
使用 62 個 Characters 表示數值的 Encoding 方法。
常見:
0-9
a-z
A-Z
共 62 個 Symbols。
Encoding:
按照一套規則,把 Data 轉成另一種表示方式。
例如:
Integer ID
↓
Base62 Encoding
↓
Short String
Base62 不是 Encryption;它只是表示方式的轉換。
6 Characters:
62^6
≈ 56.8 Billion
7 Characters:
62^7
≈ 3.5 Trillion
Combination 在這裡可以理解:
不同 Character 排列能產生多少不同結果。
Random:
按某種隨機方式選擇結果,而不是固定順序。
例如隨機選 6 個 Base62 Characters:
aB3x9K
問題是可能發生:
Collision
Collision:
兩個不同 Records 最後得到相同 Identifier。
例如:
URL A → aB3x9K
URL B → aB3x9K
這是不允許的。
可以:
Generate
↓
Check DB
↓
Exists?
├─ Yes → Generate Again
└─ No → Save
Collision Handling:
發生重複時,System 如何處理。
Probability:
某件事情發生的可能性。
Collision Probability:
隨機產生 Codes 時出現重複的機率。
Code Space 越大,Collision 通常越不容易發生,但不能說永遠不會發生。
Birthday Problem / Birthday Paradox:
當隨機選擇數量增加時,兩個結果碰巧相同的機率會比很多人的直覺更快上升。
URL Short Code 的概念也類似。
今天不用背公式,只要記:
Random Code
→ Large Code Space helps
→ Collision Handling still needed
Hash Function:
把 Input 經固定計算轉成某個 Hash Output。
概念:
Long URL
↓
Hash Function
↓
Hash Value
同一 Input 通常得到同一 Output。
但 Hash 仍可能有 Collision,尤其把長 Hash 截短時。
Encryption:
Data 透過 Key 轉成密文,持有正確 Key 時可以解密。
Hash:
通常設計成單向轉換,不是拿來還原原始 Input。
所以:
Hash ≠ Encryption
另一個方法:
Generate Unique Integer ID
↓
Base62 Encode
↓
Short Code
如果 ID 本身 Unique,Base62 又是一對一轉換,就比較容易 reasoning about
uniqueness。
Unique ID:
每一筆 Record 都不重複的 Identifier。
例如:
1001
1002
1003
Auto Increment:
Database 每新增 Record,自動產生下一個遞增 ID。
單一 Database 很簡單。
但多台 Writers 時會出現:
誰負責產生下一個 ID?
Distributed:
工作由多台 Machines / Nodes 共同完成。
Distributed ID Generation:
多台 Servers 同時建立 Records 時,仍能產生不重複 IDs。
例如:
Server A
Server B
Server C
不能同時都拿到:
1001
ID Generator:
專門負責產生 Unique IDs 的 Component。
URL Service
↓
ID Generator
↓
Unique ID
↓
Base62
但它也可能帶來:
SPOF
Scaling
Availability
等新問題。
Sequential:
按照順序排列。
例如:
1001
1002
1003
這種 ID 很簡單,但可能容易猜。
Enumeration:
按照可能的 Identifier 一個一個嘗試。
例如:
/1001
/1002
/1003
所以 Short Code Strategy 也有 Security Trade-off。
為了容易理解,今天採:
Unique ID
↓
Base62
↓
Short Code
優點:
Uniqueness reasoning simple
Compact code
Fast lookup
Trade-off:
Need scalable ID generation
Sequential information may be predictable
沒有唯一正解。
不要背:
URL Shortener = NoSQL
先看 Access Pattern:
short_code → long_url
主要需求:
Key-based Lookup
High Read Traffic
Simple Record
Large Scale
SQL 或 Key-Value Store 都可能合理。
Key-Value Store:
用 Key 找 Value 的 Data Store。
例如:
Key:
aB3x9K
Value:
https://example.com/article/123
很符合 URL Shortener 的核心 Access Pattern。
例如:
CREATE TABLE urls (
short_code VARCHAR(10) PRIMARY KEY,
long_url TEXT NOT NULL,
created_at TIMESTAMP NOT NULL,
expires_at TIMESTAMP
);
Lookup:
SELECT long_url
FROM urls
WHERE short_code = ?;
有合適 Primary Key / Index 時也可以很快。
User
↓
URL Service
↓
Database
Create:
POST /urls
↓
Generate Code
↓
Database
↓
Return Short URL
Redirect:
GET /aB3x9K
↓
Database
↓
Long URL
↓
Redirect
先簡單,再根據 Bottleneck 演進。
Peak 約:
50K Redirect RPS
一台 Backend 可能不夠。
所以:
User
↓
Load Balancer
↓
URL Service #1
URL Service #2
URL Service #3
Stateless:
Backend 不依賴自己 Machine Memory 裡保存的永久 User-specific State
才能處理下一個 Request。
URL Mapping 放在:
Shared Cache / Database
而不是只存在 Server #1。
所以 Request 去 Server #2 也能處理。
這讓 Horizontal Scaling 更容易。
因為:
Read : Write ≈ 100 : 1
而 Popular URLs 會反覆被讀。
每次都查 DB:
Database may become bottleneck
因此 Cache 很合理。
User
↓
Load Balancer
↓
URL Service
↓
Redis
↓ Cache Miss
Database
Cache-Aside:
Application 先查 Cache;找不到再查 DB,然後把結果放入 Cache。
Cache Hit
→ Return
Cache Miss
→ DB
→ Put Cache
→ Return
Cache Hit:
Data 已在 Cache。
Cache Miss:
Cache 找不到,需要查下一層。
假設:
Peak Read = 50K RPS
Hit Rate = 95%
DB:
50K × 5%
=
2.5K RPS
Cache 可以大幅降低 DB Load。
TTL = Time To Live
Cache Entry 可以存在多久。
例如:
TTL = 1 hour
一小時後 Entry 過期。
注意:
Cache TTL
≠
URL Expiration
URL 可以有效一年,但 Cache Copy 只保留一小時。
Hot Key:
某一個 Key 收到遠高於其他 Keys 的 Traffic。
例如 Celebrity 分享:
sho.rt/viral
突然收到大量 Requests。
Hotspot:
System 某個局部 Component / Key / Partition 承受過度集中 Load。
Hot Key 是 Hotspot 的一種。
Local Cache:
存在每台 Backend 自己 Memory 裡的 Cache。
優點:
Very low latency
Reduce Redis traffic
Trade-off:
Duplicated memory
Harder invalidation
Different servers may have different copies
Coalesce:
把多個相同需求合併。
Request Coalescing:
大量 Requests 同時需要同一筆 Missing Data 時,只讓少數 Request
去載入,其餘等待 / 共用結果。
例如:
10,000 Cache Misses
不是:
10,000 DB Queries
而可能:
1 load
→ shared result
Cache Stampede:
熱門 Cache Entry 過期後,大量 Requests 同時 Miss,全部衝向 DB。
Request Coalescing 是可能的緩解方法之一。
如果 Read Capacity 還需要提高:
Primary
↓
Replica #1
Replica #2
Write:
Primary
Reads:
Replica
Replica:
Database Data 的另一份 Copy。
Replication Lag:
Primary 已更新,但 Replica 尚未收到最新 Data 的時間差。
例如剛建立:
aB3x9K
Primary 有,但 Replica 還沒有。
User 馬上開啟 Short URL:
Replica → Not Found
Read-After-Write Consistency:
User 剛完成 Write 後,接下來的 Read 應能看到自己剛寫入的 Data。
URL Shortener:
Create URL
↓
Immediately open it
User 會期待它馬上能用。
這裡簡化理解:
Write-through Cache:
成功寫入主要 Data Store 時,也同步更新對應 Cache。
例如:
Write DB
↓
Put Redis
↓
Return Short URL
但要處理:
DB success
Cache failure
這種 Partial Failure。
Partial Failure:
多個 Components 參與 Operation 時,一部分成功、一部分失敗。
例如:
DB Write = Success
Cache Write = Failure
Distributed System 很常遇到這種情況。
如果 Data / Write Capacity 最後超過一台 DB:
Sharding:
把不同 Data 分散到不同 Database Servers。
例如:
Shard #1
Shard #2
Shard #3
Shard Key:
決定 Record 應該去哪個 Shard 的 Key。
URL Shortener 可以考慮 short_code,因為主要 Lookup 本來就是:
short_code → long_url
例如:
hash(short_code) % number_of_shards
Hash-based Sharding:
先 Hash Shard Key,再根據結果決定 Shard。
可以幫助 Data 比較平均分散。
但 Sharding 會增加:
Routing
Rebalancing
Operational Complexity
所以不要過早 Shard。
URL 過期:
now > expires_at
就不 Redirect。
Lazy Deletion:
Data 過期後不一定立刻從 DB 刪除,而是在讀取時判斷失效,再由之後的
Process 清理。
Background Job:
不需要 User 等待完成、可以在背景執行的工作。
例如:
Delete expired URLs
Send Email
Process Analytics
Cleanup Job:
專門清理不再需要 Data 的 Background Job。
Scheduler:
按照時間或規則安排 Job 執行的 Mechanism。
例如:
Every hour
→ Delete expired URLs
Analytics:
收集與分析 User Behavior / System Data。
URL Shortener 可能想知道:
Click Count
Country
Device
Time
Referrer
每次 Redirect 可以產生:
URL_CLICKED
Event:
描述某件事情已經發生的 Message。
例如:
{
"event": "URL_CLICKED",
"shortCode": "aB3x9K"
}
Critical Path:
User 的核心 Operation 成功前必須完成的必要步驟。
Redirect:
Find Long URL
↓
Return Redirect
Analytics 通常不是 Redirect 成功的必要條件。
可以:
Redirect Service
├── Return Redirect
└── Publish Event
↓
Message Queue
↓
Analytics Consumer
Asynchronous Processing:
Caller 不必等待所有工作完成,就能先繼續。
Consumer:
從 Message System 接收 Message 並處理工作的 Component。
Analytics Consumer:
URL_CLICKED
↓
Process
↓
Analytics Storage
Message Queue 在這裡不是因為「大型系統一定要 Kafka」,而是因為 Analytics
不應阻塞 Redirect。
如果某台 Backend Crash:
URL Service #2 ❌
Load Balancer 的 Health Check 可以停止把新 Requests 傳給它。
Health Check:
定期確認 Component 是否能正常提供 Service 的檢查。
Redis Down 時可能:
Fallback to DB
Fallback:
主要方法不能使用時,改用備用方法。
但如果所有 Cache Traffic 突然打 DB,可能造成 Cascading Failure。
Cascading Failure:
一個 Component Failure 導致其他 Components Overload,最後更多
Components 也失敗。
例如:
Redis Down
↓
All Reads → DB
↓
DB Overloaded
↓
Backend waits
↓
Backend overload
所以 Fallback 本身也需要 Capacity Planning。
Primary Failure:
Primary ❌
Replica ✅
可以 Promote Replica。
Failover:
主要 Component 失敗時,把工作切換到健康 Backup / Replica。
Failover 可能需要:
Failure Detection
Promotion
Routing Update
Consistency Handling
Create API 可能被大量濫用。
Rate Limiter:
限制 Client 在一段時間內可以執行多少 Operations。
例如:
100 URL creations/min/user
Abuse:
用不符合正常用途、可能傷害 Service 或 Users 的方式使用 System。
Malicious URL:
可能導向 Malware、Phishing 或其他有害內容的 URL。
Phishing:
攻擊者假裝成可信任 Service,誘騙 User 提供 Password、Credit Card
等資訊。
Short URL 會隱藏 Destination,因此需要考慮 Abuse Protection。
Blocklist:
明確禁止的 Items 清單。
例如:
Known malicious domains
Known phishing URLs
Create URL 時可以檢查。
但 Blocklist 不能保證抓到所有新攻擊。
Validation:
檢查 Input 是否符合預期規則。
例如:
Valid URL format?
Allowed protocol?
Too long?
Blocked destination?
URL 中:
https://example.com
https 是 Scheme。
Scheme:
表示使用什麼 Protocol / 方法存取 Resource。
Authentication:
確認「你是誰」。
Authorization:
確認「你有沒有權限做這件事」。
例如 User A 不應該刪除 User B 的 Short URL。
簡單記:
Authentication → Who are you?
Authorization → What can you do?
Observability:
透過 System Signals 理解內部狀態與問題。
可以監控:
Redirect RPS
Create RPS
Latency
Cache Hit Rate
DB QPS
Error Rate
Queue Backlog
Metrics:
可以持續測量的數值。
Error Rate:
所有 Requests 中失敗 Requests 的比例。
例如:
100K Requests
1K Errors
→ 1%
但要區分:
Expected 404
vs
Server 500 Error
因為代表不同問題。
把 Requests Latency 從快到慢排序。
p95:
大約 95% Requests 不超過這個 Latency。
p99:
大約 99% Requests 不超過這個 Latency。
Average 很低,不代表沒有少數非常慢的 Requests。
User
↓
DNS / CDN
↓
Load Balancer
/ \
↓ ↓
URL Service URL Service
\ /
\ /
Redis
↓
Database Layer
/ \
Primary Replica(s)
↓
Optional Sharding
Create Path:
User
↓
Rate Limiter
↓
URL Service
↓
Validate Long URL
↓
Generate Unique ID
↓
Base62 Encode
↓
Write Database
↓
Populate Cache
↓
Return Short URL
Redirect Path:
User
↓
Load Balancer
↓
URL Service
↓
Redis
├─ Hit → Long URL
└─ Miss → Database → Cache
↓
HTTP Redirect
Analytics:
Redirect Service
↓
Publish URL_CLICKED
↓
Message Queue
↓
Analytics Consumer
↓
Analytics Storage
因為真正的推導應該是:
Requirement
↓
Scale
↓
Bottleneck
↓
Solution
↓
Trade-off
Cache 存在是因為:
Read-heavy
Repeated Lookup
Low Latency
Message Queue 存在是因為:
Analytics 不需要阻塞 Redirect
Replication 是因為:
Read Scaling
Availability
Failover
Sharding 只有在:
Storage / Write Scale
真的需要時才加入。
Problem:
One Backend cannot handle all traffic
Solution:
Multiple Backends + Load Balancer
Trade-off:
More infrastructure and health checking
Problem:
Huge repeated reads
Solution:
Redis
Trade-off:
Memory cost
Invalidation
Stale data
Cache failure
Problem:
Read capacity / availability
Solution:
Primary + Replicas
Trade-off:
Replication lag
Failover complexity
Problem:
One DB cannot hold / write all data
Solution:
Split data
Trade-off:
Routing
Rebalancing
Operational complexity
Problem:
Analytics should not slow Redirect
Solution:
Async Events
Trade-off:
Eventual processing
Duplicates
Queue monitoring
不要只說:
Redis is fast.
可以回答:
Redirect traffic is much higher than URL creation traffic, and popular
short codes are repeatedly requested. I would use Redis as a cache to
reduce database read load and redirect latency. The trade-offs are
memory cost, cache invalidation, stale data, and the risk of database
overload if the cache fails.
I would not shard immediately. I would first determine whether storage
capacity or write throughput is actually the bottleneck. If one
database can no longer handle the dataset or write load, then I would
consider sharding.
301
→ More cache-friendly
→ Can reduce Shortener traffic
302
→ More requests return to service
→ Better visibility for click analytics
根據 Product Requirement 選。
Random
+ Harder to predict
- Collision handling
ID + Base62
+ Easy uniqueness reasoning
+ Compact
- Distributed ID generation
- Potential predictability
可以 Fallback to DB,但必須補充:
Database needs enough headroom, otherwise all cache traffic falling
back to the database may cause a cascading failure.
可能:
Write Primary
↓
Read Replica
↓
Replication Lag
可以討論:
Populate Cache after write
Temporarily read Primary
Other Read-After-Write strategies
Requirements
□ Create?
□ Redirect?
□ Expiration?
□ Analytics?
□ Authentication?
Scale
□ URLs/day?
□ Redirects/day?
□ Average RPS?
□ Peak RPS?
□ Read / Write Ratio?
□ Storage?
□ Retention?
Short Code
□ Random?
□ Hash?
□ ID + Base62?
□ Collision?
□ Predictability?
Database
□ SQL / Key-Value?
□ Primary Key?
□ Replication?
□ Sharding?
Cache
□ Cache-Aside?
□ TTL?
□ Hit Rate?
□ Hot Key?
□ Stampede?
□ Failure?
Reliability
□ Multiple Backends?
□ Health Check?
□ Failover?
□ Cascading Failure?
Consistency
□ Replication Lag?
□ Read-After-Write?
□ Partial Failure?
Analytics
□ Async?
□ Message Queue?
□ Consumer?
□ Critical Path?
Security
□ Validation?
□ Rate Limiting?
□ Authentication?
□ Authorization?
□ Phishing?
□ Blocklist?
Observability
□ RPS?
□ p95 / p99?
□ Error Rate?
□ Cache Hit Rate?
□ DB Load?
1. URL Shortener?
2. Mapping?
3. Redirect?
4. 301 vs 302?
5. Expiration?
6. Short Code?
7. Access Pattern?
8. Primary Key?
9. Unique Constraint?
10. Character Set?
11. Base / Base62?
12. Encoding?
13. 62^6 約多少?
14. Random Code?
15. Collision?
16. Collision Handling?
17. Collision Probability?
18. Birthday Problem?
19. Hash Function?
20. Hash vs Encryption?
21. Unique ID?
22. Auto Increment?
23. Distributed ID Generation?
24. ID Generator?
25. Sequential ID?
26. Enumeration?
27. Key-Value Store?
28. Stateless Backend?
29. Cache-Aside?
30. Cache Hit / Miss / Hit Rate?
31. TTL?
32. Cache TTL vs URL Expiration?
33. Hot Key / Hotspot?
34. Local Cache?
35. Request Coalescing?
36. Cache Stampede?
37. Replica?
38. Replication Lag?
39. Read-After-Write?
40. Write-through Cache?
41. Partial Failure?
42. Sharding / Shard Key?
43. Hash-based Sharding?
44. Lazy Deletion?
45. Background Job?
46. Cleanup Job?
47. Scheduler?
48. Analytics / Event?
49. Critical Path?
50. Asynchronous Processing?
51. Consumer?
52. Health Check?
53. Fallback?
54. Cascading Failure?
55. Failover?
56. Rate Limiting / Abuse?
57. Malicious URL / Phishing?
58. Blocklist?
59. Validation / Scheme?
60. Authentication vs Authorization?
61. Observability / Metrics?
62. Error Rate?
63. p95 / p99?
64. 為什麼 URL Shortener 適合 Cache?
65. 為什麼不能一開始就 Shard?
66. Cache Down 為什麼可能造成 Cascading Failure?
67. URL 剛建立卻打不開可能是什麼問題?
68. Analytics 為什麼適合 Message Queue?
不要背:
URL Shortener
=
Load Balancer + Redis + DB + Queue
要理解推導:
Requirement
↓
Create + Redirect
Scale
↓
Read ≫ Write
Problem
↓
Repeated DB reads
Solution
↓
Cache
Problem
↓
One Backend cannot handle peak
Solution
↓
Load Balancer + Horizontal Scaling
Problem
↓
Need read capacity / availability
Solution
↓
Replication
Problem
↓
Dataset / write capacity exceeds one DB
Solution
↓
Sharding
Problem
↓
Analytics slows redirect
Solution
↓
Async Event + Message Queue
Problem
↓
Malicious / excessive usage
Solution
↓
Validation + Rate Limiting + Abuse Protection
Short Code 也要思考:
Code Space
Uniqueness
Collision
Predictability
Generation at Scale
核心仍然是:
Problem
↓
Requirement
↓
Solution
↓
Trade-off
真正的 System Design 能力,不是記住 URL Shortener 的標準
Architecture,而是能從 Requirements 一步一步推導出 Architecture。
Day 21|Design Notification System:Email、SMS、Push Notification
如何可靠地送到 Millions of Users?
會解釋:
Notification
Push Notification
Email
SMS
Channel
Provider
Fan-out
Template
Preference
Opt-in / Opt-out
Message Queue
Retry
Exponential Backoff
Idempotency
Deduplication
Priority
Scheduling
Delivery Status
Dead Letter Queue
Rate Limiting
Provider Failure
每一個新名詞都會先用初學者能理解的方式解釋,再放進 Architecture。