κ°μ λ©΄μ μ¬λ‘λ‘ λ°°μ°λ λκ·λͺ¨ μμ€ν μ€κ³ κΈ°μ΄ 4μ₯
πΉ μ²λ¦¬μ¨ μ ν μ₯μΉ(Rate Limiting)λ ν΄λΌμ΄μΈνΈ λλ μλΉμ€κ° 보λ΄λ νΈλν½μ μ μ΄νλ μ₯μΉλ€.
πΉ API μμ² νμκ° μ€μ λ μκ³μΉλ₯Ό μ΄κ³Όνλ©΄ μΆκ° μμ²μ΄ κ±°λΆλλ€.
π μ£Όμ λͺ©μ
β
DoS(μλΉμ€ κ±°λΆ) 곡격 λ°©μ§ β μ
μμ μΈ νΈλν½μ΄ μλ² μμμ μλͺ¨νμ§ μλλ‘ λ§μ.
β
λΉμ© μ κ° β μλ² μμμ λλΉνμ§ μκ³ , μ°μ μμκ° λμ APIμ λ λ§μ μμμ λ°°μ κ°λ₯.
β
μλ² κ³ΌλΆν λ°©μ§ β λ΄ νΈλν½ λ° μλͺ»λ μ¬μ©μ μμ²μ νν°λ§νμ¬ μ±λ₯ μ μ§.
β οΈ μ λ΅μ μμ!
β νμ¬ μ¬μ©νλ κΈ°μ μ€ν, μμ§λμ΄λ§ 리μμ€, λΉμ¦λμ€ λͺ©νμ λ°λΌ κ²°μ ν΄μΌ ν¨.
π ν¨μ¨μ μΈ μ²λ¦¬μ¨ μ νμ μν΄ κ³ λ €ν μ¬ν
β
κΈ°μ μ€ν μ κ² β νμ¬ μ¬μ©νλ νλ‘κ·Έλλ° μΈμ΄ λ° μΊμ μμ€ν
(μ: Redis)κ³Όμ νΈνμ± νμΈ.
β
μ μ ν μκ³ λ¦¬μ¦ μ ν β μλ² vs. κ²μ΄νΈμ¨μ΄ λ°°μΉμ λ°λΌ μ¬μ© κ°λ₯ν μκ³ λ¦¬μ¦μ΄ λ¬λΌμ§ μ μμ.
β
API Gateway νμ© μ¬λΆ β μ΄λ―Έ κ²μ΄νΈμ¨μ΄λ₯Ό μ¬μ© μ€μ΄λΌλ©΄ μ²λ¦¬μ¨ μ ν κΈ°λ₯μ ν¬ν¨νλ κ²μ΄ ν©λ¦¬μ .
β
μ§μ ꡬν vs. Managed API μ¬μ© β μ체 ꡬνμ΄ μ΄λ €μ°λ©΄ ν΄λΌμ°λ API(μ: AWS API Gatewayμ Rate Limiting)λ₯Ό νμ©νλ κ²λ λ°©λ².
π λ€μν μκ³ λ¦¬μ¦μ΄ μμΌλ©°, κ°κ° μ₯λ¨μ μ΄ μ‘΄μ¬ν¨
πͺ£ μ€λͺ
β
μ₯μ
βοΈ κ°λ¨νκ³ κ΅¬νμ΄ μ¬μ.
βοΈ λ²μ€νΈ νΈλν½ μ²λ¦¬ κ°λ₯ β μμ²μ΄ λͺ°λ €λ 미리 μ μ₯λ ν ν°μ΄ μμΌλ©΄ μ²λ¦¬ κ°λ₯.
β λ¨μ
β οΈ λ²ν· ν¬κΈ°μ ν ν° κ³΅κΈλ₯ μ‘°μ μ΄ μ΄λ ΅λ€ β νΈλν½ ν¨ν΄μ λ°λΌ μ΅μ μ κ° μ€μ μ΄ μ€μν¨.
π° μ€λͺ
β
μ₯μ
βοΈ λ©λͺ¨λ¦¬ ν¨μ¨μ .
βοΈ μΌμ ν μλλ‘ μμ²μ μ²λ¦¬ν΄ μλ² λΆνκ° κΈκ²©ν μ¦κ°νμ§ μμ.
β λ¨μ
β οΈ νΈλν½ κΈμ¦ μ μ΅μ μμ²μ΄ μμ€λ κ°λ₯μ± μμ β μ€λλ μμ²μ΄ νμ μμ¬μ μ΅μ μμ²μ΄ μ²λ¦¬λμ§ λͺ»ν μλ μμ.
π μ€λͺ
β
μ₯μ
βοΈ κ°λ¨νκ³ λ©λͺ¨λ¦¬ ν¨μ¨μ .
βοΈ νΉμ νΈλν½ ν¨ν΄μ μ²λ¦¬νκΈ°μ μ ν©.
β λ¨μ
β οΈ μλμ° κ²½κ³μμ νΈλν½μ΄ λͺ°λ¦΄ κ²½μ° μκ³μΉλ₯Ό μ΄κ³Όν μ μμ β μκ°μ μΈ λΆνλ₯Ό νμ©ν μ μμ.
π μ€λͺ
β
μ₯μ
βοΈ μ κ΅ν νΈλν½ μ μ΄ κ°λ₯ β μ΄λ μκ°μ κΈ°μ€μΌλ‘ 보λλΌλ μ νν μ νμ μ μ©ν μ μμ.
β λ¨μ
β οΈ λ©λͺ¨λ¦¬ μ¬μ©λ μ¦κ° β λͺ¨λ μμ²μ νμμ€ν¬νλ₯Ό μ μ₯ν΄μΌ νλ―λ‘ λΆνκ° μ¦κ°ν μ μμ.
π μ€λͺ
β
μ₯μ
βοΈ νΈλν½ κΈμ¦μλ ν¨κ³Όμ μΌλ‘ λμ.
βοΈ λ©λͺ¨λ¦¬ ν¨μ¨μ΄ μ’μ.
β λ¨μ
β οΈ νΈλν½ ν¨ν΄μ΄ κ· λ±νκ² λΆν¬λλ€κ³ κ°μ ν¨ β μ€μ νΈλν½ νκ²½μμλ λΆμ νν μ μμ.
π μΌλ°μ μΈ μ²λ¦¬ κ³Όμ
1οΈβ£ ν΄λΌμ΄μΈνΈκ° μμ²μ 보λ.
2οΈβ£ μ²λ¦¬μ¨ μ ν λ―Έλ€μ¨μ΄κ° μμ²μ κ°λ‘μ±μ Redisμμ μΉ΄μ΄ν° κ°μ νμΈ.
429 Too Many Requests μλ΅ λ°ν. π μ€μ μ§μ€ν λ°μ΄ν° μ μ₯μ μ¬μ©
π π₯ λ¬Έμ 1: κ²½μ 쑰건
π π λ¬Έμ 2: λκΈ°ν μ΄μ
π Hard vs. Soft μ²λ¦¬μ¨ μ ν
π μ²λ¦¬μ¨ μ ν ννΌ λ°©λ²
β
ν΄λΌμ΄μΈνΈ μΊμ± νμ©ν΄ API νΈμΆ νμ κ°μ.
β
λ°±μ€ν(μ¬μλ) λ‘μ§ κ΅¬ν μ μΆ©λΆν λκΈ° μκ° μ μ©.
π μ²λ¦¬μ¨ μ ν μ₯μΉλ μλ² λ³΄νΈ, λΉμ© μ κ°, νΈλν½ κ΄λ¦¬ μΈ‘λ©΄μμ νμμ μΈ κΈ°λ₯!
πΉ μꡬμ¬ν λ° κΈ°μ μ€νμ λ°λΌ μ μ ν μκ³ λ¦¬μ¦κ³Ό ꡬν λ°©μμ μ νν΄μΌ νλ€.
πΉ Redis κ°μ λΉ λ₯Έ μΊμ μμ€ν
μ νμ©νμ¬ ν¨μ¨μ μΈ νΈλν½ μ μ΄ κ°λ₯!
ZADD: λ°μ΄ν° μΆκ° ZINCRBY: μ μ μ¦κ° (μμμ μ°μ°) ZRANGE: μ μ μ μ λ ¬λ λ°μ΄ν° μ‘°ν ZREVRANGE: μ μ λ΄λ¦Όμ°¨μ μ λ ¬ ZREM: νΉμ λ©€λ² μμ ZSCORE: νΉμ λ©€λ² μ μ μ‘°ν π μ μ© λμ: λ¨μΌ Redis μΈμ€ν΄μ€ νκ²½
ZADD, ZINCRBY λ±μ μ°μ°μ μμμ μΌλ‘ μ€νλ¨ π μ μ© λμ: κΈ°λ³Έμ μΈ λ°μ΄ν° μΆκ°/μμ
WATCH λͺ
λ Ήμ΄λ‘ νΉμ ν€λ₯Ό κ°μ β κ°μ΄ λ³κ²½λλ©΄ νΈλμμ
μ·¨μ MULTI/EXECμ μ¬μ©νμ¬ μμμ νΈλμμ
μ€ν π μ μ© λμ: κ²½μ μ‘°κ±΄μ΄ λ°μν κ°λ₯μ±μ΄ μλ κ²½μ° (μ: λμΌν ν€μ λν μ¬λ¬ ν΄λΌμ΄μΈνΈμ λμ μ κ·Ό)
π μμ (μ μ μ λ°μ΄νΈ)
WATCH leaderboard
MULTI
ZINCRBY leaderboard 20 "Alice"
EXEC # λ€λ₯Έ ν΄λΌμ΄μΈνΈκ° λ³κ²½νμ§ μμμ κ²½μ° μ€νλ¨
π μ μ© λμ: μ¬λ¬ κ°μ μ°μ°μ μμμ μΌλ‘ μ²λ¦¬ν΄μΌ ν λ
π μμ (μ μ μ¦κ° μμμ μ€ν)
local key = KEYS[1]
local member = ARGV[1]
local increment = tonumber(ARGV[2])
local currentScore = redis.call("ZSCORE", key, member)
if currentScore then
return redis.call("ZADD", key, currentScore + increment, member)
else
return redis.call("ZADD", key, increment, member)
end
π μ μ© λμ: μ¬λ¬ Redis λ Έλμμ λμ μ κ·Ό λ°©μ§
π μμ (Python Redis-pyμμ RedLock μ¬μ©)
from redis import Redis
from redis_lock import Lock
redis_client = Redis()
lock = Lock(redis_client, "leaderboard_lock")
if lock.acquire(blocking=True, timeout=5):
try:
redis_client.zincrby("leaderboard", 10, "Alice")
finally:
lock.release()
| μ λ΅ | μ€λͺ | μ μ© λμ | μ₯μ | λ¨μ |
|---|---|---|---|---|
| μ±κΈ μ€λ λ λͺ¨λΈ | κΈ°λ³Έμ μΌλ‘ λμ μ€ν λ°©μ§ | λ¨μΌ μΈμ€ν΄μ€ νκ²½ | κ°λ¨νκ³ μμ μ | νμ₯μ± μ ν |
| μμμ μ°μ° | ZADD, ZINCRBYλ μμμ μΌλ‘ μ€ν | κΈ°λ³Έ λ°μ΄ν° μΆκ°/μμ | λΉ λ¦ | μ νμ μΈ μ°μ° |
| WATCH + MULTI/EXEC | λκ΄μ λ½μ νμ©νμ¬ μΆ©λ λ°©μ§ | μΆ©λ κ°λ₯μ±μ΄ λμ λ°μ΄ν° μμ | λμμ± λ³΄μ₯ | μΆ©λ μ μ¬μλ νμ |
| Lua μ€ν¬λ¦½νΈ | 볡μ‘ν μ°μ°μ μμμ μΌλ‘ μ²λ¦¬ | 볡μ‘ν νΈλμμ | μμμ± λ³΄μ₯ | μ μ§λ³΄μ μ΄λ €μ |
| RedLock | λΆμ° νκ²½μμ λκΈ°ν 보μ₯ | Redis ν΄λ¬μ€ν° νκ²½ | κ°λ ₯ν λκΈ°ν | μ±λ₯ μ€λ²ν€λ |
WATCH + MULTI/EXECλ₯Ό μ¬μ©νμ¬ λκ΄μ λ½ μ μ© κ°λ₯. π Redisμ Sorted Set(ZSET)μ κΈ°λ³Έμ μΌλ‘ κ²½μ 쑰건μ λ°©μ§ν μ μμ§λ§, νμ₯μ±μ΄λ λ°μ΄ν° λκΈ°νκ° μ€μν κ²½μ° μμ μ λ΅μ μ μ ν μ‘°ν©ν΄μΌ νλ€!