Files
llm-wiki/raw/official-docs/redis-incr-rate-limiter-pattern.md

9.4 KiB
Raw Permalink Blame History

title, source_type, url, archive_url, related_branches, related_projects, tags, created, last_reviewed, status, confidence, vendor, author, published
title source_type url archive_url related_branches related_projects tags created last_reviewed status confidence vendor author published
official-doc / Redis INCR — Atomicity & Rate Limiter Pattern Race Condition official-doc https://redis.io/docs/latest/commands/incr/
feature-redis-atomic-program-catalog-contract
ca-skeleton
official-doc
ca-skeleton
caching
redis
rate-limit
2026-07-28 2026-07-28 raw high Redis Redis (official docs)

Redis INCR — Atomicity & Rate Limiter Pattern Race Condition

Layer: raw/official-docs/ — Redis 공식 커맨드 레퍼런스(INCR) 원문 발췌·출처 기록. 검증된 요약은 /ingestwiki/concepts/source-summary-template 형식으로 별도 작성. 원본은 raw에 영구 보관.

Parent / 활용 branch

Branch 이 자료가 정당화하는 결정
raw/branch-notes/feature-redis-atomic-program-catalog-contract 각 atomic program helper 는 흔한 unsafe multi-command recipe 와 그 안전한 atomic 대체를 쌍으로 문서화한다 — 대표 사례 GET → 판단 → INCR → EXPIRE 의 race condition 을 공식 문서가 명시적으로 서술한다는 근거

출처 / Source

  • 원본 URL: https://redis.io/docs/latest/commands/incr/
  • 아카이브 URL: (미제공)
  • 저자 / 조직: Redis (공식 커맨드 레퍼런스)
  • 발행일: (페이지에 명시 없음 — since: 1.0.0 커맨드 메타데이터만 존재)
  • 마지막 확인일: 2026-07-28

왜 저장했는지 / Why archived

feature-redis-atomic-program-catalog-contract branch 는 "다단계 read-decide-write recipe 는 항상 unsafe 버전과 atomic 대체를 쌍으로 문서화한다"는 프로젝트 결정(DEC-CA-SKELETON-OPERATIONAL-CONTRACT-REDIS-PROGRAM-001)을 구현해야 한다. Redis 공식 INCR 문서의 "Pattern: rate limiter" 절이 바로 이 다단계 recipe (GET → 판단 → INCR → 조건부 EXPIRE)의 race condition 을 공식적으로 서술하고, MULTI/EXEC 및 Lua(EVAL) 대체를 명시적으로 권고하므로 1차 근거로 확보한다.

핵심 인용 / Key quotes (verbatim)

[§Details > Pattern: counter] "The counter pattern is the most obvious thing you can do with Redis atomic increment operations." (lines 508509 in fetched text)

[§Details > Pattern: rate limiter > Pattern: rate limiter 1] "Note the used of MULTI and EXEC in order to make sure that we'll both increment and set the expire at every API call." (lines 565566 in fetched text)

[§Details > Pattern: rate limiter > Pattern: rate limiter 2] "In the above code there is a race condition." (line 593 in fetched text)

[§Details > Pattern: rate limiter > Pattern: rate limiter 2] "If for some reason the client performs the INCR command but does not perform the EXPIRE the key will be leaked until we'll see the same IP address again." (lines 594595 in fetched text)

[§Details > Pattern: rate limiter > Pattern: rate limiter 2] "This can be easily fixed by turning the INCR with optional EXPIRE into a Lua script that is then sent using the EVAL command (only available since Redis version 2.6)." (lines 597599 in fetched text)

Claims Extracted / 추출된 주장

