在上期,我们提到,如果我们想把对象存储用在生产环境,仅仅在单AZ内部实现三副本只能保证数据99.9999999%的持久性。如果我们还期望业务的可用性达到99.999%以上,还需要实现对象存储的跨AZ部署,也就是所谓的“同城双活”。
由于对象存储是基于HTTP的,而HTTP是基于IP的,所以,我们首先要解决HTTP Server的双活问题。
让我们举一个栗子。
如果用户Rhino想访问oss.por***b.com的存储桶里面的一个对象,域名为:
maz.por***b.com
解析得到IP地址为61.83.133.6
访问路径如图所示:
然而,当主AZ不可用时,需要通过一种什么机制将Rhino的访问切换到另一个AZ呢?
对于这个图,熟悉云计算网络的同学一定会想到,为了避免单点故障,图中的http server实际上并不是一台真实的服务器,而是由VM或容器构成的集群。因此,实际每个AZ的架构实现,是这样的——
(Metadata数据库也可以为分布式的,在此不画出)
那么,我们只要让LB能够跨AZ,就可以让http server的HA跨AZ!
这并不是一件难以实现的事情。
如图,我们可以这么做:
Rhino输入oss.por***b.com这个域名的时候,DNS会解析返回61.83.133.6(主AZ的VIP),一旦主AZ整体不可用,或主AZ内部的Http server (可以称为RS,Real Server),oss.por***b.com会被解析为106.15.220.171 (双活AZ的VIP)。Rhino的访问被双活AZ所接管,从而实现了HTTP层的双活。
大家可能会问一个问题:如果Rhino在上传(put)或下载(get)一个文件的时候,主AZ整体断电呢?
我们回想一下我们之前学习过的《一蓑烟雨任平生 明月千里共婵娟》的内容,里面提到,对象存储之所以使用http协议访问,其中一个重要的好处是,http是天然支持断点续传的。因此,Rhino只需要重新发起断点续传,就可以从上一次传输终端的地方重新开始上传或下载文件了。
当然,我们如果期望实现对象存储在两个AZ都是可用的,还需要让它实现一个功能——
我们在前面提过,对象存储和其他分布式存储一样,一般使用三副本保障数据持久性。但是,对于双AZ的情况呢?
如图,我们可以将三副本机制做一定的修改:
当HTTP Server收到建立一个对象(http put)请求的时候,将对象进行切片,并在一致性哈希环上找到它的主副本所在的物理节点和物理磁盘,以及其他两个从副本所在的物理节点和磁盘。
我们只需要修改从副本分配策略,让两个从副本必须有一个在另一个AZ,就可以让三副本跨AZ分布了。
这不是很好吗?
正如鲁迅指出的那样,事实总是和理想有一定的差距。
当主AZ全部失效(如整个AZ断网或断电)时——
如图,主AZ的两个副本都不可用了,只有从AZ的一个副本,如李密《陈情表》里面描述的:“外无期功强近之亲,内无应门五尺之童。茕(qiong)茕(qiong)孑(jie)立,形影相吊。”
显然,这是不符合分布式系统设计原则的。如果这一个独苗再有意外,将导致数据不可用,我们向客户承诺的SLA也就无从谈起。
因此,工程师们开动脑筋,对多副本机制做了一点微小的贡献……
请看下期分解。