97 lines
16 KiB
Markdown
97 lines
16 KiB
Markdown
---
|
|
title: "official-doc / Redis — Scripting with Lua (atomicity, script cache/EVALSHA/NOSCRIPT, KEYS/ARGV, SCRIPT KILL)"
|
|
source_type: official-doc
|
|
url: https://redis.io/docs/latest/develop/programmability/eval-intro/
|
|
archive_url:
|
|
related_branches: [feature-redis-atomic-program-catalog-contract]
|
|
related_projects: [ca-skeleton]
|
|
tags: [official-doc, ca-skeleton, persistence, redis]
|
|
created: 2026-07-28
|
|
---
|
|
|
|
# Redis — Scripting with Lua (atomicity, script cache/EVALSHA/NOSCRIPT, KEYS/ARGV, SCRIPT KILL)
|
|
|
|
> Layer: `raw/official-docs/` — Redis 공식 reference ("Scripting with Lua" / eval-intro) 원문 발췌.
|
|
> ca-skeleton `feature-redis-atomic-program-catalog-contract` 의 "다단계 read-decide-write 는 EVALSHA 기반 버전 있는 atomic program 으로만 제공" 결정 근거.
|
|
|
|
## Parent / 활용 branch
|
|
|
|
| Branch | 이 자료가 정당화하는 결정 |
|
|
|---|---|
|
|
| [[raw/branch-notes/feature-redis-atomic-program-catalog-contract]] | 다단계 read-decide-write 는 EVALSHA 로 실행하는 버전 있는 atomic program 으로만 제공하고, NOSCRIPT 시 안전 재적재하며, bounded execution(유한 실행) 규칙을 둔다 |
|
|
|
|
## 출처
|
|
|
|
- 원본 URL: https://redis.io/docs/latest/develop/programmability/eval-intro/
|
|
- 아카이브 URL: (미수집)
|
|
- 저자 / 조직: Redis (Redis Ltd. 공식 문서)
|
|
- 발행일: Redis 공식 reference, 최신 버전 anchor (7.0 관련 변경 다수 명시 — verbatim 인용 참조)
|
|
- 마지막 확인일: 2026-07-28
|
|
|
|
## 왜 저장했는지
|
|
|
|
Redis Lua 스크립트가 **원자적으로 실행**되고(다른 클라이언트 명령과 인터리빙되지 않음), 스크립트 캐시(SHA1)가 **휘발성**이라 `NOSCRIPT` 발생 시 재적재가 필요하며, 접근하는 key 는 반드시 `KEYS` 인자로 선언해야 한다는 공식 근거를 보존한다. `feature-redis-atomic-program-catalog-contract` 의 EVALSHA + 안전 재적재 + KEYS 선언 규칙 결정을 직접 뒷받침한다.
|
|
|
|
## 핵심 인용
|
|
|
|
> [§(intro, "Getting started" 이전)] "Redis guarantees the script's atomic execution. While executing the script, all server activities are blocked during its entire runtime. These semantics mean that all of the script's effects either have yet to happen or had already happened."
|
|
> (한글 요약: Redis 는 스크립트의 원자적 실행을 보장한다. 스크립트 실행 중에는 모든 서버 활동이 전체 실행 시간 동안 블로킹된다. 즉 스크립트의 효과는 "아직 발생 안 함" 아니면 "이미 발생함" 둘 중 하나다.)
|
|
|
|
> [§Getting started] "to ensure the correct execution of scripts, both in standalone and clustered deployments, all names of keys that a script accesses must be explicitly provided as input key arguments. The script should only access keys whose names are given as input arguments. Scripts should never access keys with programmatically-generated names or based on the contents of data structures stored in the database."
|
|
> (한글 요약: standalone/clustered 배포 모두에서 스크립트의 정확한 실행을 보장하려면, 스크립트가 접근하는 모든 key 이름은 반드시 입력 key 인자로 명시적으로 제공해야 한다. 스크립트는 입력 인자로 주어진 이름의 key 만 접근해야 하며, 프로그램적으로 생성된 이름이나 DB 저장 데이터 구조의 내용에 기반한 key 는 절대 접근해서는 안 된다.)
|
|
|
|
> [§Script cache → Cache volatility] "The Redis script cache is always volatile. It isn't considered as a part of the database and is not persisted. The cache may be cleared when the server restarts, during fail-over when a replica assumes the master role, or explicitly by SCRIPT FLUSH."
|
|
> (한글 요약: Redis 스크립트 캐시는 항상 휘발성이다. DB 의 일부로 취급되지 않으며 영속화되지 않는다. 서버 재시작, failover 시 replica 의 master 승격, 또는 명시적 SCRIPT FLUSH 호출 시 캐시가 지워질 수 있다.)
|
|
|
|
> [§Script cache → Cache volatility] "Applications that use scripts should always call EVALSHA to execute them. The server returns an error if the script's SHA1 digest is not in the cache." ... "(error) NOSCRIPT No matching script" ... "In this case, the application should first load it with SCRIPT LOAD and then call EVALSHA once more to run the cached script by its SHA1 sum."
|
|
> (한글 요약: 스크립트를 사용하는 애플리케이션은 항상 EVALSHA 로 실행해야 한다. SHA1 다이제스트가 캐시에 없으면 서버는 에러를 반환한다(`NOSCRIPT No matching script`). 이 경우 애플리케이션은 먼저 SCRIPT LOAD 로 적재한 뒤 SHA1 로 EVALSHA 를 다시 호출해야 한다.)
|
|
|
|
> [§Script cache → EVALSHA in the context of pipelining] "The commands in a pipelined request run in the order they are sent, but other clients' commands may be interleaved for execution between these. Because of that, the NOSCRIPT error can return from a pipelined request but can't be handled. Therefore, a client library's implementation should revert to using plain EVAL of parameterized in the context of a pipeline."
|
|
> (한글 요약: 파이프라인 요청 내 명령은 보낸 순서대로 실행되지만 다른 클라이언트의 명령이 그 사이에 인터리빙될 수 있다. 이 때문에 파이프라인에서 발생한 NOSCRIPT 에러는 처리(handle)될 수 없다. 따라서 클라이언트 라이브러리 구현은 파이프라인 맥락에서는 파라미터화된 일반 EVAL 로 되돌아가야 한다.)
|
|
|
|
> [§The SCRIPT command] "SCRIPT KILL: this command is the only way to interrupt a long-running script (a.k.a slow script), short of shutting down the server. A script is deemed as slow once its execution's duration exceeds the configured maximum execution time threshold. The SCRIPT KILL command can be used only with scripts that did not modify the dataset during their execution (since stopping a read-only script does not violate the scripting engine's guaranteed atomicity)."
|
|
> (한글 요약: SCRIPT KILL 은 서버를 종료하지 않고 장시간 실행 중인(slow) 스크립트를 중단시키는 유일한 방법이다. 스크립트는 설정된 최대 실행 시간 임계값을 초과하면 slow 로 간주된다. SCRIPT KILL 은 실행 중 dataset 을 수정하지 않은 스크립트에만 사용 가능하다 — read-only 스크립트를 중단하는 것은 스크립팅 엔진이 보장하는 원자성을 위반하지 않기 때문이다.)
|
|
|
|
> [§Script replication] "Effects replication: only the script's data-modifying commands are replicated. Replicas then run the commands without executing any scripts. While potentially lengthier in terms of network traffic, this replication mode is deterministic by definition and therefore doesn't require special consideration." ... "In Redis 5.0, effects replication became the default mode. As of Redis 7.0, verbatim replication is no longer supported."
|
|
> (한글 요약: Effects replication 은 스크립트의 데이터 변경 명령만 복제한다. Replica 는 스크립트를 실행하지 않고 그 명령만 실행한다. 네트워크 트래픽 면에서 더 길어질 수 있으나, 이 복제 모드는 정의상 결정론적이라 별도 조치가 필요 없다. Redis 5.0 부터 effects replication 이 기본값이 되었고, Redis 7.0 부터는 verbatim replication 이 더 이상 지원되지 않는다.)
|
|
|
|
## Claims Extracted / 추출된 주장
|
|
|
|
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|
|
|---|---|---|---|---|---|
|
|
| REDIS-EVAL-C1 | Redis 는 스크립트의 원자적 실행을 보장하며, 실행 중 모든 서버 활동이 블로킹되어 스크립트 효과는 "아직 발생 안 함" 또는 "이미 발생함" 둘 중 하나만 관측된다 | "Redis guarantees the script's atomic execution. While executing the script, all server activities are blocked during its entire runtime." | `official-vendor-doc` | 모든 EVAL/EVALSHA 스크립트 실행 (standalone) | 이 페이지는 스크립트 원자성을 MULTI/EXEC 트랜잭션과 명시적으로 대조·비교하는 서술을 포함하지 않는다 — 두 메커니즘의 이동성/차이는 본 인용 범위 밖 |
|
|
| REDIS-EVAL-C2 | 스크립트 캐시는 항상 휘발성이며 DB 의 일부로 영속화되지 않는다 — 서버 재시작, failover, 명시적 SCRIPT FLUSH 시 지워질 수 있다 | "The Redis script cache is always volatile. ... The cache may be cleared when the server restarts, during fail-over when a replica assumes the master role, or explicitly by SCRIPT FLUSH." | `official-vendor-doc` | 모든 Redis 배포(standalone/replica/cluster)의 스크립트 캐시 | 클러스터 각 노드별 캐시 상태가 서로 독립적으로 유실될 수 있는지의 세부 동작까지는 명시하지 않음 |
|
|
| REDIS-EVAL-C3 | 애플리케이션은 항상 EVALSHA 로 실행해야 하며, SHA1 다이제스트가 캐시에 없으면 서버는 `NOSCRIPT` 에러를 반환한다. 이 경우 클라이언트는 SCRIPT LOAD 로 재적재 후 EVALSHA 를 재시도해야 한다 | "Applications that use scripts should always call EVALSHA to execute them. The server returns an error if the script's SHA1 digest is not in the cache." / "(error) NOSCRIPT No matching script" / "the application should first load it with SCRIPT LOAD and then call EVALSHA once more" | `official-vendor-doc` | EVALSHA 실행 경로 + NOSCRIPT 복구 절차 일반 | 구체적인 client 라이브러리(예: Lettuce/Jedis)가 이 재적재를 자동화하는지는 "대부분의 클라이언트가 유틸리티 API 를 제공한다"고만 언급 — 특정 라이브러리 API 는 본 인용 범위 밖 |
|
|
| REDIS-EVAL-C4 | 파이프라인 컨텍스트에서는 다른 클라이언트 명령이 인터리빙될 수 있어 `NOSCRIPT` 에러가 발생해도 처리(handle)할 수 없으므로, 클라이언트 라이브러리는 파이프라인 안에서는 파라미터화된 일반 EVAL 로 되돌아가야(fallback) 한다 | "the NOSCRIPT error can return from a pipelined request but can't be handled. Therefore, a client library's implementation should revert to using plain EVAL of parameterized in the context of a pipeline." | `official-vendor-doc` | pipelined EVALSHA 실행 시나리오 | 이것이 client 라이브러리의 필수 구현 요건인지 권고인지의 구속력(should = 권고) 강도까지만 확인됨 — RFC 수준 MUST 아님 |
|
|
| REDIS-EVAL-C5 | standalone/clustered 배포 모두에서 정확한 스크립트 실행을 보장하려면, 스크립트가 접근하는 모든 key 이름은 `KEYS` 입력 인자로 명시적으로 제공되어야 하며, 프로그램적으로 생성되거나 DB 데이터 구조 내용에 기반한 key 는 절대 접근해서는 안 된다 | "all names of keys that a script accesses must be explicitly provided as input key arguments. The script should only access keys whose names are given as input arguments. Scripts should never access keys with programmatically-generated names or based on the contents of data structures stored in the database." | `official-vendor-doc` | 모든 EVAL/EVALSHA 스크립트의 key 접근 설계 (cluster 포함) | 미선언 key 를 실제로 접근했을 때의 구체적 에러 코드/거부 동작, 그리고 cluster hash-slot 라우팅 알고리즘 자체는 이 페이지에 명시되지 않음 |
|
|
| REDIS-EVAL-C6 | `SCRIPT KILL` 은 서버 종료 없이 장시간 실행 스크립트를 중단하는 유일한 방법이며, 설정된 최대 실행 시간 임계값 초과 시 slow 로 간주되고, dataset 을 수정하지 않은 스크립트에만 사용 가능하다(원자성 보장 위반 방지) | "SCRIPT KILL: this command is the only way to interrupt a long-running script ... A script is deemed as slow once its execution's duration exceeds the configured maximum execution time threshold. The SCRIPT KILL command can be used only with scripts that did not modify the dataset during their execution ..." | `official-vendor-doc` | 장시간 실행(slow) 스크립트의 중단 절차 일반 | `busy-reply-threshold`(구 `lua-time-limit`) 설정 이름, `BUSY` 에러 문자열, 쓰기를 수행한 스크립트에 대한 `SHUTDOWN NOSAVE` 강제 종료 조건은 **본 페이지에서 확인되지 않음** — "maximum execution time" 은 별도 개요 페이지(`develop/programmability/#maximum-execution-time`)로만 링크됨, 별도 fetch 필요 |
|
|
| REDIS-EVAL-C7 | Effects replication(Redis 5.0 부터 기본값, Redis 7.0 부터 유일 모드)은 스크립트의 데이터 변경 명령만 복제하고 replica 는 스크립트를 재실행하지 않으며, 이 방식은 정의상 결정론적이라 별도 조치가 불필요하다 | "Effects replication: only the script's data-modifying commands are replicated. Replicas then run the commands without executing any scripts. ... this replication mode is deterministic by definition ..." / "In Redis 5.0, effects replication became the default mode. As of Redis 7.0, verbatim replication is no longer supported." | `official-vendor-doc` | Redis 5.0+ (특히 7.0+) 의 스크립트 복제 모드 | Redis 7.0 미만 버전에서 verbatim replication 을 여전히 사용하는 배포의 결정론 제약(비결정적 명령 제한)은 별도 섹션("Scripts with deterministic writes")에 있으며, ca-skeleton 이 대상으로 하는 Redis 버전이 7.0+ 인지 여부는 본 자료가 증명하지 않음 |
|
|
|
|
## Usage Boundaries / 적용 경계
|
|
|
|
- **이 자료가 직접 증명하는 것**:
|
|
- `REDIS-EVAL-C1`: 스크립트 실행 중 서버 전체가 블로킹되어 원자적으로 실행됨
|
|
- `REDIS-EVAL-C2`, `C3`, `C4`: 스크립트 캐시의 휘발성 + EVALSHA/NOSCRIPT 복구 절차 (단일 요청 및 파이프라인 맥락 모두)
|
|
- `REDIS-EVAL-C5`: 스크립트가 접근하는 key 는 반드시 `KEYS` 인자로 선언해야 하며 미선언/동적 생성 key 접근 금지
|
|
- `REDIS-EVAL-C6`: `SCRIPT KILL` 은 dataset 미수정 + 실행시간 초과 스크립트에만 적용되는 중단 메커니즘
|
|
- `REDIS-EVAL-C7`: Effects replication 이 Redis 5.0+ 기본, 7.0+ 유일 모드이며 결정론적임
|
|
- **이 자료가 증명하지 않는 것**:
|
|
- `busy-reply-threshold`(구 `lua-time-limit`) 설정 항목, `BUSY` 에러 문자열, 쓰기 스크립트에 대한 `SHUTDOWN NOSAVE` 필요조건 — 이 페이지에는 등장하지 않음(다른 programmability 개요 페이지로만 링크)
|
|
- 스크립트 원자성과 `MULTI`/`EXEC` 트랜잭션의 명시적 비교·차이 서술
|
|
- Redis Cluster 의 실제 hash-slot 라우팅/정적 분석 알고리즘 detail
|
|
- Redis Functions(7.0+ 대안 프로그래밍 모델)의 세부 규칙 — 존재만 언급되고 상세는 별도 문서로 링크됨
|
|
- **내 프로젝트(ca-skeleton)에 적용하려면 추가 확인이 필요한 것**:
|
|
- "bounded execution(유한 실행)" 규칙의 구체적 서버 설정값(`busy-reply-threshold` 기본값/권장값, `BUSY` 에러 처리 흐름) — `https://redis.io/docs/latest/develop/programmability/#maximum-execution-time` 별도 fetch 필요
|
|
- unsafe multi-command recipe ↔ atomic 대체 쌍의 실제 Lua 스크립트 구현 detail은 이 자료 범위 밖 — `feature-redis-atomic-program-catalog-contract` 자체 설계 결정
|
|
- Redisson/Jedis/Lettuce 등 실제 사용 클라이언트 라이브러리가 EVALSHA→NOSCRIPT→SCRIPT LOAD 재시도를 자동화하는지 여부는 각 라이브러리 문서에서 별도 확인 필요
|
|
|
|
## 메모
|
|
|
|
- `busy-reply-threshold` / `BUSY` / `SHUTDOWN NOSAVE` 관련 인용은 이 페이지(`eval-intro`)에 없음을 self-grep 으로 확인(부재 확인, fabrication 아님) — bounded execution 완전한 근거를 위해 `develop/programmability/` 개요 페이지 추가 수집 필요.
|
|
- 인용 6 (`REDIS-EVAL-C7`)의 "결정론/복제" 서술은 branch 결정의 직접 근거는 아니지만, atomic program 이 실행 후 replica 에 어떻게 전파되는지에 대한 배경 지식으로 유용.
|
|
|
|
## Related / 관련
|
|
|
|
- 같은 주제 다른 official-doc: (아직 없음 — `develop/programmability/` 개요, `develop/programmability/lua-api` 후속 수집 후보)
|
|
- 이 자료를 인용한 wiki 요약: `[[wiki/concepts/...]]` (생성 시)
|