--- title: Caffeine — AsyncLoadingCache & cache stampede prevention (GitHub Wiki — Population) source_type: official-doc url: https://github.com/ben-manes/caffeine/wiki/Population archive_url: status: raw confidence: high tags: [ca-cache-consistency, caffeine, local-cache, stampede, single-instance, official-doc] related_branches: [feature-cache-consistency-contract] related_projects: [ca-skeleton] created: 2026-05-22 last_reviewed: 2026-05-27 --- # Caffeine — AsyncLoadingCache & cache stampede prevention > Layer: `raw/official-docs/` — Caffeine GitHub Wiki "Population" 페이지 (verbatim 발췌) + 관련 보조 인용 (`Refresh`, Spring `@Cacheable` Javadoc). ## Parent / 활용 branch (필수) | Branch | 이 자료가 정당화하는 결정 | |---|---| | [[raw/branch-notes/feature-cache-consistency-contract]] | ca-tmpl single-instance stampede 방지에 Caffeine `LoadingCache` / `AsyncLoadingCache` 또는 Spring `@Cacheable(sync=true)` 채택 근거 | ## 컨텍스트 / 왜 저장했는지 ca-tmpl single-instance stampede 방지 결정 **"Caffeine local lock"** 의 근거. `LoadingCache` / `AsyncLoadingCache` 의 stampede 방지 메커니즘과 Spring `@Cacheable sync=true` 와의 관계를 명시. ## 출처 / Source - 원본 URL (Wiki "Population" 페이지): https://github.com/ben-manes/caffeine/wiki/Population - 보조 페이지: Caffeine Wiki — "Refresh", "Specification" - 보조 자료: Spring Framework `@Cacheable` Javadoc (`sync` attribute) - 저자 / 조직: Ben Manes (Caffeine 저자) / Caffeine project - 발행일: 지속 갱신 (GitHub Wiki) - 마지막 확인일: 2026-05-27 ## 핵심 인용 / Key quotes (verbatim) **Caffeine Wiki "Population" — 2026-05-27 fetch 로 확인된 인용**: > [§LoadingCache] "A `LoadingCache` is a `Cache` built with an attached `CacheLoader`." > [§AsyncLoadingCache] "A `AsyncLoadingCache` is a `AsyncCache` built with an attached `AsyncCacheLoader`." > [§Asynchronous Computation] "A `AsyncCache` is a `Cache` variant that computes entries on an `Executor` and returns a `CompletableFuture`." > [§CacheLoader Options] "A `CacheLoader` should be supplied when the computation is best expressed in a synchronous fashion." / "Alternatively, a `AsyncCacheLoader` should be supplied when the computation is expressed asynchronously and returns a `CompletableFuture`." > [§Bulk Operations] "By default, `getAll` will issue a separate call to `CacheLoader.load` for each key which is absent from the cache." **보조 인용 (별도 페이지 — 본 fetch 로는 verbatim 미확인, 원래 raw 작성 시점 수집본 보존)**: > [Caffeine Wiki "Refresh" — needs-confirmation] "`refreshAfterWrite` reloads asynchronously, returning the old value during reload. Combined with `AsyncLoadingCache`, refresh does not block readers." *(2026-05-27 Wiki Population fetch 에서는 verbatim 미확인 — Refresh 별도 페이지 재확인 필요)* > [Spring Framework `@Cacheable` Javadoc — `sync` attribute] "`sync=true` instructs the cache abstraction to synchronize the invocation of the underlying method, if several threads are attempting to load a value for the same key. Only one invocation is performed; others wait." *(별도 출처 — Caffeine wiki 가 아님)* ## Claims Extracted / 추출된 주장 > 본 raw 의 1차 출처는 Caffeine Wiki "Population". `CAFFEINE-POP-C*` prefix. | Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove | |---|---|---|---|---|---| | CAFFEINE-POP-C1 | `LoadingCache` = `CacheLoader` 가 attach 된 `Cache` 변형 | [§LoadingCache] "A `LoadingCache` is a `Cache` built with an attached `CacheLoader`." | `official-vendor-doc` | Caffeine 2.x/3.x `LoadingCache` API 사용 | "동일 key 동시 miss 시 single load 직렬화" 메커니즘 자체는 본 인용으로 직접 증명 안 됨 — 별도 Caffeine 동작 명세 또는 `CacheLoader.load` 계약 확인 필요 | | CAFFEINE-POP-C2 | `AsyncLoadingCache` = `AsyncCacheLoader` 가 attach 된 `AsyncCache` 변형 | [§AsyncLoadingCache] "A `AsyncLoadingCache` is a `AsyncCache` built with an attached `AsyncCacheLoader`." | `official-vendor-doc` | Caffeine async API 사용 | in-flight `CompletableFuture` 가 같은 key 동시 요청에 공유되는지 / 실패 future 의 자동 제거 여부는 본 인용 범위 밖 | | CAFFEINE-POP-C3 | `AsyncCache` 는 `Executor` 위에서 entry 를 계산하고 `CompletableFuture` 를 반환 | [§Asynchronous Computation] "A `AsyncCache` is a `Cache` variant that computes entries on an `Executor` and returns a `CompletableFuture`." | `official-vendor-doc` | Caffeine `AsyncCache.get(key, loader)` 호출 | Executor 의 기본 구현 (ForkJoinPool 등) 은 본 인용으로 명시 안 됨 — Caffeine `Specification` 페이지 별도 확인 | | CAFFEINE-POP-C4 | 계산이 동기적이면 `CacheLoader`, 비동기적이고 `CompletableFuture` 반환이면 `AsyncCacheLoader` 사용 | [§CacheLoader Options] "A `CacheLoader` should be supplied when the computation is best expressed in a synchronous fashion." / "Alternatively, a `AsyncCacheLoader` should be supplied when the computation is expressed asynchronously and returns a `CompletableFuture`." | `official-vendor-doc` | loader 선택 결정 | "어느 쪽이 stampede 방지 측면에서 더 강력한지" 는 본 인용 범위 밖 | | CAFFEINE-POP-C5 | `getAll` 의 기본 동작은 cache 에 없는 각 key 에 대해 `CacheLoader.load` 를 개별 호출 | [§Bulk Operations] "By default, `getAll` will issue a separate call to `CacheLoader.load` for each key which is absent from the cache." | `official-vendor-doc` | Caffeine `Cache.getAll(keys)` 호출 | bulk load 최적화 (예: `loadAll` override) 의 효과는 본 인용으로 직접 증명 안 됨 | | CAFFEINE-POP-C6 | `refreshAfterWrite` 는 비동기 reload, 진행 중 old value 반환. `AsyncLoadingCache` 와 결합 시 reader 를 block 하지 않음 | [Wiki "Refresh"] "`refreshAfterWrite` reloads asynchronously, returning the old value during reload. Combined with `AsyncLoadingCache`, refresh does not block readers." | `needs-confirmation` *(원 raw 수집본; 2026-05-27 Population 페이지 fetch 에서는 verbatim 미발견 — Refresh 별도 페이지 재fetch 필요)* | Caffeine refresh 모드 | reload 실패 시 old value 의 유효 기간은 본 인용 범위 밖 | | SPRING-CACHEABLE-C1 | Spring `@Cacheable(sync=true)` 는 같은 key 에 대해 여러 thread 가 동시에 load 시도할 때 underlying method 호출을 1회로 동기화. 나머지는 대기 | [Spring `@Cacheable` Javadoc — `sync` attribute] "`sync=true` instructs the cache abstraction to synchronize the invocation of the underlying method, if several threads are attempting to load a value for the same key. Only one invocation is performed; others wait." | `official-vendor-doc` *(Spring Framework reference Javadoc; Caffeine wiki 아님)* | Spring Cache abstraction 사용 + Caffeine backend | 이 동기화가 Caffeine 내부 lock 으로 위임되는지 vs Spring 자체 lock 인지는 본 인용으로 직접 증명 안 됨 — Spring `CaffeineCache` 구현 확인 필요 | ### Strength 적용 메모 - `official-vendor-doc`: Caffeine GitHub Wiki 는 저자 (Ben Manes) 가 직접 유지하는 공식 문서. official-standard (RFC) 가 아니므로 한 단계 아래. - `needs-confirmation`: 본 fetch 에서 verbatim 으로 확인 불가능한 인용. 원 raw 작성 시점 수집본을 보존하되 별도 fetch 로 재확인 필요. ## Usage Boundaries / 적용 경계 - **이 자료가 직접 증명하는 것**: - `CAFFEINE-POP-C1~C5`: Caffeine `LoadingCache`/`AsyncLoadingCache` 의 API 형태 + `getAll` 기본 동작 - `SPRING-CACHEABLE-C1`: Spring `@Cacheable(sync=true)` 의 동기화 의미 (Spring Javadoc 기준) - **이 자료가 증명하지 않는 것**: - **Caffeine `LoadingCache` 가 동일 key 동시 miss 시 backend 호출을 정확히 1회로 직렬화한다는 보장**: 본 Population 페이지 fetch 에서 verbatim 인용 미확보. ca-tmpl `Required test` 검증 시 별도 동작 테스트 + Caffeine source 코드 (`BoundedLocalCache#doComputeIfAbsent`) 확인 필요 - in-flight `CompletableFuture` 공유 / 실패 future 자동 제거 메커니즘: 본 fetch 범위 밖 - Spring `@Cacheable(sync=true)` 가 Caffeine backend 와 결합 시 어느 layer 에서 lock 이 걸리는지 (Spring 자체 lock vs Caffeine 내부): 별도 검증 필요 - **내 프로젝트에 적용하려면 추가 확인이 필요한 것**: - ca-tmpl `Required test` ("동일 key 동시 cache miss → backend 호출 1회") 의 actual 검증 - multi-instance 환경에서 본 메커니즘이 적용 안 되는 점 (instance 별 별도 load) — Redisson RLock 등 분산 잠금으로 승격 필요한 분기 ## 메모 / Notes (내 프로젝트 해석 — PRESERVED) > 본 섹션은 자료 직접 인용 아님. ca-tmpl 결정 컨텍스트 해석. 원 raw 의 해석을 보존하되 verifiability gap 을 명시. - single-instance stampede 방지 mechanism: - **Caffeine `LoadingCache` 자체가 같은 key 에 대한 동시 load 를 1회로 직렬화 (널리 알려진 동작이나, 본 Population 페이지 fetch 만으로는 verbatim 증거 없음 — `needs-confirmation`)**. 외부 lock 불필요. - Spring abstraction 을 쓸 때는 `@Cacheable(sync=true)` 로 동등 효과. 내부적으로 Caffeine `get(key, loader)` 가 호출됨 (Spring `CaffeineCache` 구현 가정 — 본 raw 자료로 직접 증명 안 됨). - ca-tmpl `Required test` 와의 정합성: - "동일 key 에 대해 동시 cache miss 시 backend 호출 1회로 제한" 검증 → Caffeine `LoadingCache` 또는 `@Cacheable(sync=true)` 둘 다 통과 가정. - test 에서 명시한 (a) `sync=true` 또는 (b) `AsyncLoadingCache` 또는 (c) Redisson RLock wrap 분기 중 **(a)(b) 가 Caffeine 분기**, (c) 가 multi-instance 분기. - 장점: - in-process, network round-trip 없음 → 1µs급 hit latency. - Window TinyLFU eviction policy 로 LRU 보다 hit-rate 우수 (Caffeine 논문 인용 영역 — 본 wiki 페이지 직접 증명 아님). - 단점 (ca-tmpl 입장): - **multi-instance** 에서는 의미 없음 — instance 별로 별도 load 가 일어남. HPA 환경에서는 RLock 으로 승격 필요. - JVM restart 시 cache cold start. 안 가져갈 hot key 가 cold path 를 거치면 backend burst. - 시사점: ca-tmpl 의 "single-instance Caffeine, multi-instance Redisson" 분기는 **scope 에 맞춘 도구 차등화**. write-back/distributed mode 를 Caffeine 에 요구하지 않음 (out of scope). ## Related / 관련 - 같은 주제 다른 raw: - (Caffeine `Refresh` / `Specification` 별도 페이지 — 미작성) - 인용하는 branch: - [[raw/branch-notes/feature-cache-consistency-contract]] - 적용 contract: - [[raw/project-notes/ca-skeleton-operational-contract]] (Cache consistency 그룹) - 인용하는 wiki: (미작성)