新闻详情

新闻详情

首页 / 资讯中心 / 详情

hiredis 0.11.0 变更深度解析:多批量回复深度、16KB 读缓冲与 poll(2) 大 fd 支持

发布时间:2026/9/25 1:24:14来源:尧图网络
hiredis 0.11.0 变更深度解析:多批量回复深度、16KB 读缓冲与 poll(2) 大 fd 支持
缓存KV存储数据库后端【免费下载链接】redisNative port of Redis for Windows. Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes, Streams, HyperLogLogs. This repository contains unofficial port of Redis to Windows.项目地址https://gitcode.com/gh_mirrors/redis1/redis点击查看免费下载导读hiredis 是 Redis 官方发布的 C 语言客户端库也是当前仓库Redis for Windows 原生移植版在 deps/hiredis 目录下直接内嵌并随主项目一起编译的依赖组件。本文以 deps/hiredis/CHANGELOG.md 中 0.11.0 与 0.10.1 的条目为主线逐条还原这些变更的源码实现与测试证据帮助读者理解 hiredis 协议解析器read.c、异步上下文async.c以及连接建立逻辑net.c的内部工作机制。读完本文你将掌握 hiredis 读缓冲扩容、multi-bulk 嵌套深度限制、select→poll 迁移、空 multi-bulk 内存泄漏修复与异步错误回复崩溃修复等关键细节并能据此评估自身项目的兼容性与升级风险。版本背景这份 CHANGELOG 记录了什么hiredis 的 CHANGELOG 是典型的修复 增强型发布记录0.11.0 与 0.10.1 两个版本共涵盖 6 项实质性变更全部聚焦于客户端协议栈的健壮性与性能版本变更类型核心内容0.11.0能力增强multi-bulk 回复最大嵌套深度提升到 70.11.0性能优化读缓冲区从 2KB 扩大到 16KB0.11.0兼容性使用 poll(2) 取代 select(2)支持 fd 10240.10.1构建Makefile 全面重构注意环境变量/make 参数覆盖行为0.10.1Bug 修复Issue #45空元素 multi-bulk 回复的内存泄漏0.10.1Bug 修复Issue #43异步上下文下错误回复导致崩溃其中 0.10.0 仅标注See commit log无独立内容本文不做展开。以下按主题逐一深入。multi-bulk 嵌套深度提升到 7解析器任务栈的扩容变更语义Redis 协议中的数组multi-bulk以*开头可以嵌套例如*1\r\n*2\r\n...。0.11.0 之前 hiredis 解析器对嵌套深度的支持有限0.11.0 将最大 multi-bulk 回复嵌套深度提高到 7并在超出时明确报错而不是静默出错。源码实现该限制直接体现在 read.c 的processMultiBulkItem()中static int processMultiBulkItem(redisReader *r) { redisReadTask *cur (r-rstack[r-ridx]); ... /* Set error for nested multi bulks with depth 7 */ if (r-ridx 8) { __redisReaderSetError(r,REDIS_ERR_PROTOCOL, No support for nested multi bulk replies with depth 7); return REDIS_ERR; } ... }配合 read.h 中的任务栈声明redisReadTask rstack[9];解析器使用固定大小的rstack数组作为解析任务栈ridx指向当前任务每解析一个嵌套数组elements 0就ridx压入一层read.c。ridx 8即代表已经处于第 8 层嵌套此时再遇到新的 multi-bulk 就会触发REDIS_ERR_PROTOCOL错误——因此数组大小为 9、最深允许 7 层嵌套rstack[0]为根任务。错误类型为REDIS_ERR_PROTOCOL定义于 read.h错误消息通过errstr字段暴露给调用方。测试验证test.c 中有对应的回归测试连续向解析器喂入 9 次*1\r\n随后断言redisReaderGetReply返回REDIS_ERR且errstr以No support for开头test(Set error on nested multi bulks with depth 7: ); reader redisReaderCreate(); for (i 0; i 9; i) { redisReaderFeed(reader,(char*)*1\r\n,4); } ret redisReaderGetReply(reader,NULL); test_cond(ret REDIS_ERR strncasecmp(reader-errstr,No support for,14) 0);同时 README.md 也向使用者明确说明multi-bulk 负载的嵌套层级被限制为 7超过则解析器返回错误。若你的业务场景中服务器端可能返回超过 7 层嵌套的数组结构例如嵌套的 Lua 脚本返回值需要注意这一硬限制。读缓冲区从 2KB 扩容到 16KB性能与解析器的双重变化变更语义0.11.0 将 hiredis 默认读缓冲区从 2KB 提升到 16KB旨在减少大回复场景下的系统调用次数提升吞吐。源码实现这一变更体现在两处1socket 读取的栈上缓冲区hiredis.c 的redisBufferRead()使用char buf[1024 * 16]一次性从 fd 读取数据int redisBufferRead(redisContext *c) { char buf[1024 * 16]; int nread; ... nread (int)read(c-fd, buf, sizeof(buf)); ... }2解析器的最大未用缓冲上限read.h 定义#define REDIS_READER_MAX_BUF (1024*16) /* Default max unused reader buffer. */在 read.c 附近redisReaderFeed()会检查当缓冲区中已消费但未回收的字节数超过阈值时压缩内部 sds 缓冲避免长期连接下缓冲无限膨胀。扩容后解析器能容纳更大的单次feed数据块减少频繁的缓冲整理。实践意义16KB 的栈上缓冲意味着单次read()最多可吞下 16KB 响应数据对于批量 GET/SET 或大 key 读取能显著减少 read 系统调用次数REDIS_READER_MAX_BUF与读写缓冲相互配合读入 16KB → 喂给解析器 → 若未消费字节超限则压缩。两者同步扩容保持了读入能力与缓冲管理的匹配对嵌入方如本仓库的 Windows 移植而言缓冲位于栈上需注意栈空间有限的线程场景但 16KB 在常规线程栈默认 1MB中影响可忽略。select(2) 迁移到 poll(2)突破 1024 描述符上限变更语义0.11.0 将连接建立时的等待逻辑从select(2)切换到poll(2)以支持fd 1024的场景。select()受FD_SETSIZE通常为 1024限制超出后会越界访问 fd_set而poll()基于 fd 数组、无此上限。源码实现在 net.c 的redisContextWaitReady()中非阻塞 connect 的EINPROGRESS等待完全基于pollfdstatic int redisContextWaitReady(redisContext *c, PORT_LONG msec) { struct pollfd wfd[1]; wfd[0].fd c-fd; wfd[0].events POLLOUT; if (errno EINPROGRESS) { int res; if ((res poll(wfd, 1, (int)msec)) -1) { __redisSetErrorFromErrno(c, REDIS_ERR_IO, poll(2)); ... } else if (res 0) { errno ETIMEDOUT; ... } ... } ... }对应地net.c 引入了poll.h。poll()失败会经__redisSetErrorFromErrno()标记为REDIS_ERR_IO超时res 0则置errno ETIMEDOUT并关闭 fd。实践意义使用 hiredis 管理大量连接的场景如连接池 fd 号被其他资源推高到 1024不再受FD_SETSIZE束缚poll()使用POLLOUT事件等待 socket 可写配合随后的redisCheckSocketError()net.c通过getsockopt(SO_ERROR)检查连接结果构成完整的非阻塞连接建立流程超时值 msec 由redisContextTimeoutMsec()net.c从struct timeval换算而来支持秒微秒到毫秒的转换。Issue #45空 multi-bulk 回复的内存泄漏修复变更语义0.10.1 修复了默认回复对象函数创建含 0 个元素的 multi-bulk 回复时可能发生的内存泄漏。源码实现与测试修复点在 read.c 的processMultiBulkItem()当elements 0时不再压栈而是直接调用moveToNextTask(r)结束该数组只有当elements 0时才创建cur-obj并压入子任务。空数组因此走创建数组对象 → 立即完成的路径避免了对象引用与释放链路的不一致。test.c 有专门的回归测试/* Regression test for issue #45 on GitHub. */ test(Dont do empty allocation for empty multi bulk: ); reader redisReaderCreate(); redisReaderFeed(reader,(char*)*0\r\n,4); ret redisReaderGetReply(reader,reply); test_cond(ret REDIS_OK ((redisReply*)reply)-type REDIS_REPLY_ARRAY ((redisReply*)reply)-elements 0); freeReplyObject(reply);测试名Dont do empty allocation直指问题本质空数组不应触发多余的且可能泄漏的分配路径且freeReplyObject()必须能正确回收。对使用者的意义Redis 命令如LRANGE、KEYS、SMEMBERS等在结果为空时都会返回*0\r\n。修复前在特定对象函数组合下可能泄漏内存修复后空数组作为普通redisReplytype REDIS_REPLY_ARRAY、elements 0被正确创建与释放。升级到 0.10.1 及以上的使用者无需改代码只需在长时间运行的服务中保持版本即可消除该泄漏源。Issue #43异步上下文下错误回复导致的崩溃修复变更语义0.10.1 修复了异步非阻塞场景下连接建立后收到错误回复时崩溃的问题——典型触发场景是 Redis 服务端达到最大连接数对新连接直接回错误并关闭连接。源码实现问题根因位于 async.c 的redisProcessCallbacks()。当异步上下文在没有 pending callback 的情况下收到自发回复spontaneous reply时原实现会将其当作普通回复处理但这类回复实质是服务端拒绝连接的错误如ERR max number of clients reached随后服务端立即断开连接错误信息会被随后的 EOF 错误覆盖进而导致上下文状态错乱、崩溃。修复逻辑如下if (__redisShiftCallback(ac-replies, cb) ! REDIS_OK) { /* * A spontaneous reply in a not-subscribed context can be the error * reply that is sent when a new connection exceeds the maximum * number of allowed connections on the server side. * * This is seen as an error instead of a regular reply because the * server closes the connection after sending it. * * To prevent the error from being overwritten by an EOF error the * connection is closed here. See issue #43. */ if (((redisReply*)reply)-type REDIS_REPLY_ERROR) { c-err REDIS_ERR_OTHER; snprintf(c-errstr, sizeof(c-errstr), %s, ((redisReply*)reply)-str); c-reader-fn-freeObject(reply); __redisAsyncDisconnect(ac); return; } ... }关键点有三检测到REDIS_REPLY_ERROR类型的自发回复时把错误文本复制进c-errstrREDIS_ERR_OTHER立即释放 reply 对象并调用__redisAsyncDisconnect()async.c主动关闭连接防止后续 EOF 错误覆盖真实错误信息注释中还提到另一种触发场景服务端正在加载数据集loading时拒绝请求同样会被正确处理。对使用者的意义升级后异步客户端在连接数打满服务端 loading等场景下不再崩溃且通过redisAsyncContext的err/errstr由__redisAsyncCopyError()同步自底层redisContext见 async.c可以读到真实的错误原因如max number of clients reached便于程序做出重试或降级决策。附0.10.1 Makefile 重构的影响面0.10.1 对构建系统做了整体 overhaul。若你的项目通过环境变量或make 命令行参数覆盖了 hiredis 的编译选项如CC、CFLAGS、DEBUG、PREFIX、INSTALL等升级后必须重新核对这些变量的名称与行为是否仍然生效避免静默失效导致编译产物行为异常。本仓库中 deps/Makefile 与 hiredis 自身 deps/hiredis/Makefile 是构建入口Windows 侧则由 msvs/hiredis/hiredis.vcxproj 承担含 Win32_Interop 的移植适配如WIN_PORT_FIX宏对%zu、%Iu等格式符的替换见 hiredis.c。总结与升级建议变更影响面是否需要应用侧改动multi-bulk 深度 7仅超深嵌套回复会报错协议错误一般无需需确认业务回复不超过 7 层读缓冲 2KB → 16KB性能提升栈上缓冲增大无需select → poll支持 fd 1024无需若自行封装了连接等待逻辑需对齐#45 空 multi-bulk 泄漏内存正确性无需升级即修复#43 异步错误崩溃稳定性无需升级即修复可依赖errstr做错误处理Makefile 重构构建系统需复核自定义的 make 变量覆盖本仓库内嵌的 hiredis 版本同时具备 Windows 移植特性如win32_types_hiredis.h的PORT_LONG/PORT_LONGLONG类型适配见 read.h上述所有修复与增强在 Windows 移植版中同样生效。对于正在使用 hiredis 构建 Redis 客户端或依赖该库的服务的开发者建议对照本文条目逐一验证自身代码的依赖行为并利用 test.c 中的回归用例在升级后重新跑一遍自测确保行为符合预期。赞分享缓存KV存储数据库后端【免费下载链接】redisNative port of Redis for Windows. Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes, Streams, HyperLogLogs. This repository contains unofficial port of Redis to Windows.项目地址https://gitcode.com/gh_mirrors/redis1/redis点击查看免费下载相关推荐hiredis 0.10.1 → 0.11.0 演进深度解析multi-bulk 解析深度、16KB 读缓冲与 poll(2) 化改造hiredis 0.10.1 → 0.11.0 演进深度解析multi bulk 解析深度、16KB 读缓冲与 poll 2 化改造 导读 本篇文章以 Cod后端缓存hiredis 0.10.x–0.11.0 变更解析multi-bulk 嵌套深度、读缓冲区与 poll(2) 连接等待机制hiredis 0.10.x–0.11.0 变更解析multi bulk 嵌套深度、读缓冲区与 poll 2 连接等待机制 这篇技术指南以 Codis 仓库内后端缓存Codis 仓库内嵌 hiredis 0.11.0 变更解析嵌套深度、读缓冲区与 poll(2) 迁移实战指南Codis 仓库内嵌 hiredis 0.11.0 变更解析嵌套深度、读缓冲区与 poll 2 迁移实战指南 导读 本文以 extern/redis 3.2.后端缓存创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

