Redis 源码剖析与实战
蒋德钧
中科院计算所副研究员
17747 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 47 讲
Redis 源码剖析与实战
15
15
1.0x
00:00/00:00
登录|注册

27 | 从MOVED、ASK看集群节点如何处理命令?

你好,我是蒋德钧。
在上节课一开始我给你介绍了,我们在 Redis Cluster 这个模块中会学习三部分内容:节点间如何传递信息和运行状态、节点如何处理命令,以及数据如何在节点间迁移。那么通过上节课的学习,现在我们已经了解了 Gossip 协议的基本实现,也就是支持集群节点间信息和运行状态传递的数据结构、关键函数设计与实现。
所以在今天这节课,我们就来了解下集群命令处理的实现。这部分内容不仅包括了集群节点处理一个命令的基本流程,更重要的是,我们可以掌握集群特定命令 MOVED、ASK 是如何实现的。这两个命令对应了 Redis Cluster 中请求重定向的处理场景,了解了这部分内容之后,我们就可以参考 Redis Cluster,来设计和实现分布式系统中的请求重定向。
接下来,我们先来看下集群节点处理一个命令的基本流程,这可以让我们对集群节点的实现有个整体观。

集群节点处理命令的基本流程

我在第 14 讲中提到过,Redis server 处理一条命令的过程可以分成四个阶段,分别是命令读取、命令解析、命令执行和结果返回。而和单个 Redis server 一样,Redis Cluster 中的节点,也是按照相同的阶段来处理命令的。
因此,集群节点在各阶段处理命令的入口函数和单个 Redis server 也是一样的,如下图所示。你也可以再去回顾下第 14 讲中,我介绍的命令处理详细流程。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Redis Cluster中的请求重定向机制是本文的重点内容。文章详细介绍了集群节点处理命令的基本流程,包括命令读取、解析、执行和结果返回等阶段,并着重介绍了处理请求重定向的实现。在处理阶段,节点会调用getNodeByQuery函数查询命令访问的key所在的slot和对应的集群节点,并根据查询结果调用clusterRedirectClient函数执行请求重定向。请求重定向的实现考虑了数据迁移的情况,包括MOVED和ASK两种重定向情况,以及对事务操作的处理。文章指出,Redis Cluster的请求重定向机制对于分布式系统具有重要的参考价值,值得学习。文章还提到了数据迁移的具体实现,为读者提供了深入了解Redis Cluster中集群节点处理命令的技术特点和实现细节的内容。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 源码剖析与实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(3)

  • 最新
  • 精选
  • Kaito
    1、cluster 模式的 Redis,在执行命令阶段,需要判断 key 是否属于本实例,不属于会给客户端返回请求重定向的信息 2、判断 key 是否属于本实例,会先计算 key 所属的 slot,再根据 slot 定位属于哪个实例 3、找不到 key 所属的实例,或者操作的多个 key 不在同一个 slot,则会给客户端返回错误;key 正在做数据迁出,并且访问的这个 key 不在本实例中,会给客户端返回 ASK,让客户端去目标节点再次查询一次(临时重定向);key 所属的 slot 不是本实例,而是其它节点,会给客户端返回 MOVED,告知客户端 key 不在本实例,以后都去目标节点查询(永久重定向) 课后题:processCommand 函数在调用完 getNodeByQuery 函数后,实际调用 clusterRedirectClient 函数进行请求重定向前,会根据当前命令是否是 EXEC,分别调用 discardTransaction 和 flagTransaction 两个函数。这 2 个函数的目的是什么? 看代码逻辑,只有当 n == NULL || n != server.cluster->myself 时,才会调用这 2 个方法。 其中,如果当前执行的是 EXEC 命令,则调用 discardTransaction。这个函数表示放弃整个事务,它会清空这个 client 之前缓存的命令队列,放弃事务中 watch 的 key,重置 client 的事务标记。 如果当前命令不是 EXEC,而是一个普通命令,则调用 flagTransaction。这个函数会给当前 client 打上一个标记 CLIENT_DIRTY_EXEC,如果后面执行了 EXEC,就会判断这个标记,随即也会放弃执行事务,给客户端返回错误。 也就是说,当集群不可用、key 找不到对应的 slot、key 不在本实例中、操作的 keys 不在同一个 slot、key 正在迁移中,发生这几种情况时,都会放弃整个事务的执行。
    2021-10-13
    8
  • 曾轼麟
    回答老师的问题: 按照我个人理解,不知道是否准确。 我们先了解一下Redis事务的实现方式,命令在multiState中是以队列的形式保存着的,只有当执行EXEC的时候,才会按照队列顺序依次执行里面的命令,否则会调用queueMultiCommand将命令保存到这个队列中,而事务在Redis中是以client的维度开启的,如果一个client开启了事务,那么它结构体中的flags会被设置为CLIENT_MULTI(在事务中),那么问题中的两个函数的作用是什么? 1、【discardTransaction】:直接丢弃当前的事务,清空multiState队列里面的命令,并且会对事务中的key unWatch。 2、【flagTransaction】:将client的flages设置为CLIENT_DIRTY_EXEC(事务最终将在EXEC的时候也会失败)。 两个方法刚好对应了client在事务中,执行EXEC命令和普通命令的两种情况。Redis是发现当getNodeByQuery返回的clusterNode节点不是自己的时候才会执行这两个方法,并且当Redis以集群模式运行的时候,跨节点是不支持事务,如果发现当前client有事务开启的情况,可能是之前开启的,那么当getNodeByQuery发现不是自己的时候需要把之前的事务废弃。如果命令直接就是EXEC了那么直接调用discardTransaction丢弃事务,如果是事务中的某个命令出现这种情况(例如:开启事务后发生迁移),则调用flagTransaction,等到EXEC的时候一样丢弃。 补充: 集群中涉及MULTI/EXEC的操作需要让key都在同一节点上面,如果不在会返回 MOVED 信息或者直接返回error信息。
    2021-10-12
    2
  • 可怜大灰狼
    只要能够进入n == NULL || n != server.cluster->myself,都表示需要重定向客户端了。如果当前是execCommand,discardTransaction就释放整个multi阶段缓存下来的命令。否则就打一个脏标识CLIENT_DIRTY_EXEC
    2021-10-12
收起评论
显示
设置
留言
3
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部