首页 > 其他分享 >etcd 历史版本回溯的方法

etcd 历史版本回溯的方法

时间:2023-11-18 18:33:05浏览次数:39  
标签:版本 版本号 -- etcd key 回溯 revision

在使用 etcd 作为配置存储或者其他的场景,如果因为误操作对其中 key 的值进行了修改,如果想要找回原来的值,可以利用 etcd 的版本机制进行回溯找回以前的值。在具体操作之前,我们首先获取一下 key 完整的信息来举个例子:

# 如果开启认证要指定 --user <username>:<password>
etcdctl get --endpoints=$ENDPOINTS <key> -w=json

上面 -w=json 是以 JSON 格式输出指定 key 的数据和元数据,例如下面的内容:

{"header":{"cluster_id":6783024485397960691,"member_id":2129759788194751561,"revision":583,"raft_term":5},"kvs":[{"key":"YWJjZA==","create_revision":370,"mod_revision":375,"version":4,"value":"NA=="}],"count":1}

我们首先看 header 里面的 revision 是当前 etcd 集群全局最新的版本号,注意这个版本号是当前存在数据的版本号,也就是最新写入键值的版本号,不是下一个版本号。然后 kvs 里面就是数据了,其中 key, value 都做了 Base64 编码,其中 create_revision 表示这个 key 创建时所对应的全局版本号,mod_revision 是表示当前版本的修订版本号,version 表示当前这个 key 的局部版本号,创建时的版本是 1,version 是 4 也就是说当前这个 key 在创建后修改了 3 次。

假如我们由于误操作而覆盖了这个 key 的值,那么可以就可以基于版本号来进行历史版本的回溯,前提是不能执行 compact,否则为了压缩空间所有的版本数据都会被清理掉,无法再进行恢复了。

然后如果没有合并过,我们就可以执行回溯,以上面的数据为例,创建版本为 370,修改版本为 375,那么我们要获得上一个版本,首先就需要拿 mod_revision - 1 去查询,然后就可以查询到上一个版本:

etcdctl get --endpoints=$ENDPOINTS <key> -w=json --rev=374

注意对于某个 key 来说,版本不是连续的,因为同时有其他 key 也在操作,这点要明白,现在我们拿到的信息如下:

{"header":{"cluster_id":6783024485397960691,"member_id":2129759788194751561,"revision":583,"raft_term":5},"kvs":[{"key":"YWJjZA==","create_revision":370,"mod_revision":373,"version":3,"value":"Mw=="}],"count":1}

可以看到上一个实际的版本是 373,然后我们再继续使用 372 获取:

etcdctl get --endpoints=$ENDPOINTS <key> -w=json --rev=372

结果如下:

{"header":{"cluster_id":6783024485397960691,"member_id":2129759788194751561,"revision":583,"raft_term":5},"kvs":[{"key":"YWJjZA==","create_revision":370,"mod_revision":371,"version":2,"value":"Mg=="}],"count":1}

可以看到上一个版本实际是 371,那么由于创建版本是 370,两者之间不可能再有其他版本号,所以到这里我们就得到了所有的版本号,当然在实际情况下也可能是不连续的,我们要迭代到两者相等为止,所以我们再继续查询一下:

etcdctl get --endpoints=$ENDPOINTS <key> -w=json --rev=370
{"header":{"cluster_id":6783024485397960691,"member_id":2129759788194751561,"revision":583,"raft_term":5},"kvs":[{"key":"YWJjZA==","create_revision":370,"mod_revision":370,"version":1,"value":"MQ=="}],"count":1}

毫无疑问,现在 create_revisionmod_revision 是相等的,那么也就意味着迭代完毕,拿到的版本号就是 370。

所以根据我们的迭代顺序,将版本号序列反转,结果为:370, 371, 373, 375,这样就得到的全部的版本号序列,然后我们就可以按照版本号依次查看 key 具体版本的值了:

# 只需要去掉 -w 选项,正常输出即可
etcdctl get --endpoints=$ENDPOINTS <key> --rev=<revision>

上面就是指定对于指定 key 整个回溯历史版本的过程,需要注意的是 etcd 只能根据全局的 revision 来回溯,不支持按照每个 key 的 version 来回溯,不过局部这个 version 可以用来直观地查看这个 key 被改了几次。

我们也可以根据上面的过程编写一个程序来实现快速查找 key 历史版本的功能,帮助我们快速拿到指定 key 的所有历史记录。

另外也可以使用 watch 的方法来拿到所有的历史记录,比如我们知道这个 key 对应的 create_revision,那么可以 watch 时指定初始版本,这样就会输出所有的历史:

etcdctl watch --endpoints=$ENDPOINTS <key> --rev=<create_revision>

