From 4e3a3388d612e3642e5dd7e9102674734047a2de Mon Sep 17 00:00:00 2001 From: asahi Date: Tue, 23 Sep 2025 16:24:43 +0800 Subject: [PATCH] =?UTF-8?q?doc:=20=E9=98=85=E8=AF=BBredis=20script/functio?= =?UTF-8?q?n=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 中间件/redis/redis.md | 62 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/中间件/redis/redis.md b/中间件/redis/redis.md index ee382a5..cdae8e6 100644 --- a/中间件/redis/redis.md +++ b/中间件/redis/redis.md @@ -155,6 +155,13 @@ - [TDIGEST.MERGE](#tdigestmerge) - [Retrieving sketch information](#retrieving-sketch-information) - [Resetting a sketch](#resetting-a-sketch) + - [Redis Programmability](#redis-programmability) + - [Introduce](#introduce) + - [Backgroud](#backgroud) + - [running scripts](#running-scripts) + - [Read-only scripts](#read-only-scripts) + - [Sandboxed script context](#sandboxed-script-context) + - [Maximum execution time](#maximum-execution-time) # redis @@ -2604,3 +2611,58 @@ TDIGEST.MERGE destKey numKeys sourceKey... [COMPRESSION compression] [OVERRIDE] > TDIGEST.RESET racer_ages OK ``` + +## Redis Programmability +redis提供了programming interface,允许在server执行自定义的脚本。在redis 7及以上,可以使用`Redis Function`来管理和运行脚本;而在redis 6.2或更低的版本,则使用`lua scripting with EVAL command`。 + +### Introduce +#### Backgroud +在redis中,`Programmability`代表`可以在server端执行任意用户定义的逻辑`,我们将该逻辑片段称之为`scripts`。通过脚本,能够在server端,即数据被存储的地方处理数据。在server端处理用户逻辑,能够降低网络延迟,并且能提高整体性能。 + +在redis通过一个`embedded, sandboxed scripting engine`来执行用户脚本。目前,redis仅支持单一的脚本引擎,即`lua 5.1 interpreter`。 + +#### running scripts +redis提供了两种方式来运行脚本。从`2.6.0`版本开始,redis支持通过`EVAL`命令来运行server-side scripts。在使用用户脚本时,`脚本逻辑中包含应用的业务逻辑`。脚本的source code必须存储在应用端,redis server仅会临时存储source code。当应用的逻辑发生变动时,script将变得难以维护。 + +在redis 7.0版本中,引入了Redis Function。function能够将脚本编写与应用逻辑解耦,并且支持脚本的独立开发、测试和部署。如果要使用redis function,需要先对其进行导入,redis function导入后对所有的connections都是可用的。 + +当redis执行script或function时,能够保证执行过程是原子的。在脚本执行的整个过程中,redis server端的所有其他活动都会被阻塞。 + +在脚本执行中,应当避免执行`slow script`。如果脚本执行较慢,在执行脚本过程中,所有其他clients都会被阻塞,执行不了任何命令。 + +#### Read-only scripts +`read-only scipts`代表在脚本执行时,并不会对redis中的任何key造成修改。可以通过两种方式来执行`read-only script`: +- 在脚本中添加`no-write flag` +- 通过`read-only script command`来执行脚本 + - 常用read-only command如下: + - `EVAL_RO` + - `EVALSHA_RO` + - `FCALL_RO` + +`read-only script`拥有如下特性: +- read-only scripts可以在replicas上被执行 +- 其总是可以被`SCRIPT_KILL`命令被killed +- 即使当redis超过内存限制,其也不会`fail with OOM error` +- 当发生`write pause`时,其也不会被阻塞 +- 在read-only script中,不允许执行任何能对data set造成修改的命令 +- `PUBLISH, SPUBLISH, PFCOUNT`目前仍然被视为write command + +#### Sandboxed script context +redis将执行用户脚本的engine放在了sandbox中。sandbox主要用于防止`accidental misuse`并且降低server环境的潜在威胁。 + +script中永远不应该访问redis server的底层宿主机系统,例如file system、network或执行不受支持的系统调用。 + +script仅应该操作`redis中存储的数据`和`脚本执行时传入的作为参数的数据`。 + +#### Maximum execution time +脚本的执行时长受限于最大执行时长(默认情况下为5s)。这个默认超时很大,默认情况下脚本的运行时长应当小于1ms。该超时用于处理脚本执行时非预期的无限循环。 + +可以通过`修改redis.conf文件`或`使用config set命令`来修改该脚本执行时长上限。影响脚本最长执行时间上限的配置属性为`busy-reply-threshold`。 + +当脚本达到该超时上限时,其并不会自动被redis终止。中断脚本的执行将可能导致`half-write`的问题。 + +故而,将脚本执行时长超过限制时,将会发生如下事件: +- redis会在日志中添加`脚本执行时间过长` +- redis开始从其他clients接收commands,但是会对所有发送normal commands的clients返回`BUSY error`。在该场景下,唯一被允许的命令为`SCRIPT_KILL, FUNCTION_KILL, SHUTDOWN NOSAVE` + - 对于`read-only script`,可以使用`SCRIPT_KILL`和`FUNCTION_KILL`命令,因为该脚本未对数据造成任何修改 + - 如果`script`在执行过程中哪怕执行了一个write operation,那么只能使用`SHUTDOWN NOSAVE`命令,其会停止server,并且不会将当前的data set保存到磁盘中 \ No newline at end of file