redis.sha1hex是Redis内置Lua函数,用于在服务端计算字符串的SHA-1哈希值(40位小写十六进制),适用于键名派生、一致性哈希预处理等轻量校验场景,不支持加密或非string输入。

redis.sha1hex 是什么,能用来做什么
redis.sha1hex 是 Redis 内置的 Lua 脚本函数,用于在服务端计算字符串的 SHA-1 哈希值(十六进制小写表示)。它不依赖外部库,也不触发网络或 IO,纯内存运算,适合做轻量级校验、键名派生、一致性哈希预处理等。
它不能用来加密敏感数据(SHA-1 已不安全),也不能替代 redis.call 或 redis.pcall 这类命令执行函数——它只返回字符串,不操作数据。
常见误用是把它当加密函数或试图传 table 给它,但它的参数只能是 string 类型,传 nil 或 table 会直接报错:ERR Error running script (call to f_...): @user_script:1: bad argument #1 to 'sha1hex' (string expected, got nil)
怎么正确调用 redis.sha1hex
调用方式非常简单,只有一个参数:
local hash = redis.sha1hex("hello")- 参数必须是 Lua string;如果变量可能为
nil,务必先判断或默认为空串 - 返回值是长度为 40 的小写十六进制字符串,例如
"aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d" - 不支持二进制字符串(如包含 \0 的 string),Redis 的 Lua 环境对 null byte 处理不稳定,传入会导致截断或错误
实际使用中建议加一层保护:
- 用
tostring(input)防止传入 number/boolean 导致意外结果(虽然 Redis 会隐式转,但显式更可控) - 避免直接对用户输入不做清洗就哈希,尤其含控制字符时可能影响后续键构造逻辑
- 不要用它生成密码哈希——没有 salt、不可调参、无抗碰撞性,用 bcrypt/scrypt 等专用方案
和客户端计算 SHA-1 的结果一致吗
一致,前提是输入完全相同(包括编码、空格、换行符)。Redis 的 redis.sha1hex 使用标准 SHA-1 算法,与 OpenSSL、Python 的 hashlib.sha1().hexdigest() 或 Node.js 的 crypto.createHash('sha1').update(...).digest('hex') 结果相同。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
但要注意:Lua 字符串是字节序列,Redis 不做字符编码转换。如果你在客户端用 UTF-8 编码的字符串哈希,在 Lua 脚本里也得确保传入的是同样编码的 bytes —— 比如中文字符串在 Lua 脚本中就是 UTF-8 字节流,无需额外 encode。
一个容易踩的坑是:在某些 Lua 客户端(如 lua-resty-redis)里拼接 key 时用了 string.format,但格式化结果含不可见字符(如 \r\n),导致哈希值和预期不符。建议用 redis.log(redis.LOG_DEBUG, "input="..input) 在调试时确认原始输入。
性能和限制需要注意什么
redis.sha1hex 性能很好,单次调用耗时在纳秒级,对吞吐影响几乎为零。但它不是“免费”的——每个调用都会计入 Lua 脚本的 CPU 时间配额(由 lua-time-limit 配置,默认 5000ms),极端情况下大量循环调用可能触发 BUSY 错误。
限制很明确:
- 每次脚本中最多调用次数无硬性限制,但总执行时间受
lua-time-limit约束 - 输入字符串长度理论上无上限,但过长(如 >1MB)会显著增加执行时间并挤占其他请求资源
- 不能在
redis.call中嵌套使用(比如redis.call("set", redis.sha1hex("x"), "v")是合法的;但redis.sha1hex(redis.call("get", "k"))没问题,只要get返回 string
真正复杂的地方在于:哈希结果常被用作键名的一部分,而键名一旦生成,就要考虑集群 slot 分布、过期策略、以及是否可逆。这些不是 redis.sha1hex 本身的问题,但却是你用它时绕不开的设计点。

