这样就可以一次性拿到所有的修改记录,不过命令是阻塞的,需要手动结束,写程序时也需要做好控制。上面指定的版本号也不一定是 create_revision,指定个比较小的也可以,比如 1。

以上操作基于 etcd 3.5 版本。

基于 Rust 编写的 etcd 版本回溯工具:https://github.com/monchickey/etcd-version-history 可以参考使用。

Reference:

  1. https://etcd.io/docs/v3.5/learning/data_model/
  2. https://github.com/etcd-io/etcd/issues/7292
  3. https://github.com/etcd-io/etcd/issues/11027

标签:版本,版本号,--,etcd,key,回溯,revision
From: https://www.cnblogs.com/freeweb/p/17840855.html

相关文章

  • Conda管理Python版本
    查看Python版本查看当前环境的Python版本condaactivate&&python-V查看指定环境condaactivatetest&&python-V创建Python环境先搜索conda有哪些python版本condasearch--full--namepython根据搜索出来的版本安装condacreate--nametestpython=3.9.7或......
  • 电脑同时配置JDK8和JDK17两个版本
    1,下载JDK17https://www.oracle.com/java/technologies/downloads/#java17下载zip版本,解压后新建一个jre目录win+rcmdsysmd.cpl2,在系统变量中设置要用JDK17时,就将JAVA_HOME=%JAVA_HOME8%改为JAVA_HOME=%JAVA_HOME17%3,双击Path编辑环境变量小知识如果把以%......
  • Centos7.8 go1.18.3指定版本安装 完美运行Golang安装
    安装背景说明:公司已经有3台服务器安装了go1.18.3版本,这次又买了一台新服务器,由于线上推上去的功能,可能会导致用户出现异常,要做压力测试,所以要重建go环境。遇到问题:昨天下午自己下载了安装包,也是go1.18.3解析到了/usr/local目录也配置了环境/etc/profile 就是识别不到go ......
  • 使用openjdk17编译时报错:Fatal error compiling: 错误: 不支持发行版本 1.17
    1.在linux环境下(docker镜像里面)使用如下命令编译打包时报错mvncleanpackage-Dmaven.test.skip=true[INFO]Scanningforprojects...[INFO][INFO]---------------------<xxx.xxx:pero-xdd>----------------------[INFO]Buildingpero-xdd0.0.1-SNAPSHOT[INFO]-......
  • 记一次Rider2021版本 + EmmyLua + XLua 断点失败问题
    https://www.jianshu.com/p/5a453a80b7e9 按照上述配置加载到对应的LuaMain文件中 也发现连接成功了,但是无论如何都断点不到网上寻找发现Rider2021版本后需要1.ProjectSetting->Editor->C#ProjectGeneration添加;lua如下图ps:一定要保存一下(Ctrl+S),关闭Unity,删......
  • sqlite3版本过低
    报错信息django.db.utils.NotSupportedError:deterministic=TruerequiresSQLite3.8.3orhigher使用sqlite3有时候会出现跟django版本不兼容的问题。如果我们还想使用sqlite3该怎么办?解决方法安装pysqlite3pip3installpysqlite3pip3installpysqlite3-binar......
  • centos执行pip3 install etcd3报错
    centos执行pip3installetcd3报错   File"/usr/lib64/python3.6/os.py",line800,infsencode    filename=fspath(filename) #Doestype-checkingof`filename`.  TypeError:expectedstr,bytesoros.PathLikeobject,notlist这个错误通常是......
  • linux系统多版本boost共存
    因为几个库都用到boost,但是各个库依赖的boost最低版本不一样安装boost1.71tar-zxvfboost_1_71_0.tar.gz&&cdboost_1_71_0su-root./bootstrap.sh--with-libraries=all./b2./b2install 用./b2install把boost1.71安装在默认路径了,即/usr/local下,头文件和库文件分别位......
  • 新版本 el-input 不支持 v-model.trim,自定义指令去除首尾空格
    问题场景<el-inputtype="textarea"v-model.trim="value"/>多行文本输入框无法换行。经测试,去掉.trim修饰符后,就可正常换行了。从官网文档,发现element-ui新版本不支持v-model修饰符。因此,若在新版本的element-ui的el-input中使用v-model.trim,会发生以下问题......
  • linux系统多版本boost库共存
    因为几个库都用到boost,但是各个库依赖的boost最低版本不一样安装boost1.71tar-zxvfboost_1_71_0.tar.gz&&cdboost_1_71_0su-root./bootstrap.sh--with-libraries=all./b2./b2install用./b2install把boost1.71安装在默认路径了,即/usr/local下,头文件和库文件分别......