配置改坏了怎么回滚?Nacos 的历史里存的是哪一版?删除之后还找得回来吗?两个人同时改同一份配置会不会互相覆盖?etcd 和 Consul 有没有历史?这篇用 Nacos 3.2.4、etcd 3.7.2 和 Consul 2.0.4 逐项试出来。
历史条目 id | opType | 修改时间(相对第一条,s) | 这条历史里的内容 --------+--------+---------------+--------- 1 | I | 0.0 | 'v1' 2 | U | 0.4 | 'v1' 3 | U | 0.8 | 'v2' 4 | U | 1.1 | 'v3' 5 | U | 1.4 | 'v4' 6 | U | 1.7 | 'v5' 当前内容:'v6';历史共 6 条,发布了 6 次。每条历史里放的是那次修改“之前”的内容,所以最新的一版(当前内容)不在历史列表里,要回滚到某个旧版本,取的是比它晚一条的历史
U 记录存的是那次修改之前的内容,最新一版不在历史里;要回到某个版本取比它晚一条的历史。
回滚(重新发布历史 id 4 的内容):HTTP 200;当前内容 'v3',md5 与 v3 原来的 md5 相同;历史从 6 条变成 7 条,最新一条(id 7)存的内容是 'v6' 用最新一条历史的内容再发布一次(撤销回滚):当前内容 'v6';历史现在 8 条
回滚是把旧内容重新发布一次,md5 与原来相同,回滚之前的状态也进了历史。
DELETE:HTTP 200 {"code":0,"message":"success","data":true};删除之后当前内容:(HTTP 404 code 20004)
历史条目 id | opType | 这条历史里的内容
--------+--------+---------
9 | I | 'g1'
10 | U | 'g1'
11 | D | 'g2'
用删除记录里的内容重新发布:HTTP 200;当前内容 'g2'(删除之前最后一版是 g2)删除记录里存着删除之前的最后一版,可以用它恢复。
场景 | 操作 | publish_config 返回 | 备注
-------------+---------------------+-------------------------------------------------------------------------------+------------------
(a)不带 CAS | 编辑者 1 发布 | True |
(a)不带 CAS | 编辑者 2 发布 | True | 最终内容 'a: 1\nb: 2'
(b)带 cas_md5 | 编辑者 1 发布(md5 与当前一致) | True |
(b)带 cas_md5 | 编辑者 2 发布(md5 已过期) | 'NacosException: Error [500]: Cas publish fail, server md5 may have changed.' |
(b)带 cas_md5 | 编辑者 2 重新读取、合并、再发布 | True | 最终内容 'a: 2\nb: 2'
另一个观察:用 SDK 发布 c0 后立刻 get_config 得到 '',1.5 s 后得到 'c0';再用 SDK(带 cas_md5)发布 c1,立刻 get_config 得到 'c0',1.5 s 后得到 'c1'。所以上面的读取都走管理 API
顺带一个观察:管理 API 的 POST 带 casMd5=deadbeef(明显不对的 md5)发布,返回 HTTP 200 {'code': 0, 'message': 'success', 'data': True};当前内容 'y'。这个参数名在这个版本的管理 API 上没有起作用(我没有查正确的参数名),要用 CAS 就走 SDK不带 CAS 后发布的会覆盖先发布的;带 cas_md5 过期的发布会被拒绝,需要重新读取合并再发布。
操作 | 结果
---------------------------------------+----------------------------------------------------------------
按 revision 3 读(未压缩) | v2
compact 到 revision 6 之后,按 revision 3 读 | HTTP 400 etcdserver: mvcc: required revision has been compacted
compact 之后,按 revision 6 读 | HTTP 200 v5
key 的元数据:version=5(这个 key 被写了几次),create_revision=2,mod_revision=6(全局 revision);五次写入的 revision:[2, 3, 4, 5, 6]
Consul:写了 v1(ModifyIndex 17)和 v2;用 index=16(早于 v1 的修改)读,0 ms 后返回的是 ModifyIndex 18 的值 'v2';也就是说带旧索引读(blocking query 的 index 参数)得到的是当前值,不是旧版本。我没有在文档或其他接口里找按旧版本读的办法(没有穷尽)
ERRORS {}etcd 能按旧 revision 读,但压缩后读不到;Consul 带旧索引读得到的是当前值。