lua-resty-redis-fast
版本兼容性
本文保留旧实现的安装和使用说明,并补充面向 Nginx 1.31.8 的新版配置说明。
| 实现 | 适用版本 | 状态与使用说明 |
|---|---|---|
| 新版独立动态模块 | 仅面向 Nginx 1.31.8,对应 OpenResty 1.31.8.x | 加载 ngx_redis_fast_module.so;Lua 接口差异见“新版使用”。 |
| 旧实现 | 与 OpenResty 1.21.4.x、1.25.3.x、1.27.1.x 或 1.31.8.x 匹配的旧版软件包 | 保留以下安装步骤和“旧版使用”说明。 |
旧版 OpenResty 用户应继续使用匹配的旧版私有库。本文的新接口说明依据新版源码;安装时请选择与 OpenResty 匹配的软件包,并根据所安装的实现选择配置。
与开源库的性能比较
在一个典型的并发读取应用场景中,lua-resty-redis-fast 的吞吐量达到开源 lua-resty-redis v0.34 的 3.47 倍,提升 246.9%。
| 指标 | lua-resty-redis-fast | lua-resty-redis v0.34 |
|---|---|---|
| GET 吞吐量中位数 | 214,314 次/秒 | 61,778 次/秒 |
| GET p99 延迟中位数 | 0.785 毫秒 | 1.793 毫秒 |
性能比较采用相同 Lua 并发的共享连接模式,物理连接数不同。测试中 Fast 的连接上限为 6,当前默认上限为 3。实际提升取决于业务负载、连接配置和部署环境。
前提条件
安装软件包要求用户具有 root 权限
机器必须能够访问以下的域名以下载软件包和 GPG 秘钥:
你可以通过执行以下命令验证域名可访问性:
curl https://openresty.org/package/pubkey.gpg curl https://pkg2.openresty.com/xray-priv-libs/
配置软件包仓库
将 CLIENT_TOKEN 替换为订阅邮件中的有效 Token。先下载仓库配置脚本,再按照所用实现选择以下步骤。这些命令只配置仓库,不会安装私有库软件包。
curl -o get-xray-priv-lib-repo.sh https://pkg2.openresty.com.cn/scripts/get-xray-priv-lib-repo.sh
新旧实现都需要配置 OpenResty 开源软件仓库,以便安装 OpenResty 及其依赖。
OpenResty 1.31.8.x 新版实现的仓库
新版只需配置 lua-resty-redis-fast 私有仓库:
sudo bash get-xray-priv-lib-repo.sh -l lua-resty-redis-fast -t CLIENT_TOKEN
新版不需要安装 coro-nginx-module 或 coro-hiredis-nginx-module 软件包,也不需要加载它们的 Nginx 动态模块。
旧版实现的仓库
使用匹配的旧版软件包时,需要配置以下两个私有仓库:
sudo bash get-xray-priv-lib-repo.sh -l coro-nginx-module -t CLIENT_TOKEN
sudo bash get-xray-priv-lib-repo.sh -l lua-resty-redis-fast -t CLIENT_TOKEN
安装
针对 OpenResty-1.21.4.x
使用 yum 的系统,执行以下命令安装私有库:
sudo yum install --disablerepo="*" --enablerepo="coro-nginx-module,lua-resty-redis-fast" -y lua-resty-redis-fast-1.21.4
使用 dnf 的系统,执行以下命令安装私有库:
sudo dnf install --disablerepo="*" --enablerepo="coro-nginx-module,lua-resty-redis-fast" -y lua-resty-redis-fast-1.21.4
使用 apt 的系统,执行以下命令安装私有库:
sudo apt-get install -y lua-resty-redis-fast-1.21.4
针对 OpenResty 1.25.3.x
使用 yum 的系统,执行以下命令安装私有库:
sudo yum install --disablerepo="*" --enablerepo="coro-nginx-module,lua-resty-redis-fast" -y lua-resty-redis-fast-1.25.3
使用 dnf 的系统,执行以下命令安装私有库:
sudo dnf install --disablerepo="*" --enablerepo="coro-nginx-module,lua-resty-redis-fast" -y lua-resty-redis-fast-1.25.3
使用 apt 的系统,执行以下命令安装私有库:
sudo apt-get install -y lua-resty-redis-fast-1.25.3
针对 OpenResty 1.27.1.x
使用 yum 的系统,执行以下命令安装私有库:
sudo yum install --disablerepo="*" --enablerepo="coro-nginx-module,lua-resty-redis-fast" -y lua-resty-redis-fast-1.27.1
使用 dnf 的系统,执行以下命令安装私有库:
sudo dnf install --disablerepo="*" --enablerepo="coro-nginx-module,lua-resty-redis-fast" -y lua-resty-redis-fast-1.27.1
使用 apt 的系统,执行以下命令安装私有库:
sudo apt-get install -y lua-resty-redis-fast-1.27.1
针对 OpenResty 1.31.8.x
软件包名为 lua-resty-redis-fast-1.31.8,提供 RPM 和 DEB 软件包。新版需要 OpenResty 1.31.8.1 或更新的同系列版本。安装前应配置 OpenResty 开源软件仓库,以便包管理器解析依赖。软件包名称中的 1.31.8 只标识匹配的 Nginx 系列;升级后请确认加载的是新版独立动态模块。
使用 yum、dnf 或 apt 的系统,分别执行对应命令:
sudo yum install -y lua-resty-redis-fast-1.31.8
sudo dnf install -y lua-resty-redis-fast-1.31.8
sudo apt-get install -y lua-resty-redis-fast-1.31.8
安装 OpenResty
新版选择 OpenResty 1.31.8.x,使用旧版私有库时则选择匹配的 OpenResty 系列。安装或升级前,先查询软件仓库中的完整版本号,避免动态模块与 OpenResty 不兼容。
| 包管理器 | 查询可用版本 | 安装指定版本 |
|---|---|---|
yum | yum list --showduplicates openresty | sudo yum install openresty-VERSION |
dnf | dnf list --showduplicates openresty | sudo dnf install openresty-VERSION |
apt | apt-cache madison openresty | sudo apt-get install openresty=VERSION |
将 VERSION 替换为查询结果中与所选私有库匹配的完整版本号。
使用
请区分新版独立动态模块与旧版 coro 实现。
新版使用
Nginx 配置
在 nginx.conf 的 main 上下文中加载新版软件包提供的动态模块:
load_module /usr/local/openresty/nginx/modules/ngx_redis_fast_module.so;
自定义安装目录时,应替换为实际模块路径。新版不再需要本库的 coro_preload、coro_stack_size 或两个 coro 动态模块;其他私有库仍需要的配置应予以保留。RPM 和 DEB 软件包使用相同的配置方式。软件包将 Lua 字节码模块安装到 /usr/local/openresty/site/lualib;自定义 lua_package_path 时应保留默认路径(;;),或包含 /usr/local/openresty/site/lualib/?.ljbc。Nginx worker 需要能够读取模块和所需证书、私钥文件。
本次 Lua 接口与行为差异
入口仍为 require "resty.redis.fast",常用命令和流水线方法继续可用,但连接所有权、连接池和会话操作需要按新版语义使用:
| 接口或配置 | 新版行为与迁移要求 |
|---|---|
connect(host, port, options) | 支持 TCP、TLS 和 Unix domain socket;端口可为数字或数字字符串。主机名需要 Nginx resolver。重新连接会清除原有流水线和订阅状态,失败后对象保持关闭。 |
db、select(db) | 可在连接时选择数据库,支持数字或数字字符串。select() 只改变当前 Lua 实例的数据库绑定,不改变其他实例;事务、WATCH、订阅或不可迁移的会话状态中不能切换数据库。 |
max_connections | 默认 3,限制每个 worker、服务端地址和数据库的普通共享连接总数,跨自定义池名、认证和 TLS/RESP 设置计数;每个数据库独立计数,独占连接不受此限制。该地址和数据库的首个连接在连接池仍被使用期间确定上限。 |
pending_threshold | 默认 32,为每条连接上的待回复命令数软阈值。普通命令选择兼容连接中待回复最少的连接;全部达到阈值时,在连接预算允许的情况下扩容,否则继续共享最空闲的连接。 |
pool_size、backlog | 空闲连接数默认 128;设置 backlog 后,pool_size 还限制该池的普通物理连接数,backlog 限制等待建连的队列长度。它们与 max_connections 的限制范围不同。 |
set_keepalive(timeout, size) | 新版实际使用两个参数,更新空闲策略并关闭当前逻辑客户端;默认 60000 毫秒和 128 条空闲连接,超时为 0 时不自动过期。升级时需检查现有调用的超时和容量参数。 |
close() | 释放当前逻辑客户端;干净的普通物理连接可以继续缓存复用,独占或被修改的会话连接会关闭,不保证立即断开共享物理连接。 |
get_reused_times() | 返回最近借用的物理连接的复用计数,关闭时返回 0;后续操作可能使用另一条连接。 |
exclusive = true | 需要 WAIT 或 WAITAOF 时,必须在写入前以此选项连接,将写入和确认固定在同一条连接上;共享模式会拒绝这两个命令。 |
| TLS 与认证 | TLS 证书链验证默认开启;ssl_ca_cert 指定 CA,ssl_verify_name 单独校验证书 DNS 名或 IP,SNI 不代替身份验证。可在 connect() 中提供 password、username。 |
| RESP3 | 在 connect() 中设置 resp3 = true;受保护的服务器还需同时提供认证信息。手动认证时,先以默认 RESP2 连接,AUTH 成功后再调用 hello(3)。 |
| 错误返回 | Redis 命令错误仍返回 false, err,传输错误返回 nil, err;数组或流水线错误项为 {false, err}。RESP3 的 false, nil 是有效结果,应检查 err ~= nil。 |
普通命令完成、读取超时或协程取消后会归还物理连接;当前 Lua 实例仍可继续执行普通命令,迟到回复会被丢弃,不会交给后续调用。改变会话状态的请求超时或取消后,需先执行 RESET,再执行其他命令或归还连接。超时不代表写入没有执行,不能无条件重试写操作。不要在并发操作间共享同一个 Lua 客户端对象。
AUTH、HELLO、RESET、事务、WATCH、订阅和阻塞命令使用独占连接。SELECT 在普通流水线中形成分段边界;事务或 WATCH 中的 SELECT 返回 nil, "SELECT cannot switch connections in a transaction",含此类切换的流水线会在发送任何命令前被拒绝。订阅和 MONITOR 命令不能放入流水线。
Lua 示例
以下代码可放入 content_by_lua_block 中:
local redis = require "resty.redis.fast"
local red = redis:new()
red:set_timeouts(1000, 1000, 1000)
local ok, err = red:connect("127.0.0.1", 6379, {
db = 0,
max_connections = 3,
pending_threshold = 32,
})
if not ok then
ngx.say("failed to connect: ", err)
return
end
local res
res, err = red:set("dog", "an animal")
if err ~= nil then
red:close()
ngx.say("failed to set dog: ", err)
return
end
res, err = red:get("dog")
if err ~= nil then
red:close()
ngx.say("failed to get dog: ", err)
return
end
ngx.say("dog: ", res == ngx.null and "not found" or res)
ok, err = red:set_keepalive(60000, 128)
if not ok then
red:close()
ngx.say("failed to set keepalive: ", err)
end
完整参数和会话规则见API 手册。本库仅支持 HTTP 子系统,不提供 Redis Cluster 路由;访问 Redis Cluster 应使用 lua-resty-redis-cluster-fast。
旧版使用
以下保留旧实现的 Nginx 配置和 Lua 示例;新版请使用上面的配置并核对接口差异。
Nginx 配置
在使用前需要在配置文件 nginx.conf 中需要添加以下这些配置项,用以加载 lua-resty-redis-fast 相关的动态模块。
...
load_module "/usr/local/openresty-coro-nginx-module/lib/ngx_http_coro_module.so";
load_module "/usr/local/openresty-coro-nginx-module/lib/ngx_http_coro_hiredis_module.so";
http {
coro_preload /usr/local/openresty-plus/hiredis/lib/libhiredis.so;
coro_stack_size 32768;
...
}
Lua 接口
除了 set_keepalive 接口发生了变化,该库的其他接口和开源的 lua-resty-redis 保持一致,以下是一个简单的例子:
load_module "/usr/local/openresty-coro-nginx-module/lib/ngx_http_coro_module.so";
load_module "/usr/local/openresty-coro-nginx-module/lib/ngx_http_coro_hiredis_module.so";
http {
coro_preload /usr/local/openresty-plus/hiredis/lib/libhiredis.so;
coro_stack_size 32768;
server {
location /test {
# need to specify the resolver to resolve the hostname
resolver 8.8.8.8;
content_by_lua_block {
local redis = require "resty.redis.fast"
local red = redis:new()
red:set_timeout(1000) -- 1 sec
local ok, err = red:connect("127.0.0.1", $TEST_NGINX_REDIS_PORT)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ok, err = red:select(1)
if not ok then
ngx.say("failed to select: ", err)
return
end
local res, err = red:set("dog", "an animal")
if not res then
ngx.say("failed to set dog: ", err)
return
end
local ok, err = red:set_keepalive()
if not ok then
ngx.say("failed to set keepalive: ", err)
return
end
}
}
}
}