HBase 2.0上安装Phoenix 5.0.0:选包、配置与生产避坑全指南 2026/9/25 2:11:11

HBase 2.0上安装Phoenix 5.0.0:选包、配置与生产避坑全指南

简介:这份压缩包是 Apache Phoenix 5.0.0 针对 HBase 2.0 的官方编译二进制发行版,面向需要在大数据平台上通过标准 SQL 对 HBase 数据做低延迟查询的架构师、运维与开发人员。Phoenix 以 JDBC 驱动形式提供关系型数据库访问层,会把 SQL 自动…

阅读更多 →
RL-赵-(七)-不基于模型2-时序差分/TD算法02-计算ActionValue:Sarsa01【基于RM算法⮕求解贝尔曼公式】【基于一步采样直接求出给定π下ActionValue】 2026/9/25 2:11:05

RL-赵-(七)-不基于模型2-时序差分/TD算法02-计算ActionValue:Sarsa01【基于RM算法⮕求解贝尔曼公式】【基于一步采样直接求出给定π下ActionValue】

RL-赵-(七)-不基于模型3:Sarsa【TD算法】【在线】【基于RM算法在无模型条件下求解贝尔曼公式->基于一步采样直接计算出给定π下的Action Value->立刻基于ϵ-greedy更新π】 原始Sarsa用于估计一个给定policy(π)的 Action Value(Policy Evaluation)。 和 Policy Improv…

