88 lines
12 KiB
Markdown
88 lines
12 KiB
Markdown
---
|
|
title: "official-doc / Spring Data Redis — Scripting execution (RedisScript, ScriptExecutor, EVALSHA/NOSCRIPT fallback)"
|
|
source_type: official-doc
|
|
url: https://docs.spring.io/spring-data/redis/reference/redis/scripting.html
|
|
archive_url:
|
|
related_branches: [feature-redis-atomic-program-catalog-contract]
|
|
related_projects: [ca-skeleton]
|
|
tags: [official-doc, ca-skeleton, persistence, redis, spring-data]
|
|
created: 2026-07-28
|
|
---
|
|
|
|
# Spring Data Redis — Scripting execution (RedisScript, ScriptExecutor, EVALSHA/NOSCRIPT fallback)
|
|
|
|
> Layer: `raw/official-docs/` — Spring Data Redis 공식 reference ("Scripting" 페이지, 버전 4.1.0) 원문 발췌.
|
|
> ca-skeleton `feature-redis-atomic-program-catalog-contract` 의 "EVALSHA 우선 실행 + NOSCRIPT 재적재를 직접 구현할지, 프레임워크(Spring Data Redis) 기존 script executor 에 위임할지" 결정 근거.
|
|
|
|
## Parent / 활용 branch
|
|
|
|
| Branch | 이 자료가 정당화하는 결정 |
|
|
|---|---|
|
|
| [[raw/branch-notes/feature-redis-atomic-program-catalog-contract]] | EVALSHA 우선 실행 + NOSCRIPT 재적재를 직접 구현하지 않고 Spring Data Redis 의 기본 `ScriptExecutor` 에 위임하며, `RedisScript`/`DefaultRedisScript` 위에 typed facade 를 얹는 API 설계의 근거 |
|
|
|
|
## 출처
|
|
|
|
- 원본 URL: https://docs.spring.io/spring-data/redis/reference/redis/scripting.html
|
|
- 아카이브 URL: (미수집)
|
|
- 저자 / 조직: Spring (VMware/Broadcom) — Spring Data Redis 공식 reference
|
|
- 발행일: 명시된 발행일 없음(living reference doc). fetch 시점 페이지 메타데이터 기준 버전 `4.1.0` (`data-version="4.1.0"`, GitHub 소스 `spring-projects/spring-data-redis/blob/4.1.0/...`) — Spring Boot 4.0 세대와 정렬되는 최신판
|
|
- 마지막 확인일: 2026-07-28
|
|
|
|
## 왜 저장했는지
|
|
|
|
`feature-redis-atomic-program-catalog-contract` 는 다단계 read-decide-write 를 버전 있는 atomic Lua program 으로 제공해야 하고, EVALSHA 실행 + NOSCRIPT 시 안전 재적재가 그 핵심 메커니즘이다. Redis 자체 공식 문서(`raw/official-docs/redis-eval-scripting-atomicity.md`)는 "애플리케이션이 EVALSHA 를 호출하고 NOSCRIPT 시 SCRIPT LOAD 후 재시도해야 한다"는 프로토콜 수준 규약만 증명하고, 어떤 client 라이브러리가 이를 자동화하는지는 범위 밖이라고 명시한다. 본 자료는 그 공백을 메운다 — Spring Data Redis 의 기본 `ScriptExecutor` 가 이 EVALSHA→NOSCRIPT→EVAL 재시도를 실제로 자동 처리한다는 프레임워크 공식 근거이며, 따라서 branch 가 직접 구현할지 위임할지를 결정하는 데 직접 쓰인다.
|
|
|
|
## 핵심 인용
|
|
|
|
> [§Scripting] "Scripts can be run by calling the execute methods of RedisTemplate and ReactiveRedisTemplate. Both use a configurable ScriptExecutor (or ReactiveScriptExecutor) to run the provided script. By default, the ScriptExecutor (or ReactiveScriptExecutor) takes care of serializing the provided keys and arguments and deserializing the script result. This is done through the key and value serializers of the template. There is an additional overload that lets you pass custom serializers for the script arguments and the result."
|
|
|
|
> [§Scripting] "The default ScriptExecutor optimizes performance by retrieving the SHA1 of the script and attempting first to run evalsha, falling back to eval if the script is not yet present in the Redis script cache."
|
|
|
|
> [§Scripting] "The preceding code configures a RedisScript pointing to a file called checkandset.lua, which is expected to return a boolean value. The script resultType should be one of Long, Boolean, List, or a deserialized value type. It can also be null if the script returns a throw-away status (specifically, OK)."
|
|
|
|
> [§Scripting, tip admonition] "It is ideal to configure a single instance of DefaultRedisScript in your application context to avoid re-calculation of the script's SHA1 on every script run."
|
|
|
|
> [§Scripting, 코드 예시] "ScriptSource scriptSource = new ResourceScriptSource(new ClassPathResource("META-INF/scripts/checkandset.lua")); return RedisScript.of(scriptSource, Boolean.class);"
|
|
|
|
> [§Scripting, 코드 예시] "return redisOperations.execute(script, List.of("key"), expectedValue, newValue);"
|
|
|
|
## Claims Extracted
|
|
|
|
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|
|
|---|---|---|---|---|---|
|
|
| SDR-SCRIPT-C1 | Spring Data Redis 의 기본 `ScriptExecutor`(`RedisTemplate`/`ReactiveRedisTemplate.execute(...)` 경로)는 스크립트의 SHA1 을 조회해 먼저 `evalsha` 실행을 시도하고, 스크립트가 Redis 스크립트 캐시에 아직 없으면 `eval` 로 폴백한다 — 즉 EVALSHA 우선 + NOSCRIPT 시 재적재를 프레임워크가 자동 처리한다 | "The default ScriptExecutor optimizes performance by retrieving the SHA1 of the script and attempting first to run evalsha, falling back to eval if the script is not yet present in the Redis script cache." | `official-vendor-doc` | `RedisTemplate`/`ReactiveRedisTemplate.execute(RedisScript, keys, args...)` 경로의 기본 `ScriptExecutor`/`ReactiveScriptExecutor` 구현 | 어떤 예외/에러 타입으로 NOSCRIPT 를 감지하는지, fallback 후 서버 캐시에 재적재되는지, 커스텀 `ScriptExecutor` 구현체의 동작, cluster/샤딩 환경에서의 동작은 증명하지 않음 |
|
|
| SDR-SCRIPT-C2 | `RedisTemplate`/`ReactiveRedisTemplate` 는 `execute` 메서드를 통해 설정 가능한 `ScriptExecutor`/`ReactiveScriptExecutor` 에 실행을 위임하며, 기본적으로 이 executor 가 전달된 key/인자를 직렬화하고 스크립트 결과를 역직렬화한다(템플릿의 key/value serializer 사용), 커스텀 직렬화기를 넘기는 오버로드도 존재한다 | "Scripts can be run by calling the execute methods of RedisTemplate and ReactiveRedisTemplate. [...] There is an additional overload that lets you pass custom serializers for the script arguments and the result." | `official-vendor-doc` | typed facade 설계 시 `execute(script, keys, args...)` 시그니처와 직렬화 책임 분담 근거 | 정확한 Java 오버로드 전체 목록, `ScriptOutputType` 열거값과의 매핑 관계는 증명하지 않음(이 페이지에 `ScriptOutputType` 자체가 등장하지 않음) |
|
|
| SDR-SCRIPT-C3 | 예시 코드는 `execute` 가 `RedisScript`, `List<K>` 형태의 KEYS, 그리고 나머지 가변인자 형태의 ARGV 를 받는 형태임을 보여준다 | "return redisOperations.execute(script, List.of("key"), expectedValue, newValue);" | `official-vendor-doc` | keys/args 전달 방식(List + varargs) 설계 근거 | 이 예시 1건이 모든 오버로드(커스텀 직렬화 포함 포함)를 대표한다고 증명하지 않음 |
|
|
| SDR-SCRIPT-C4 | `RedisScript` 의 `resultType` 은 `Long`, `Boolean`, `List`, 또는 역직렬화된 값 타입 중 하나여야 하며, 스크립트가 `OK` 같은 throw-away 상태를 반환하면 `null` 도 허용된다 | "The script resultType should be one of Long, Boolean, List, or a deserialized value type. It can also be null if the script returns a throw-away status (specifically, OK)." | `official-vendor-doc` | golden vector / typed facade 반환 타입 계약 설계 | `ScriptOutputType` enum 자체의 존재나 값 목록, 역직렬화 실패 시 예외 타입은 이 페이지에서 확인되지 않음 |
|
|
| SDR-SCRIPT-C5 | `DefaultRedisScript` 는 애플리케이션 컨텍스트에 단일 인스턴스로 구성해 매 실행마다 스크립트 SHA1 을 재계산하지 않는 것이 권장(ideal)된다 | "It is ideal to configure a single instance of DefaultRedisScript in your application context to avoid re-calculation of the script's SHA1 on every script run." | `official-vendor-doc` | 카탈로그의 `ScriptDescriptor`/`RedisScript` bean 을 싱글턴으로 구성해야 하는 근거 | thread-safety 를 명시적으로 보장한다고는 말하지 않음(싱글턴 권장이 암묵적으로 시사할 뿐), 런타임 카탈로그 재적재/버저닝 전략은 다루지 않음 |
|
|
| SDR-SCRIPT-C6 | 스크립트 본문을 classpath resource 로 두고 `ResourceScriptSource(new ClassPathResource(...))` 를 통해 `RedisScript.of(scriptSource, Boolean.class)` 로 구성하는 것이 공식 예시의 표준 패턴이다 | "ScriptSource scriptSource = new ResourceScriptSource(new ClassPathResource(\"META-INF/scripts/checkandset.lua\")); return RedisScript.of(scriptSource, Boolean.class);" | `official-vendor-doc` | 프로그램 카탈로그의 `.lua` 파일을 classpath resource 로 두고 `ResourceScriptSource` 로 로드하는 설계의 공식 근거 | 이것이 유일하게 지원되는 `ScriptSource` 구현인지, 특정 classpath 경로(`META-INF/scripts/`)가 강제 규약인지는 증명하지 않음 — 예시 1건일 뿐 |
|
|
|
|
## Usage Boundaries
|
|
|
|
- **이 자료가 직접 증명하는 것**:
|
|
- `SDR-SCRIPT-C1`: Spring Data Redis 의 기본 `ScriptExecutor` 가 EVALSHA 우선 + NOSCRIPT 시 EVAL 폴백을 자동 처리 — branch 가 이 재적재 로직을 직접 구현할 필요가 없다는 결정의 직접 근거
|
|
- `SDR-SCRIPT-C2`, `C3`: `execute(script, keys, args...)` 시그니처와 직렬화 책임 분담 — typed facade 가 감쌀 API 표면
|
|
- `SDR-SCRIPT-C4`: `RedisScript` 반환 타입 제약 — golden vector 설계 시 참고
|
|
- `SDR-SCRIPT-C5`: `DefaultRedisScript` 싱글턴 구성 권장 — 카탈로그 bean 설계 근거
|
|
- `SDR-SCRIPT-C6`: `ResourceScriptSource` classpath resource 패턴 — 카탈로그 파일 배치 근거
|
|
- **이 자료가 증명하지 않는 것**:
|
|
- `ScriptOutputType`, `ScriptingException` 등 구체적 결과 타입 enum·예외 타입 — 이 페이지(`redis/scripting.html`)에는 **등장하지 않는다**(self-grep 으로 부재 확인, fabrication 아님). Javadoc(`org.springframework.data.redis.core.script` 패키지) 또는 별도 fetch 필요
|
|
- Redis Functions(FCALL) 배포 모드 지원 여부 — 이 페이지는 `eval`/`evalsha` 기반 `RedisScript` 경로만 다룬다
|
|
- Redis Cluster 환경에서 각 노드별 스크립트 캐시가 독립적으로 유실될 수 있는 문제와 Spring Data Redis 의 대응 방식
|
|
- fallback(`eval`) 실행 후 서버 스크립트 캐시에 실제로 재적재되어 이후 `evalsha` 가 다시 성공하는지의 명시적 서술(문맥상 당연히 그렇다고 추정되나 이 문장이 직접 말하지는 않음)
|
|
- **내 프로젝트(ca-skeleton)에 적용하려면 추가 확인이 필요한 것**:
|
|
- `ScriptOutputType`/`ScriptingException` 관련 Javadoc 확인 (typed facade 의 예외 처리 계층 설계에 필요)
|
|
- `DefaultRedisScript` 가 실제로 thread-safe 한지 Javadoc/소스 확인 (싱글턴 bean 으로 구성 시 동시성 안전성 전제)
|
|
- unsafe multi-command recipe ↔ atomic 대체 쌍의 실제 Lua 구현 detail 은 이 자료 범위 밖 — branch 자체 설계 결정
|
|
|
|
## 메모
|
|
|
|
- 이 페이지는 Redis 서버 프로토콜 수준의 EVALSHA/NOSCRIPT 규약(`raw/official-docs/redis-eval-scripting-atomicity.md`)이 남긴 공백 — "어떤 client 라이브러리가 EVALSHA→NOSCRIPT→재적재를 자동화하는가" — 을 Spring Data Redis 프레임워크 계층에서 메운다. 두 문서를 함께 인용하면 "프로토콜 규약 + 프레임워크 자동화" 근거 사슬이 완성된다.
|
|
- `ScriptOutputType`/`ScriptingException` 부재는 fabrication 방지를 위해 의도적으로 quote 하지 않았음 — 필요 시 별도 raw-source 로 Javadoc 페이지 수집 권장.
|
|
- fetch 시점 페이지 버전은 `4.1.0`(Spring Boot 4.0 세대). 향후 버전업 시 재확인 필요.
|
|
|
|
## Related
|
|
|
|
- 같은 주제 다른 official-doc: [[raw/official-docs/redis-eval-scripting-atomicity]] — Redis 서버 자체의 EVALSHA/NOSCRIPT/KEYS 선언 규약 (프로토콜 수준, 본 문서는 프레임워크 수준)
|
|
- 이 자료를 인용한 wiki 요약: `[[wiki/concepts/...]]` (생성 시)
|