Swift的存储策略Storage Policies

对象最终是以二进制文件的方式存储在物理节点上,并且Swift通过创建多个副本等冗余技术达到极高的数据持久性,但是副本的采用是以牺牲更多的存储空间为代价的,那么这里的另外一个问题是能否通过其他的技术来减少存储空间的占用。
Swift采用EC(Erasure Coding)技术来减少存储空间
EC技术将数据分块,再对每一个块加入编码,从而减少对存储空间的需求,并且还可以在某一块数据被损坏的情况的,根据其他块的数据将其恢复。其实是通过消耗更多计算和网络资源来减少对存储资源的消耗。
为了让EC和现有的基于副本的实现并存,Storage Policies应运而生。一个Storage Policies可以简单理解为一种存储方式或策略,比如要求为每一个Partition创建2个副本。
通过为每一个Storage Policy配备一个Object Ring,Swift实现了:针对不同Storage Policy的Object,采取不同额存储方式。
EC的实现并没有在Juno版本发布,但是可以说EC是Storage Policies提出的主要原因和动力,Storage Policies也被设计成一种通用的实现。
举例来说,一个Swift的部署可能会存在两种Storage Policy:一个要求每一个Partition都有3个副本,另外一个只要求2个副本,后者服务的级别比较低。另外还可以存在一个Storage Policy包含SSD硬件设备,从而使得应用这个Storage Policy的用户都能得到较高的存储效率。
使用Storage Policies的核心问题就是如何确认一个Object的Storage Policy。我们知道Swift按照Account、Container和Object三个层次来组织对象,一个新创建的Object必然包含在一个Container中。Swift要求每一个Container都有和它相关联的一个Storage Policy。这种关联关系在Container创建时确定,并且不可改变。这样,在某一个Container里面创建的Object都将采用这个Container所关联的Storage Policy。
我们可以通过/etc/swift.conf文件来配置Storage Policies:
#Storage Policies指定了关于如何存储和对待Object的一些属性。
#每一个Container都与一个Storage Policy相关联。
#这种关联方式是通过为每一个Container都指定一个Storage Policy的名字来实现的。
#Storage Policy的名字区分大小写字母。
#Storage Policy的索引(index)在配置文件中每一个Storage Policy section的header部分指定。
#索引被内部代码所使用。
#索引为0的Storage Policy预留给在Storage Policy出现之前创建的Container使用。
#可以为索引为0的Storage Policy指定一个名字以便在元数据中使用。
#但是索引为0的Storage Policy的Ring文件的名字永远是"object.ring.gz"
#这是为了兼容在Storage Policy出现之前创建的Container。
#如果没有指定Storage Policy,那么就有一个名为"Policy-0",索引为0的Storage Policy会被自动创建。
#使用"default"关键字指定默认的Storage Policy。
#在创建新的Container时,如果没有指定Storage Policy,那么就使用默认的Storage Policy与其关联。
#如果没有指定默认Storage Policy,则将索引为0的Storage Policy视为默认值。
#如果创建了多个Storage Policy,则必须指定一个索引为0的Storage Policy以及一个默认的Storage Policy。
[storage-policy:0]
name = Policy-0
default = yes
#下面的section示范如何创建一个名字为"silver"的Storage Policy
#每一个Storage Policy都有一个Object Ring。
#创建这个Ring时所指定副本个数就是这个Storage Policy的副本个数。
#在这个例子中,"silver"可以有一个比上述"Policy-0"高的或者低的副本数量。
#这个Storage Policy的Ring的名字是"object-1.ring.gz"
#如果把"silver"作为默认的Storage Policy,那么当一个Container被创建时,
#如果没有指定Storage Policy,那么这个Container就会与"silver"相关联。
#但是如果swift访问的是一个在Storage Policy出现之前创建的Container,
#那么该Container所关联的依然是索引号为0的Storage Policy
#[storage-policy:1]
#name = silver
以Policy-0为例,”[storage-policy:0]”说明这个Storage Policy的索引(index)是0,Storage Policy的内部实现是用索引而非名字来检索。
name = Policy-0说明这个Storage Policy的名字叫做Policy-0。
我们看到在定义了Policy-0之后,在注释里面又定义了一个名字为”silver”、索引号为1的Storage Policy。
Storage Policy和Object Ring之间1:1映射是通过索引号来建立的。索引号为0的Storage Policy所对应的Ring文件名字是object.ring.gz。索引号为1的Storage Policy所对应的Ring文件名字是object1.ring.gz,依次类推。
那么如何在创建一个Container的时候指定使用何种Storage Policy呢?这通过一个特殊的Request head——“X-Storage-Policy”来实现。如果通过“X-Storage-Policy”指定了使用的Storage Policy的名字,那么这个Container就和该Storage Policy相关联。否则就关联到默认的Storage Policy上去。
Storage Policy的数据结构为类swift.common.storage_policy.StoragePolicy,我们并不需要通过实例化类StoragePolicy来创建Storage Policy,而是推荐使用swift.common.storage_policy. reload_storage_policies()函数从Swift配置文件/etc/swift/swift.conf中加载Storage Policy。
StoragePolicy最重要的成员就是object_ring,也就是这个Storage Policy所对应的Object Ring。object_ring可以在初始化的时候作为参数传进来,也可以通过调用load_ring()函数从一个Ring文件里读取出来。
#swift/common/storage_policy.py
class StoragePolicy(object):
    def __init__(self, idx, name='', is_default=False, is_deprecated=False,
                 object_ring=None):
        try:
            self.idx = int(idx)
        except ValueError:
            raise PolicyError('Invalid index', idx)
        if self.idx < 0:
            raise PolicyError('Invalid index', idx)
        if not name:
            raise PolicyError('Invalid name %r' % name, idx)
        if not all(c in VALID_CHARS for c in name):
            raise PolicyError('Names are used as HTTP headers, and can not '
                              'reliably contain any characters not in %r. '
                              'Invalid name %r' % (VALID_CHARS, name))
        if name.upper() == LEGACY_POLICY_NAME.upper() and self.idx != 0:
            msg = 'The name %s is reserved for policy index 0. ' \
                'Invalid name %r' % (LEGACY_POLICY_NAME, name)
            raise PolicyError(msg, idx)
        self.name = name
        self.is_deprecated = config_true_value(is_deprecated)
        self.is_default = config_true_value(is_default)
        if self.is_deprecated and self.is_default:
            raise PolicyError('Deprecated policy can not be default. '
                              'Invalid config', self.idx)
        self.ring_name = _get_policy_string('object', self.idx)
        self.object_ring = object_ring
    def __int__(self):
        return self.idx
    def load_ring(self, swift_dir):
        if self.object_ring:
            return
        self.object_ring = Ring(swift_dir, ring_name=self.ring_name)
那么写在Swift配置文件中的Storage Policy又是什么时候加载到Swift的运行系统去的呢?这个操作在Proxy Server中完成。
swift.proxy.server从swift.common.storage_policy中import了全局变量POLICIES,并且在swift.proxy.server.Application类的__init__()函数中进行了加载。
其本质就是为每一个Storage Policy加载相应的Ring。
# swift/proxy/server.py
from swift.common.storage_policy import POLICIES
class Application(object):
    def __init__(self, conf, memcache=None, logger=None, account_ring=None,
                 container_ring=None):
        # ensure rings are loaded for all configured storage policies
        for policy in POLICIES:
            policy.load_ring(swift_dir)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值