完成了配置路由服务器之后,我们来到了对存储服务器的重构
在我们加入配置服务器组之后,我们发现我们的kvserver,也就是存储服务器还是单点的:
同样,我们可以借助之前实现的raft对单点进行拓展,我们可以设置三组分片存储服务器,每组三个,实现三副本,如下图:
这里我们引入几个概念:
- 资源池和可用区(故障隔离域)的概念。同一个资源池内的机型同构(简化资源调度逻辑,比如相同的磁盘数量和磁盘大小)。不同的业务可以使用不同的资源池,做到存储层资源隔离
- 不同交换机下的节点定义为不同的可用区(故障隔离域)。可用区之间实现交换机级别的隔离
- 每个存储集群由一个或者多个资源池组成。资源池之间IO隔离,资源池内部机型同构
- 每个资源池内部,由多个可用区组成。每个可用区由若干台服务器(存储节点)组成
简单来说,就是对于属于一组的分片存储服务器,为避免大规模宕机,它们应该处于不同的可用区当中,但是处于同于个资源池内,因为它们的机型同构(硬件配置相同)。
这里同学们理解即可,对于不是生产场景的系统,没有必要去严格划分。
除了将存储单点拓展为多点之外,我们对存储节点自身的架构也稍加探讨:
在之前添加配置服务器组的时候,我们说过,存储服务器本身也有一份配置,本身也维护了一张哈希槽表,也就是说,此时存储服务器架构为:
- 从上到下分为RPC层,shared层,引擎层
- RPC层负责通信
- shared层将RPC请求转化为对具体的某一个bucket的读写操作
- engine层负责将请求转化为对磁盘的请求
那么在存储时,我们的方案是:
- 请求进入RPC层之后, 根据shardid 进行分发,获取到对应的shard实例(句柄)
- shard使用key和value操作engine层
- 一个节点(或者一块磁盘)公用一个engine,使用shardID作为key前缀,用于区分不同的shard(在迁移的时候,可以使用shardID为前缀扫描属于该shard的所有的key和value)
除此之外,我们可以采用一个bucket对应一个engine,而不是之前的全局公用,这样不仅实现更简单,同时,数据迁移时我们直接对整个engine进行拷贝即可,不再需要扫描了