Diamond#1:设计

来源:互联网 发布:台湾炒股软件 编辑:程序博客网 时间:2024/05/29 01:55

diamond是淘宝内部使用的一个管理持久配置的系统,它的特点是简单、可靠、易用,目前淘宝内部绝大多数系统的配置,由diamond来进行统一管理。diamond为应用系统提供了获取配置的服务,应用不仅可以在启动时从diamond获取相关的配置,而且可以在运行中对配置数据的变化进行感知并获取变化后的配置数据。

分布式存储

个人理解Diamond同Tair、TFS一样都是提供分布式存储服务,接下来像之前分析Tair、TFS一样,从服务路由,负载均衡,容错,扩容和存储机制来看下Diamond的设计。

    +--------+           +------------+    | Client |  ------>  | HTTPServer |    +--------+           +------------+        |        |              +-----------------+        +----------->  |  DiamondServer  |         +-------+                       |     Cluster     | ----->  | MySQL |                       +-----------------+         +-------+

服务路由

同Tair与TFS一样,Diamond集群里也有机器充当着NameServer的角色,称为地址服务器。

地址服务器是一台有域名的机器,上面运行有一个HTTP server,其中有一个静态文件,存放着diamond服务器的地址列表。客户端启动时,根据自身的域名绑定,连接到地址服务器,取回diamond服务器的地址列表,从中随机选择一台diamond服务器进行连接。

出于容灾考虑,Client会将DiamondServer地址列表保存到本地,当无法从地址服务器获取列表时,使用本地保存的列表。如此一来为了保证本地列表是最新的,又起了一个后台定时任务,访问地址服务器更新本地列表。如此看来还是Tair的version机制靠谱。

负载均衡

因为每一台DiamondServer都是持有全部数据,所以也就没有数据的负载均衡一说,那么这里也就只有Client访问时的负载均衡。从服务路由中可以看出,Diamond其实没有做什么负载均衡方面的工作,就是Client随机选择一台Server连上。但是每台Server前端会有一台nginx来做流控(Client得知被流控后,会否切换Server访问?)。

容错机制

还是看两个问题,同步与切换。

数据最终是存储在数据库中,出于性能与容灾考虑每台DiamondServer都会本地缓存一份数据,如此便需要数据库与机器之间同步数据:

  1. server写数据时,先将数据写入mysql,然后写入本地文件,写入完成后发送一个HTTP请求给集群中的其他server,其他server收到请求,从mysql中dump刚刚写入的数据至本地文件。
  2. server启动后会启动一个定时任务,定时从mysql中dump所有数据至本地文件。

所以Diamond应该也是采用最终一致,个人觉得是可以做强一致的(同TFS),从使用场景来说还是有必要的。

至于切换,则简单得多,Client已经拿到所有DiamondServer的地址列表,切换地址访问即可。

此外,Diamond与Tair、TFS在容灾上最大不同点是Diamond的集群即使全部不可用也不会死人,Client在本地做了snapshot缓存,另外还有一个容灾目录,可以通过手动分发配置文件到容灾目录的方式来救火。

平滑扩容

扩容也相对简单,启动新的DiamondServer,dump数据库中的数据,修改地址服务器的服务器列表文件,应该就没问题了。

存储机制

看一下数据库的表结构就很清楚了。

create table config_info ('id' bigint(64) unsigned NOT NULL auto_increment,'data_id' varchar(255) NOT NULL default ' ','group_id' varchar(128) NOT NULL default ' ','content' longtext NOT NULL,'md5' varchar(32) NOT NULL default ' ','gmt_create' datetime NOT NULL default '2010-05-05 00:00:00','gmt_modified' datetime NOT NULL default '2010-05-05 00:00:00',PRIMARY KEY  ('id'),UNIQUE KEY 'uk_config_datagroup' ('data_id','group_id'));

Diamond其实也是使用了KV结构,key是group_id+data_id,value是content,是字符串类型,存储什么样的内容可以自由发挥,kv对,json,xml都可以,Client通过key拿到这个content再自己去解析。md5是content的md5,用法下文会说到。

MQ性质

Diamond的使用场景决定了它应该具有一点MQ的性质,从下面两点来看:

  • 配置项变更需要通知。
  • 通知给谁?逻辑上是应该有一个订阅关系的。

Diamond是怎么解决这两个问题的?从MQ的角度来看,Diamond使用pull消息的方式把两个问题都解决了。用pull消息的方式,逻辑上来看就是把订阅关系维护在Client端,Client关心哪些配置项变更就自己去服务器上面拉。但拉的方式当然也有它的缺点,需要去轮询,一定程度上造成资源浪费,为了减小这种浪费,md5字段派上用场了,Client通过只与DiamondServer对比content的md5来发现变更,如果两边md5不一致则说明配置项有变更,这时再去调接口取回变更后的content即可。

参考资料

  • http://jm-blog.aliapp.com/?p=1588
  • http://jm-blog.aliapp.com/?p=1592
  • http://jm-blog.aliapp.com/?p=1606
  • http://jm-blog.aliapp.com/?p=1617
0 0
原创粉丝点击