###问题描述:###
应用系统的配置更新过程,它会涉及到多个配置项的更新,它不是一个原子过程。如果在配置更新的过程中,应用程序去读取配置,这里可能存在些“时间窗口”,从而导致不一致性读问题。
###解决方法:###
前提:无论何种实现,要实现统一读取,避免“非一致性”问题,就必须要对所有读取操作“统一化”。
Disconf支持Web或非Web系统,对于这个问题,Web系统或非Web系统需要区分来看:
对于Web系统:
要实现统一读取,可以使用ThreadContext+AOP来实现。
AOP的使用:通过对配置的get方法做切面,统一将用户的配置请求转发至 “我们自己的配置仓库” 里获取,从而实现统一读取。
ThreadContext的使用方式有以下几种:
第一种方法,代价太大。第二种方法,严重增加用户负担,第三种还是需要用户关心这个事情。我们将采用第四种方法。
对于非Web项目:
比较难解决非一致性读取的问题。因为它没有了会话这样一个概念。Apache的FileChangedReloadingStrategy Reload配置文件的方案也没有解决此问题。所以,我们打算放弃这方面的解决。但是,我们还是会提供一个简单却Ugly的解决方案:提供函数来标识用户读取配置的边界。用户可以放弃使用这个方案,但是我们不保证不会发生“不一致读'问题。
关于配置应该放在哪里?有许多讨论,可以放在Web平台上,也可以放在Zookeeper上。从Disconf的实现中,可以看到Disconf是将配置数据放在Web平台的,而不是放在Zookeeper上的。那为什么这么设计呢?下面有个表格比较一下优劣。
配置放在ZK上 | 配置放在Disconf-web平台上 | 比较 | |
---|---|---|---|
配置管理 | 不易管理。ZK相比Mysql不易管理。 | 用Mysql统一存储所有配置数据,非常方便管理,可扩展性强。 | 配置放在Disconf-web显然容易管理和扩展。 |
职责分配 | ZK负责通知与配置数据存储,并提供给client获取数据。disconf-web负责新建、更新配置,并存储一些数据(非配置数据,用作管理),它不为client提供下载配置服务。 | ZK只负责通知。disconf-web负责新建、更新、存储 配置,并为client提供下载配置服务。 | 如果采用第一种方案,数据分散存储了。第二种方案职责明确,数据统一存储在Disconf-web上,ZK只负责通知。 |
client的配置获取 | client启动时,需要从ZK上下载配置。因此必须使用disconf-web先写到ZK上,否则client启动时就无法使用最新配置。配置更新时,client直接从ZK获取最新配置。disconf-web必须统一的在ZK上新建、更新结点。 | client不管是启动还是更新时,均是从disconf-web上获取配置。启动时,client会在ZK监控结点(如果不存在,则新建);更新时,disconf-web更新ZK结点。disconf-web不会在ZK上新建结点。 | 这两种方案其实都差不多 |
配置的一致性问题 | 把数据存储在ZK上,无法像Mysql一样可持久化存储。ZK集群关闭后,数据全部丢失。client直接从ZK上获取配置数据,系统运行久之后,client的配置是否正确无从验证。 | 数据存储在Mysql上,可持久化存储。不管未来是迁移或者扩展之类都非常方便。client是从Web上获取数据,然后再写到ZK上。理论上来说,ZK上的数据应该是与Web平台数据一样的,这可以作为验证平台正确性的一个方法。 | 从可持久化性、可验证性方面来讲,第二个方案好。 |
配置获取 | 配置存储在ZK上,非client想要获取配置,很不容易。 | 配置存储在Web平台上,通过提供RestHttp接口,不管是谁想要获取配置都非常方便。 | 第二种方案获取简单便捷。 |