我在阅读nacos distro协议实现的源码的时候,产生了一个疑问:
无论是DistroController里的onSyncDatum()方法还是syncChecksum()方法,它们在接收到其他nacos-server节点出传过来的数据的时候,都没有经过经过类似于时间戳/版本等信息的比较,就直接put进自身的内存当中去了。 onSyncDatum()传过来的数据:
syncChecksum()传过来的数据:
请问这样不会导致旧数据覆盖新数据的问题吗?
假如现在集群下有A、B、C三台nacos-server节点,设想这样两个场景:
场景一:
· 客户端短时间内向节点A发出了两个registerInstance请求,两个请求携带的元数据不一样 · 节点A收到第一个请求,通过distro向B、C广播数据包v1 · 节点A收到第二个请求,通过distro向B、C广播数据包v2 · 由于网络抖动或其他不可知因素,B或者C先收到第二个请求包 v2,再收到第一个请求包v1 · 会不会出现旧数据v1覆盖新数据v2的问题?而且此时节点B或者C的数据跟A不一致了
场景二:
· 接上面的场景一,假如这个时候节点的DistroVerifyTask开始工作,节点B或者C会把旧数据v1的checksum信息发送给A · 如果节点A不加判断、比较,会不会出现A去B或者C中查询到旧数据v1,然后把自身的新数据v2覆盖掉的情况?
总而言之,就是我发现distro协议无论是在广播通知的时候还是在verify对账的时候,收到数据包的nacos-server节点无法判断收到的数据和自身内存中的数据何者是“最近更新的正确的数据”,从而有可能发生旧数据覆盖新数据的情况。
请问是设计如此?还是我的理解有问题,阅读代码有疏漏的地方?
原提问者GitHub用户MajorHe1
看一下DistroMapper和DistroFilter, 同一个tag(service)的请求只会在一个node上执行,所以不会出现您说的场景。
我再解释一下, 假设真的出现场景1
· 客户端短时间内向节点A发出了两个registerInstance请求,两个请求携带的元数据不一样 · 节点A收到第一个请求,通过distro向B、C广播数据包v1 · 节点A收到第二个请求,通过distro向B、C广播数据包v2 · 由于网络抖动或其他不可知因素,B或者C先收到第二个请求包 v2,再收到第一个请求包v1
那么A节点就是responsible节点,他自身的数据更新是按照v1,v2的接收顺序处理的。 由于v1,v2会在短时间内进行合并,大概率只会触发v2变更。
如果正好卡在v1执行,v2不执行的窗口节点,那么v1执行和v2执行会有一个delay时间,默认应该是1~2s。且根据DistroExecuteTaskExecuteEngine,同一个服务会在同一个线程中串行执行,v1必然在v2前被广播完成。
再假设您说的各种未知问题,导致了v2比v1更早在BC节点生效,那么根据最后DistroVerifyTask和DistroMapper的权威节点判定,BC节点还是会到A节点获取最新的v2数据。保证最终一致性。
原回答者GitHub用户KomachiSion
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
阿里云拥有国内全面的云原生产品技术以及大规模的云原生应用实践,通过全面容器化、核心技术互联网化、应用 Serverless 化三大范式,助力制造业企业高效上云,实现系统稳定、应用敏捷智能。拥抱云原生,让创新无处不在。