Consul:Consul中index介绍

一、index知多少

先看阻塞查询Consul KV的例子:

curl -H 'X-Consul-Token: 93d4dc25-fb4 -486b-a216-16f8fab52fcd' 'http://127.0.0.1:8500/1/kv/test/data?index=245706000\&wait=10s' -v

返回结果:

> GET /kv/test/data HTTP/1.1

> Host: 15.56.57.200:8500

> User-Agent curl/8.19.0

> Accept:*/*

> X-Consul-Token: 93d4dc25-fbb4-486b-a216-f6f8fab52fcd

< HTTP/1.1 200 OK

< Content-Type: application/json

< Vary: Accept-Encoding

< X-Consul-Default-Acl-Policy: deny

< X-Consul-Index: 245706000

< X-Consul-Knownleader: true

< X-Consul-Lastcontact:

< X-Consul-Query-Backend: blocking-query

< Date: Mon, 21 Sep 2026 03:27:53 GMT

< Content-Length:114

("LockIndex":0, Key":"test/data","Flags":0,"Value":"MzlzMjiMyMz=","Createlindex":9356026,"Modiflndex :245706000\]

Consul查询主要条件参数如下:

?raw:直接返回原始值(不经过Base64编码),但仅适用于单个键查询

?recurse:递归查询所有子键

?keys:只返回键名,不返回值

?dc=<数据中心>:指定数据中心(多数据中心场景)

?index=<ModifyIndex>&wait=<等待时间>:index和wait必须同时使用,否则wait无效。index为0,表示从当前最新状态开始查询(不等待)。wait最大限制:默认10分钟(600s),可通过Consul配置max_query_time调整。

上面看到有index、X-Consul-Index、Modifylndex、LockIndex、Createlndex,下面介绍这些index的含义:

LockIndex:表示该KV键值对当前被锁定的次数(即锁的版本号)。每次对该键执行锁操作(如通过Consu的Session锁定)时,LockIindex会递增。如果值为0,表示该键未被锁定。它主要用于分布式锁机制,帮助检测锁是否被释放或更新。
CreateIndex:表示该KV键值对在Consul集群中被创建时的全局唯一索引号。
ModifyIndex:资源级索引,具有资源独立性,每个具体资源(KV键,服务、健康检查等)的最后ModifyIndex值,等于该资源最后一次变更时全局唯一索引号的值。存储位置:资源元数据(如KV存储的键值对)
X-Consul-Index:是存放在HTTP响应头中的ModifyIndex
index:Consul客户端通过?index=<Modifylndex>监听某个盗源的变化。Consul 比较传入的index 与资源当前的ModifyIndex:

若传入index<当前ModifyIndex,立即返回新数据。

若传入index>=当前 Modifyndex,阻塞等待,直到该资源的Modifyndex超过传入值。
applyndex:也就是上面提到的全局唯一索引号,具有全局唯一性。Consul集群使用Raft协议维护一个全局的raft:applyindex,每次写入操作(创建、更新、删除)都会使该索引递增。存储位置:Raft日志(内存+持久化)

其实平时用的最多的还是Modifyndex。在下面文章中讲到的index,如果没有特殊说明,一律等同于ModifyIndex。

二、目录的index

下面再说一下Consul中比较特殊的资源----目录的ModifyIndex

目录(即KV存储中的前缀路径,或称为资源列表)的 ModifyIndex等于该目录下所有键中最大的 Modifylndex。
资源的 ModifyIndex = 该资源最后一次被修改时的全局applylIndex

目录的 ModifyIndex = 目录中任意资源最后一次被修改时的全局applyndex

根据上面的描述,如果对目录下的KV进行操作,会有什么结果,可以分析一下:

1、当目录下某个KV修改了,这个KV的ModifyIndex将会变成这个目录下的最大ModifyIndex,这个ModifyIndex的值也同时成为这个目录的ModifyIndex;

2、如果目录下某个KV被删除了,目录的ModifyIndex将会如何变化,需要分3种场景来分析:

  • 场景一:被删除的健是最大值ModifyIndex变小

    回退到次大值

  • 场景二:被删除的键不是最大值一ModifyIndex不变

    最大值仍在

  • 场景三:被删除的键是唯一最大值ModifyIndex变0

    空目录

  • 结论:删除目录下的键不会导致目录ModifyIndex变大,只会不变或变小。

但是,实际使用Consul客户端监听目录时,如果目录下的某个KV被删除了,这个目录的ModifyIndex还是变大了,这又是怎么回事?

三、墓碑机制

这里就不得不介绍一下Consul的墓碑机制(Tombstone Mechanism)

工作原理

1、删除操作

删除一个键值对时,Consul不会立即从存储中物理移除该条目。相反,它会将该键标记为"已删除",并记录一个墓碑标记。

这个标记通常包含:

  • 被删除键的完整路径
  • 一个唯一的、递增的修改索引(ModifyIndex),用于标识删除操作的时序。
  • 一个TTL(生存时间),用于控制墓碑的保留时长。

Consul为什么采用运种处理方式也非常好理解,Consul客户端在监听这个止录时,如果目录下的资源在删除时没有生成递增的ModifyIndex,Consul客户端就监听不到变化(前面已经分析过,ModifyIndex可能不变),从而不会触发Consul客户端立即进行处理。

2、传播与同步

墓碑标记会像普通数据一样,通过Raft协议复制到集群中的所有节点。这样,即使某个Consul服务节点之前持有该键的旧值,在收到墓碑后也会将其标记为已删除。

3、垃圾回收

墓碑不会永久保留。Consul 会定期执行垃圾回收(Garbage Collection)任务。当满足以下条件时,墓碑会被物理删除:

  1. 该墓碑的TTL已过期(通常为几十分钟到几小时,取决于配置 tombstone_ttl 的值,默认值:15m)
  2. 集群中的所有节点都已确认收到该墓碑(通过Raft日志提交确认)。
  3. 没有其他未完成的、依赖于该键的会话(Session)或锁

虽然目录的ModifyIndex此时会变小,也会触发Consul客户端进行处理,但因为内容没有变化,一般也不会影响Consul客户端的数据。

应用场景

  • KV Store:这是墓碑机制最直接的应用。删除一个KV条目后,其墓碑会阻止该键在集群中重新出现。
  • 服务注册与健康检查:当一个服务实例被注销(deregister)时,Consul会为其创建一个墓碑。这可以防止因网络迟或节点故障导致的旧服务信息"复活",确保服务发现目录的准确性。
  • 会话(Session):当会话失效或被销毁时,与该会话关联的锁或临时键值对会被删除。墓碑机制确保这些锁不会在会话恢复后意外重新生效。

四、目录index的变化

结合上面对Consul墓碑机制介绍,就能知道目录下的某个KV被删除后,这个目录的index会先变大,然后过一段时间后再变小。

过程说明

  1. 目录下的某个KV被删除后,会创建一个墓碑(tombstone)记录,标记该健已被删除,墓碑记录包含一个递增的 ModifyIndex 从而导致目录的ModifyIndex也递增了;
  2. 此时这个KV已经删除了,普通的查询API(如 GET /v1/kv/)确实不会返回这个已删除的键,因为墓碑记录使其对普通查询不可见;
  3. 过了一段时间,Consul执行垃圾回收,垃圾回收只删除墓碑本身,释放元数据空间,再查询目录index时,会发现目录index变小了。

举例说明

再举个例子对这个过程说明一下:

  1. 通过查询API查某个目录的ModifyIndex(比如值为N);
  2. 删除了这个目录下的一个KV,再查这个目录的ModifyIndex(比如值为M),会发现ModifylIndex变大(M>N);
  3. 过一段时间Consul执行垃圾回收后,再查这个目录的index(比如值为S,S<M);
  • 当被删除的KV的ModifyIndex是这个目录下所有KV的ModifyIndex中最大的时,S<N;
  • 当被删除的KV的ModifyIndex不是这个目录下所有KV的ModifyIndex中最大的时,S=N;
  • 当被删除的KV是这个目录下唯一的KV时,S=0<N

五、ModifyIndex变小的其它场景

通过以上内容的介绍,可以发现删除目录下资源可能会使目录的ModifyIndex变小。其实还有其它情况会造成ModifyIndex变小:

  • 场景一:Consul 集群重启或Leader 切换

    现象:当Consul集群所有节点重启,或发生Leader切换且新Leader的Raft日志被截断时,全局索引可能从较大的值回退到较小的值。

    原因:Raft 日志在Leader 切换后可能被截断(如旧Leader 的未提交目志被丢弃),新Leader的applylndex从日持久化的日志中恢复。

  • 场景二:Consul数据被手动重置或恢复

    现象:通过consul snapshot restore 恢复快照,或手动清空Consul 数据目录后重启。

    原因:快照中的Index是备份时的值,恢复后Index会从备份值开始重新递增,可能小于恢复前的Index。

客户端如果使用旧的Index发起阻塞查询,Consul 会认为该Index大于当前值,立即返回当前数据(而非等待变更),导致客户端误以为资源发生了变更。

相关推荐
Msshu12313 天前
快充诱骗取电芯片XSP26A 支持全协议取电+串口发送充电器功率+共用D+D-网络
mongodb·postgresql·etcd·flume·consul·kylin
YOU OU15 天前
Spring Cloud Consul
spring cloud·consul·java-consul
吉甫作诵1 个月前
Prometheus 安装配置:Consul 自动发现与 Thanos Sidecar 持久化
prometheus·consul
软糖姐姐2 个月前
python eureka服务发现_python与consul 实现gRPC服务注册-发现
python·consul·grpc·服务注册·发现
南大白2 个月前
Consul 与 Nacos 核心差异总结
consul
2601_960906722 个月前
中国智能投影市场(不含激光电视)全渠道销量同比暴跌21.4%
kafka·etcd·consul·storm
希望永不加班4 个月前
SpringBoot 服务注册与发现:Nacos/Consul/Eureka
java·spring boot·eureka·consul·java-consul
成为你的宁宁4 个月前
【基于 Consul 实现 Prometheus 服务发现部署与实战】
prometheus·consul
白露与泡影4 个月前
轻量级微服务发布系统:Traefik + Nomad + Consul
微服务·架构·consul