阅读更多 →
【Dify】多阶段深度学习图像处理应用 2026/9/25 2:11:05

【Dify】多阶段深度学习图像处理应用

深度学习驱动的多阶段图像处理工作流正在成为视觉内容生成与优化的重要工具。以模型节点协同方式,流程实现了图像的逐步增强和智能化处理,适合初学编程者理解与上手。 本文梳理了典型多模型工作流的操作流程,解析每个环节的节点作用与实现方式,展示多场景下的应用方法,为…

阅读更多 →
RL-赵-(七)-不基于模型2-时序差分/TD算法05-计算ActionValue:Q-Learning01【求贝尔曼最优公式⮕直接得最优ActionValue⮕直接更新目标π】【无需PE与PI迭代】 2026/9/25 2:11:05

RL-赵-(七)-不基于模型2-时序差分/TD算法05-计算ActionValue:Q-Learning01【求贝尔曼最优公式⮕直接得最优ActionValue⮕直接更新目标π】【无需PE与PI迭代】

RL-赵-(七)-不基于模型5:Q-Learning【TD算法】【离线】【基于RM算法在无模型条件下求解贝尔曼最优公式->直接计算出最优ActionValue->直接更新目标π】【无需PE与PI迭代】 直接求解q*(最优action value)得到最优策略,无需在PE与PI迭代来找最优策略。 直接估计optimal acti…

阅读更多 →
C语言详解 2026/9/25 2:11:05

C语言详解

文章目录1 . 概要2 . C语言语法2.1 关键字解释、3 . C语言运算符优先级4 . 本质理解4.1 内存的本质:数字世界的生命与轮回4.2 语法的本质:掌控数字宇宙的至高功法5 . 语法应用5.1 简单示例5.2 指针:时空操控的灵魂之术5.2.1 跨越维度的力量5.…

阅读更多 →
RL-赵-(七)-不基于模型2-时序差分/TD算法04-计算ActionValue:n-step Sarsa【折中①one-step Sarsa与②∞-step MC:采样n步然后更新π】 2026/9/25 2:11:05

RL-赵-(七)-不基于模型2-时序差分/TD算法04-计算ActionValue:n-step Sarsa【折中①one-step Sarsa与②∞-step MC:采样n步然后更新π】

RL-赵-(七)-不基于模型4:n-step Sarsa【TD算法】【Sarsa与MC的折中形式:采样n步就更新π】【Sarsa只需要一步的数据就更新;MC需等到一个episode数据搜集结束再更新】 n-Step Sarsa是Sarsa的一个变型或者是一个推广,因为n-step Sarsa包含了Sarsa和蒙特卡洛两种方法,也就是c…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