kevy4.0

Unix-domain socket(UDS)传输

kevy 提供一个可选的 Unix-domain 流式监听,RESP 语义与 TCP 端口完全一致,让同主机客户端彻底绕开 loopback 栈。

什么时候需要它

客户端和服务器同在一台主机上时,UDS 就是合适的传输:

跨主机的客户端仍然要走 TCP——UDS 以文件系统为作用域,永远出不了内核。

核心思路

KEVY_UNIX_SOCKET 设成一个文件系统路径,kevy 就会双绑定:TCP 监听原样保留,UDS 监听跑在同一套 shard 运行时上,用同一个 RESP2/3 解析器接受连接。任何支持 unix:// URL 或 -s <path> 参数的 RESP 客户端,改一行配置就能切过去。UDS 省掉了 loopback 的 rep_movsnft_do_chain 和整条 TCP 系统调用路径,所以单次操作的开销下限在所有负载上都有明显下降。

实例

同时启用两种传输:

KEVY_UNIX_SOCKET=/tmp/kevy.sock kevy --port 6379

redis-cli 走 UDS 连接:

redis-cli -s /tmp/kevy.sock SET foo bar
# OK
redis-cli -s /tmp/kevy.sock GET foo
# "bar"

:6379 上的 TCP 依然并行可用——同一份数据、同一组 shard:

redis-cli -p 6379 GET foo
# "bar"

内置的 Rust 客户端(kevy-client / kevy-client-async)讲 tcp:// / kevy:// / redis:// 加上进程内的 mem://file:/// 两种 scheme——它们不接受 unix:// URL。在 Rust 里,同宿主客户端要么走 TCP loopback 连接,要么当它与服务端同在一个*进程*里时,用 embedded 后端(file:/// / mem://)彻底跳过 socket——那比 UDS 所能达到的还要快。UDS 服务的是其他语言或生态 driver 的跨进程同宿主客户端。

权限与安全

UDS 的信任边界是文件系统——Unix socket 上没有 RESP 层的 AUTH 或 TLS。谁能 open(2) 这个 socket 文件,谁就能下任何命令,包括 FLUSHALL

服务器配置旋钮

Env 变量CLI 标志默认效果
KEVY_UNIX_SOCKET(目前仅 env)未设置要绑定的文件系统路径。不设则只走 TCP。
KEVY_BIND--bind127.0.0.1TCP 绑定地址;UDS 绑定与之独立。
--port--port6379TCP 端口;设了 UDS 之后 TCP 照样绑定。

注意事项:

取舍

同一个 kevy 二进制上,UDS 对比 TCP loopback:

方面UDSTCP loopback
单操作开销下限更低(没有 IP/校验和/端口/NAGLE)较高
可达范围仅同主机任意主机
身份文件系统权限端口 + 绑定地址 + AUTH
生命周期磁盘上的 socket 文件;重启要清理端口生命周期由内核管理
可观测性lsof / ss -xlss -tlnnetstattcpdump
客户端配置unix:///path-s /pathhost:port

吞吐收益取决于负载形态——小载荷、低连接数的格子收益最大(loopback 的每操作税在它们身上占大头);CPU 已饱和的格子收益较小(瓶颈本来就不在传输)。实测数据见 bench/REPORT.md

FAQ

UDS 和 TCP 能同时绑吗?

能——而且这是唯一的模式。设置 KEVY_UNIX_SOCKET 只是加一个 UDS 监听;TCP 监听原样不动。每个客户端各走各的就好。

服务器拒绝启动,报"socket exists"?

这是刻意的。kevy 不会 unlink 一个不是自己创建的路径,否则一次配置错误的运行就能悄悄偷走别的服务的 socket。要么重启前删掉旧文件(rm -f /tmp/kevy.sock),要么每次运行用不同路径,比如 /run/kevy/$(uuidgen).sock。如果文件是 kevy 崩溃后残留的,手工删掉是安全的。

UDS 比 TCP loopback 快多少?

所有负载上都明显更快,因为 UDS 跳过了整条 IP 路径:没有校验和、没有 netfilter 链(nft_do_chain)、没有走 loopback 的 rep_movs、没有每包的 ACK 往返。具体倍率取决于 loopback 开销在每操作预算里占多大比例——单连接、小载荷的负载提升最大;CPU 受限的 pipeline 格子提升较小。用 redis-benchmark -s /tmp/kevy.sock 对比 -h 127.0.0.1,在你自己的负载上量一下。

我的客户端库支持 UDS 吗?

生态 driver 大多支持。redis-cliredis-benchmark 接受 -s <path>。ioredis、node-redis、redis-py、redis-rb、go-redis、lettuce、jedis 都接受 unix:///path URL 或显式的 socket-path 选项——具体键名查你所用 driver 的连接选项文档。内置的 kevy-client / kevy-client-async 讲 UDS:同进程的 Rust 客户端用 embedded 的 file:/// / mem:// 后端胜过任何 socket,跨进程则走 TCP。

客户端全在同一台主机上,能不能干脆不要 TCP?

可以,但没必要。TCP 绑在 127.0.0.1 上,没人连就没有成本,而且客户端 UDS 路径配错时还能当回退。常见的部署是“热点客户端走 UDS,redis-cli 调试走 TCP”。