Tair是由淘宝开发的一个key/value存储系统。
参考:http://rdc.taobao.com/blog/cs/?p=302
在数据分配方面,Tair使用了对照表,对照表由于数据路由功能,由配置服务器(configserver负责维护),configserver周期性的初始化各个数据节点的信息,并通过Heartbeat来管理数据节点的状态。对照表通常包含多个slot(应远大于数据节点的个数,以便将slot尽可能均匀的分配给数据节点)。
如下图所示,对照表包含6个slot,其中0、2、4号slot被分配给了数据节点192.168.10.1;而1、3、5号存储节点被分配给了192.168.10.2。当客户端存储key/value时,通过key计算出一个hash值,并对对照表的总slot数取余,所得的值即为key应该被存储的slot。
0 | 192.168.10.1 |
1 | 192.168.10.2 |
2 | 192.168.10.1 |
3 | 192.168.10.2 |
4 | 192.168.10.1 |
5 | 192.168.10.2 |
Tair用户和configserver的交互主要是为了获取数据分布的对照表,当client获取到对照表后,会cache这张表,然后通过查这张表决定数据存储的节点,所以请求不需要和configserver交互,这使得Tair对外的服务不依赖configserver,所以它不是传统意义上的中心节点,configserver也不会成为集群的瓶颈。
configserver维护的对照表有一个版本号,每次新生成表,该版本号都会增加。当有数据节点状态发生变化(比如新增节点或者有节点不可用了)时,configserver会根据当前可用的节点重新生成对照表,并通过数据节点的心跳,将新表同步给数据节点。
当客户端请求数据节点时,数据节点每次都会将自己的对照表的版本号放入response中返回给客户端,客户端接收到response后,会将数据节点返回的版本号和自己的版本号比较,如果不相同,则主动和configserver通信,请求新的对照表。故客户端也不需要和configserver保持心跳,以便及时的更新对照表。这使得在正常的情况下,客户端不需要和configserver通信,即使configserver不可用了,也不会对整个集群的服务造成大的影响。
当有新的节点加入时,如192.168.10.3,configserver会构造新的对照表,具体的做法为:
1. 在新增节点(有机器不可用)时,会存在三张表:新增前的对照表,新增后的对照表和迁移表,此时客户端取到的还是老的表。当按照新旧对照表完成迁移后,暴露给客户端的表才会被更新为新表。
2. 对照表的更新算法是:计算根据新的节点数,每个节点需要负责的桶数目(假设为Y),然后针对每个原有的节点,保留原来负责的X个桶(假设某节点原来负责的桶数为X,则空余出了X-Y个桶),然后把空余的桶交由新节点负责。
更新后的对照表可能类似于:
0 | 192.168.10.1 |
1 | 192.168.10.2 |
2 | 192.168.10.1 |
3 | 192.168.10.2 |
4 | 192.168.10.3 |
5 | 192.168.10.3 |
根据新旧对照表,Tair对某些key/value需要进行数据迁移操作,如将原来哈希结果为4或5的key/value迁移到192.168.10.3,为了加速迁移,可将key/value在数据节点中按照hash值聚类存放,这样迁移操作就能迅速找到需要被迁移的key/value。
key/value存储系统通常使用余数分步法(节点数取余)对key进行分布存储,一旦数据节点发生变化,key就需要重新进行分布,Tair通过维护对照表来实现数据的重新分布,类似的机制还被应用在FastDHT(http://code.google.com/p/fastdht/)。