Claim ID Claim (이 자료가 직접 말하는 것) Evidence quote Strength Applies to Does not prove
REDIS-INCR-C1 INCR 은 "atomic increment operation" 으로 서술된다 — 단일 INCR 호출 자체는 원자적이다 [§Pattern: counter] "The counter pattern is the most obvious thing you can do with Redis atomic increment operations." official-vendor-doc 단일 INCR 커맨드 호출 자체의 원자성 (per-command atomicity) 여러 명령(GET→판단→INCREXPIRE)을 조합한 시퀀스 전체 가 원자적이라는 것 — 오히려 본 문서가 뒤에서 이를 반박(REDIS-INCR-C2)
REDIS-INCR-C2 "GET 으로 현재값 확인 → 조건부 INCR → 첫 증가 시에만 EXPIRE" 형태의 rate limiter 구현("Pattern: rate limiter 2")에 대해 공식 문서가 명시적으로 race condition 존재를 선언한다 [§Pattern: rate limiter 2] "In the above code there is a race condition." official-vendor-doc GET/INCR/조건부 EXPIRE 다단계 recipe 에 race 가 실재한다는 사실 자체 다른 언어·클라이언트 구현에서도 항상 동일 race 가 발생한다는 일반화 — 문서는 이 특정 pseudocode 예시에 대해서만 명시함
REDIS-INCR-C3 위 race 의 구체적 실패 모드는 "클라이언트가 INCR 은 수행했지만 EXPIRE 를 수행하지 못한 경우" 이며, 이 경우 같은 IP 를 다시 볼 때까지 key 가 TTL 없이 leak 된다 [§Pattern: rate limiter 2] "If for some reason the client performs the INCR command but does not perform the EXPIRE the key will be leaked until we'll see the same IP address again." official-vendor-doc INCR 성공 후 EXPIRE 미실행(크래시·네트워크 단절 등) 시 key 누수 시나리오 이 leak 이 rate-limit 판정 정확성 자체를 깨뜨린다는 것 — 문서는 메모리/키 누수로 서술하지, 카운트 오판으로 서술하지 않음
REDIS-INCR-C4 공식 문서는 두 가지 다른 recipe 에 두 가지 다른 대체를 권고한다 — (a) 고정 타임스탬프 키 카운터("rate limiter 1")에는 INCR+EXPIREMULTI/EXEC 로 묶을 것을, (b) 조건부 분기가 있는 단일 카운터("rate limiter 2")에는 INCR+조건부 EXPIRE 를 Lua 스크립트로 옮겨 EVAL 로 실행할 것을 권고한다 [§rate limiter 1] "Note the used of MULTI and EXEC in order to make sure that we'll both increment and set the expire at every API call." + [§rate limiter 2] "This can be easily fixed by turning the INCR with optional EXPIRE into a Lua script that is then sent using the EVAL command (only available since Redis version 2.6)." official-vendor-doc 두 recipe 각각에 맞는 공식 대체 메커니즘 선택 근거 MULTI/EXEC 가 "rate limiter 2" 처럼 읽은 값을 기준으로 분기(IF value == 1 THEN EXPIRE)하는 recipe 의 race 도 없앤다는 것 — 문서는 그 recipe 의 fix 로 MULTI/EXEC 가 아니라 Lua 를 명시적으로 별도 제시함 (조건부 분기 recipe 와 무분기 recipe 는 다른 처방)

Usage Boundaries / 적용 경계

  • 이 자료가 직접 증명하는 것:
    • REDIS-INCR-C1: INCR 단일 커맨드 자체가 원자적이라는 공식 서술
    • REDIS-INCR-C2: GET→판단→INCR→조건부 EXPIRE recipe 에 공식 문서가 인정하는 race condition 이 존재한다는 사실
    • REDIS-INCR-C3: 그 race 의 구체적 실패 모드(EXPIRE 유실 시 key leak)
    • REDIS-INCR-C4: recipe 종류에 따라 공식이 권고하는 두 가지 다른 대체 메커니즘(MULTI/EXEC vs Lua/EVAL)
  • 이 자료가 증명하지 않는 것:
    • MULTI/EXEC 가 조건부 분기(읽은 값에 따라 다음 커맨드를 결정)가 있는 recipe 의 race 도 없앤다는 것 — 문서는 이 경우 Lua 를 명시적으로 제시
    • EVAL/Lua 스크립트가 모든 Redis 배포 모드(clustered, Redis Functions 등)에서 동일하게 동작한다는 것 — 버전 제약("only available since Redis version 2.6")만 명시
    • key leak 이 실제 운영 환경에서 관측 가능한 심각도(메모리 규모·발생 빈도)를 가진다는 것 — 문서는 정성적 서술만 제공, 정량적 근거 없음
    • ca-tmpl/ca-skeleton 의 ScriptDescriptor/EVALSHA/NOSCRIPT 재적재 같은 구체적 구현 메커니즘 — 이는 본 branch 의 로컬 결정 사항이지 이 공식 문서의 주장이 아님
  • 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
    • feature-redis-atomic-program-catalog-contract 의 unsafe recipe 카탈로그에 이 GETINCR→조건부 EXPIRE 패턴을 등재할 때, 대응 atomic 대체를 Lua 스크립트(EVALSHA)로 명시하고 MULTI/EXEC 로 오인하지 않도록 §구현 가이드에서 구분해야 함
    • 경합 재현 test 시나리오는 REDIS-INCR-C2/C3 의 실패 모드(첫 INCR 성공 후 EXPIRE 실패)를 인위적으로 유발할 수 있는 fault-injection 지점 확인 필요

메모 / Notes

  • 본 문서의 "Pattern: rate limiter" 절은 rate limiter 1(고정 타임스탬프 키, 분기 없음 → MULTI/EXEC 로 충분)과 rate limiter 2(단일 카운터, IF value == 1 분기 있음 → MULTI/EXEC 로 불충분, Lua 필요)를 구분해서 서술한다. branch 의 unsafe-recipe 카탈로그를 작성할 때 이 두 변형을 하나의 "INCR+EXPIRE" 항목으로 뭉뚱그리면 REDIS-INCR-C4 의 구분을 잃는다 — 별개 카탈로그 항목으로 분리 권장.
  • 문서는 "Pattern: rate limiter 2" 의 세 번째 대안으로 Redis list(RPUSH/RPUSHX/LLEN) 기반 구현도 제시하며, 여기에도 EXISTS 확인과 MULTI/EXEC 사이의 race 가 있지만 "rare conditions 에서 API call 하나를 놓치는 정도"로 무해하다고 서술한다 — 이는 이번 branch 의 핵심 인용 범위(GET→INCR→EXPIRE) 밖이라 인용에는 포함하지 않았으나, "모든 race 가 치명적인 것은 아니다"라는 대비 사례로 §메모에만 남긴다(검증 안 된 해석이므로 claim 화하지 않음).