目录
一、Redis 客户端:银行的 “客户档案”
二、客户端关闭:银行的 “终止服务规则”
三、命令处理流程:柜员办理业务的 “标准步骤”
1. 接收申请单(读取命令请求)
2. 确认业务类型(查找命令)
3. 检查业务合法性(预备操作)
4. 办理业务(调用命令实现函数)
5. 收尾工作(执行后续工作)
6. 给客户回执(发送命令回复)
四、serverCron 函数:大堂经理的 “定期巡检”
五、服务器初始化:银行的 “开业准备流程”
六、总结:银行系统与 Redis 的对应逻辑
如果把 Redis 服务器比作一家高效运转的银行,那么客户端就是 “来办理业务的客户”,服务器的命令处理流程就是 “柜员办理业务的标准步骤”,而serverCron
函数则是 “大堂经理的定期巡检”。我们用银行的场景来拆解这整套系统:
一、Redis 客户端:银行的 “客户档案”
每个来银行办理业务的客户,银行都会建立一份 “客户档案(redisClient
结构体)”,记录客户的关键信息:
redisClient 属性 | 银行场景类比 | 作用 |
---|---|---|
name | 客户昵称(可选,默认无) | 用CLIENT SETNAME 给客户贴个标签,方便识别 |
fd | 客户的 “业务窗口编号” | 普通客户(网络连接)有编号(>0),内部模拟客户(伪客户端)无编号(-1) |
flags | 客户身份标识(如 “VIP”“理财客户”) | 标记客户端角色(如从服务器、未完成同步的从节点等) |
querybuf | 客户填写的 “业务申请单缓冲区” | 临时存放客户发送的命令请求(未解析前) |
argv /argc | 申请单上的 “业务详情” 和 “参数数量” | 解析后的命令参数(如SET msg "hello" 拆成argv = [SET, msg, "hello"] ,argc=3 ) |
buf /bufpos | 柜员给客户的 “回执单缓冲区” | 存放命令回复内容,bufpos 记录已写长度 |
authenticated | 客户 “身份验证状态” | 0 = 未实名,1 = 已实名(未验证不能办业务) |
ctime /lastinteraction | 客户 “开户时间” 和 “最后办理业务时间” | 用于判断客户是否 “休眠”(超时未操作) |
obuf_soft_limit_reached_time | 客户 “取号排队超时起点” | 记录输出缓冲区首次超过软限制的时间,用于判断是否强制终止服务 |
二、客户端关闭:银行的 “终止服务规则”
银行会在以下情况拒绝为客户服务(关闭客户端):
- 客户离场:客户主动离开(进程退出),窗口自动关闭(
fd
连接断开)。 - 填错单据:客户提交的申请单格式错误(命令不符合协议),柜员拒收并请客户离开。
- 被管理员清退:大堂经理(
CLIENT KILL
命令)强制请走某些客户。 - 长时间不办业务:客户取号后超时未操作(超过
timeout
配置),视为放弃服务。 - 申请单太大:客户的业务申请单超过最大尺寸(输入缓冲区 > 1GB),柜员无法处理。
- 回执单太多拿不下:给客户的回执单超过限制(输出缓冲区超限):
- 硬限制:回执单堆成山(超硬限制),直接请客户离开。
- 软限制:回执单较多(超软限制),但客户还在等,记录开始等待时间;若超时仍未取走,强制请离。
三、命令处理流程:柜员办理业务的 “标准步骤”
客户到窗口递申请单(发送命令),柜员按以下步骤处理,对应 Redis 的命令执行流程:
1. 接收申请单(读取命令请求)
- 客户把填好的申请单(命令)递进窗口,柜员先临时放在 “待处理文件夹(
querybuf
输入缓冲区)”。 - 柜员解析申请单,提取 “业务类型” 和 “参数”(如 “存款 100 元” 拆成
argv = [存款, 100]
,argc=2
),写入客户档案。
2. 确认业务类型(查找命令)
- 柜员查 “业务手册(命令表
command table
)”,根据申请单的 “业务类型”(argv[0]
)找到对应的办理流程(redisCommand
结构,包含实现函数)。
3. 检查业务合法性(预备操作)
- 柜员先做一系列检查,确保业务能正常办理:
- 业务类型是否存在(
cmd
是否为NULL
)? - 参数数量是否正确(如 “转账” 需要收款人、金额,缺一不可)?
- 银行现金是否充足(
maxmemory
限制,内存不足可能拒绝写命令)? - 银行是否在维护(如数据载入中,只允许少数查询业务)?
- 客户是否在特殊状态(如正在订阅理财产品,只能办相关业务)?
- 若有监控(
MONITOR
),需同步记录业务详情给监控员。
- 业务类型是否存在(
4. 办理业务(调用命令实现函数)
- 按业务手册的流程办理(执行命令函数),比如 “存款” 就修改客户账户余额(更新 Redis 数据库)。
5. 收尾工作(执行后续工作)
- 若业务耗时太长(慢查询),记录到 “慢业务日志”。
- 更新该业务的 “办理次数” 和 “平均耗时”(
calls
和milliseconds
属性)。 - 把业务详情记到 “银行流水(AOF 缓冲区)”,同步给 “总行备份(从服务器)”。
6. 给客户回执(发送命令回复)
- 柜员把办理结果写在 “回执单(输出缓冲区)”,等客户窗口空闲(套接字可写)时,把回执递给客户。
四、serverCron 函数:大堂经理的 “定期巡检”
银行大堂经理每 100 毫秒巡视一次(serverCron
默认频率),处理日常维护,确保银行正常运转:
- 校准时钟:同步墙上的 “电子钟(
unixtime
秒级时间)” 和 “毫秒表(mstime
)”,减少频繁看表(系统调用)的开销。 - 更新物品存放时间:每 10 秒更新一次 “储物柜最后使用时钟(
lruclock
)”,用于判断哪些物品长期无人取(LRU 内存回收)。 - 统计业务量:每 100 毫秒抽样统计 “每秒办理业务数”,估算银行繁忙程度。
- 记录最大客流量:若当前客户数创纪录,更新 “最高客流量(
stat_peak_memory
)”。 - 处理停业通知:若收到 “停业指令(
SIGTERM
信号)”,标记 “准备关门(shutdown_asap
)”,下次巡视时执行关门。 - 维护客户秩序:
- 清退 “超时未办业务的客户”(检查
lastinteraction
,超过timeout
则关闭客户端)。 - 清理客户的 “废弃申请单”(输入缓冲区过大时重置,释放内存)。
- 清退 “超时未办业务的客户”(检查
- 安排备份工作:若 “流水账重写(
BGREWRITEAOF
)” 因 “账本快照(BGSAVE
)” 排队,现在轮到它执行了。 - 检查备份进度:看看 “账本快照员(
rdb_child_pid
)” 和 “流水账重写员(aof_child_pid
)” 是否在工作,是否完成。 - 同步流水账:把 “临时流水缓冲区(AOF 缓冲区)” 的内容写到 “正式流水册(AOF 文件)”。
- 清退取单超时客户:把 “回执单拿太久(输出缓冲区超限)” 的客户请离。
- 记录巡视次数:每次巡视后,“巡视计数器(
cronloops
)” 加 1,用于一些定时任务触发。
五、服务器初始化:银行的 “开业准备流程”
Redis 服务器从启动到接待客户,像银行开业前的准备:
-
布置场地(初始化服务器状态):
- 设定 “银行编号(
runid
)”、“营业时间(默认配置)”、“业务窗口数量(端口)” 等基础信息(initServerConfig
函数)。 - 准备 “业务手册(命令表)”,把所有可办理的业务(
SET
、GET
等)录入。
- 设定 “银行编号(
-
加载个性化配置(载入配置选项):
- 根据 “上级指示(命令行参数)” 和 “银行规章(配置文件)”,调整营业时间、窗口数量等(覆盖默认配置)。
-
准备设备(初始化数据结构):
- 摆好 “客户排队表(
server.clients
链表)”、“账户档案柜(server.db
数组)”。 - 准备 “理财产品订阅簿(
pubsub_channels
字典)”、“慢业务记录本(slowlog
)” 等。
- 摆好 “客户排队表(
-
恢复账目(还原数据库状态):
- 开业前,根据 “纸质账本(RDB 文件)” 或 “历史流水(AOF 文件)”,把所有客户账户余额恢复到上次关门时的状态。
六、总结:银行系统与 Redis 的对应逻辑
整个 Redis 客户端与服务器的交互,就像银行的 “客户 - 柜员 - 大堂经理” 体系:
- 客户端是 “客户”,带着命令请求来办理业务,有自己的档案信息。
- 命令处理流程是 “柜员的标准化服务步骤”,从接收到反馈环环相扣。
- serverCron是 “大堂经理的巡检”,确保银行资源合理分配、系统稳定运行。
- 初始化过程是 “开业准备”,从场地布置到账目恢复,为服务客户做足准备。
这种设计让 Redis 既能高效处理 “客户业务(命令)”,又能通过 “巡检” 维持系统稳定,就像一家流程规范、运转高效的银行。