多存储后端

多存储后端
某些使用场景下,需要 Seafile 服务可以支持多个存储后端,例如:
  1. 要将不同的文件类型存储到不同的存储后端。例如,普通文件可以存储到主存储(disks, SSD);文档文件可以存储到 “冷存储”(其他存储系统)。
  2. 结合多个存储后端来扩展存储的可扩展性。例如,单独使用一个 NFS 挂载卷时可能会受到大小限制;单独使用一个 S3 后端存储时,当对象数量变得很大时,Ceph RGW 的性能可能会受到很大影响。
在 Seafile 中,以资料库为单位,将数据分散存储到多个存储后端中。在同一个资料库中的所有数据将被存储到同一个存储后端。每个资料库和存储后端之间的映射关系存储在数据库中。根据使用情况选择不同的映射策略。
为了使用该功能,您需要:
  1. 在 seafile.conf 中定义存储后端。
  2. 在 seahub_settings.py 中开启多存储后端功能,并选择一个映射策略。
  3. .env 中设置 SEAF_SERVER_STORAGE_TYPE=multiple。( 从13.0版本开始需设置此项
定义存储后端
在 Seafile 中,每一个存储后端都由一个 "storage class" 代表。存储后端由以下信息定义:
  • storage_id :用来定义存储后端的内部 ID 字符串,对用户不可见。例如:'primary storage'。
  • name :用户可见的存储名称。
  • is_default :定义该存储是否是默认的。这个选项在两种情况下起作用:
    • 如果选用“用户选择”的映射策略,如果用户没有给一个资料库选择存储后端,那么该资料库使用这个默认后端。
    • 对于其他的映射策略,在启用多存储后端功能之前创建的资料库,它们的存储后端会使用这个默认后端。这是因为这些现存的资料库,并没有将存储后端信息保存到数据库中。
  • commits :该存储后端中,用来存放 commit 对象的存储位置。它可以是任何 Seafile 支持的存储,比如:文件系统、S3 或者 ceph。
  • fs :该存储后端中,用来存放 fs 对象的存储位置。它可以是任何 Seafile 支持的存储,比如:文件系统、S3 或者 ceph。
  • blocks :该存储后端中,用来存放 block 对象的存储位置。它可以是任何 Seafile 支持的存储,比如:文件系统、S3 或者 ceph。
commit, fs, 和 blocks 能够被存储在不同的存储中。这为定义存储后端提供了最为灵活的方式。
在 Seafile 6.3 之前的版本中,不支持多个存储后端。您必须明确地启用这个新功能,并使用与以前定义存储后端不同的语法格式定义存储后端。
首先,你必须在 seafile.conf 中启用这个功能:
            
                
                
[storage]
enable_storage_classes = true
storage_classes_file = /opt/seafile/conf/seafile_storage_classes.json
            
                
                
#如果您使用的是redis缓存,请使用如下配置(13.0可以不用配)
[redis]
redis_host = 127.0.0.1
redis_port = 6379
max_connections = 100

#假如您使用的是memcached缓存服务,请使用如下配置
[memcached]
memcached_options = --SERVER=<the IP of Memcached Server> --POOL-MIN=10 --POOL-MAX=100

  • enable_storage_classes :设置为 True,开启多存储后端功能;接下来你必须在下一个配置项指定的 JSON 文件中定义出这些存储后端。
  • storage_classes_file :指定包含有存储后端定义的 JSON 文件的位置。
JSON 文件是一个对象数组。每个对象定义一个存储后端。定义中的字段对应于我们需要为存储后端指定的信息。
变量
描述信息
storage_id
用于标识存储类的唯一内部字符串 ID。它对用户不可见。例如,“主存储”。
name
存储类的用户可见名称。
is_default
指示此存储类是否为默认存储类。
commits
用于存储此类的commits对象的存储。
fs
用于存储此类的fs对象的存储。
blocks
用于存储此类的block对象的存储。
is_default 在两种情况下有效:
  • 当用户未选择映射策略并且可以将此存储类用于资料库时;
  • 对于其他映射策略,仅当您在启用多存储后端功能之前已有资料库时,该选项才会生效,该功能将自动映射到默认存储后端。
下面是一个例子:
            
                
                
[
{
"storage_id": "hot_storage",
"name": "Hot Storage",
"is_default": true,
"commits": {
"backend": "s3",
"bucket": "seafile-commits",
"key": "<your key>",
"key_id": "<your key id>"
},
"fs": {
"backend": "s3",
"bucket": "seafile-fs",
"key": "<your key>",
"key_id": "<your key id>"
},
"blocks": {
"backend": "s3",
"bucket": "seafile-blocks",
"key": "<your key>",
"key_id": "<your key id>"
}
},
{
"storage_id": "cold_storage",
"name": "Cold Storage",
"is_default": false,
"fs": {
"backend": "fs",
"dir": "/share/seafile/seafile-data" // /opt/seafile/seafile-data for binary-install Seafile
},
"commits": {
"backend": "fs",
"dir": "/share/seafile/seafile-data"
},
"blocks": {
"backend": "fs",
"dir": "/share/seafile/seafile-data"
}
},
{
"storage_id": "swift_storage",
"name": "Swift Storage",
"fs": {
"backend": "swift",
"tenant": "<your tenant>",
"user_name": "<your username>",
"password": "<your password>",
"container": "seafile-commits",
"auth_host": "<Swift auth host>:<port, default 5000>",
"auth_ver": "v2.0"
},
"commits": {
"backend": "swift",
"tenant": "<your tenant>",
"user_name": "<your username>",
"password": "<your password>",
"container": "seafile-commits",
"auth_host": "<Swift auth host>:<port, default 5000>",
"auth_ver": "v2.0"
},
"blocks": {
"backend": "swift",
"tenant": "<your tenant>",
"user_name": "<your username>",
"password": "<your password>",
"container": "seafile-commits",
"auth_host": "<Swift auth host>:<port, default 5000>",
"auth_ver": "v2.0",
"region": "RegionTwo"
}
},
{
"storage_id": "ceph_storage",
"name": "ceph Storage",
"fs": {
"backend": "ceph",
"ceph_config": "/etc/ceph/ceph.conf",
"pool": "seafile-fs"
},
"commits": {
"backend": "ceph",
"ceph_config": "/etc/ceph/ceph.conf",
"pool": "seafile-commits"
},
"blocks": {
"backend": "ceph",
"ceph_config": "/etc/ceph/ceph.conf",
"pool": "seafile-blocks"
}
}
]
如上所示: commits fs blocks 信息的语法格式与 seafile.conf 中定义的 [commit_object_backend] , [fs_object_backend] [block_backend] 语法格式相似。
如果你是用文件系统作为 commits fs blocks 的存储位置,您必须明确地提供"seafile-data"目录的路径。这些对象将会被存储在这个路径下的 storage/commits , storage/fs , storage/blocks 中。
注意 :一般的文件系统,S3 和 Swift 后端是支持的,7.0.14 版本起支持 Ceph/RADOS。
资料库映射策略
资料库映射策略决定了资料库使用的存储后端。目前我们为3个不同的用例提供3个策略。资料库的存储后端被创建和存储在一个数据表中。如果之后再更改映射策略各资料库对应的存储后端将不会改变。
选择映射策略之前,你需要在 seahub_settings.py 开启该功能:
            
                
                
ENABLE_STORAGE_CLASSES = True
用户选择
该策略需要用户在创建新资料库的时候选择存储后端。用户可以选择定义在 JSON 文件中的任何一个存储后端。
如果要使用该策略,需要在 seahub_settings.py 中添加以下配置:
            
                
                
STORAGE_CLASS_MAPPING_POLICY = 'USER_SELECT'
如果你开启了 STORAGE_CLASSES,但没有在 seahub_settings.py 中明确定义 STORAGE_CLASS_MAPPING_POLIICY ,则默认使用“用户选择”策略。
基于角色映射
您还可以根据用户的角色配置用户可使用的存储后端。
seahub_settings.py 中加一个新的配置项 storage_ids 到角色配置段中,给每一个角色分配存储后端。如果给某个角色只分配了一个存储后端,这个角色下的用户将不能选择其他存储后端给资料库使用。否则,如果分配了多个存储后端,用户在创建资料库时可以从中选择一个存储后端。如果没有为角色分配任何存储后端,将使用JSON文件中指定的默认后端。
这里有一个简单的 seahub_settings.py 中的配置,使用该策略:
            
                
                
ENABLE_STORAGE_CLASSES = True
STORAGE_CLASS_MAPPING_POLICY = 'ROLE_BASED'
ENABLED_ROLE_PERMISSIONS = {
'default': {
'can_add_repo': True,
'can_add_group': True,
'can_view_org': True,
'can_use_global_address_book': True,
'can_generate_share_link': True,
'can_generate_upload_link': True,
'can_invite_guest': True,
'can_connect_with_android_clients': True,
'can_connect_with_ios_clients': True,
'can_connect_with_desktop_clients': True,
'storage_ids': ['old_version_id', 'hot_storage', 'cold_storage', 'a_storage'],
},
'guest': {
'can_add_repo': True,
'can_add_group': False,
'can_view_org': False,
'can_use_global_address_book': False,
'can_generate_share_link': False,
'can_generate_upload_link': False,
'can_invite_guest': False,
'can_connect_with_android_clients': False,
'can_connect_with_ios_clients': False,
'can_connect_with_desktop_clients': False,
'storage_ids': ['hot_storage', 'cold_storage'],
},
}
基于资料库 ID 的映射
这个策略根据资料库的ID映射到存储后端。资料库的ID是UUID。这样,系统中的数据就可以在存储后端之间均匀地分配。
注意,这个策略并不是设计成完整的分布式存储解决方案。它不处理资料库数据在各存储后端之间的自动迁移。如果需要向配置文件添加更多的存储后端,则现有资料库将保留在它们的原始存储中。新的资料库可以在新的存储后端之间分布。您仍然需要在开始时计划系统的总存储容量。
要使用该策略,先在 seahub_settings.py 中添加以下配置项:
            
                
                
STORAGE_CLASS_MAPPING_POLICY = 'REPO_ID_MAPPING'
然后可以在 JSON 文件中的存储后端中添加 for_new_library 选项来存储新的资料库:
            
                
                
[
{
"storage_id": "new_backend",
"name": "New store",
"for_new_library": true,
"is_default": false,
"fs": {
"backend": "fs",
"dir": "/storage/seafile/new-data"
},
"commits": {
"backend": "fs",
"dir": "/storage/seafile/new-data"
},
"blocks": {
"backend": "fs",
"dir": "/storage/seafile/new-data"
}
}
]
多存储后端数据迁移
运行 migrate-repo.sh 脚本可以实现在不同存储后端之间迁移资料库数据。
            
                
                
./migrate-repo.sh [repo_id] origin_storage_id destination_storage_id
  • repo_id : 迁移的资料库 id
  • origin_storage_id : 迁移的源 storage id
  • destination_storage_id : 迁移的目标 storage id
repo_id 参数是可选的,若不指定,所有的资料库都会被迁移。
运行迁移脚本前,可以设置 OBJECT_LIST_FILE_PATH 环境变量指定一个路径前缀存储迁移完成的对象。 比如:
            
                
                
export OBJECT_LIST_FILE_PATH=/opt/test
这样会在指定的路径(/opt)创建三个文件: test_4c731e5c-f589-4eaa-889f-14c00d4893cb.fs test_4c731e5c-f589-4eaa-889f-14c00d4893cb.commits test_4c731e5c-f589-4eaa-889f-14c00d4893cb.blocks
设置 OBJECT_LIST_FILE_PATH 环境变量有两个好处:
  1. 如果迁移的资料库非常大,需要多次运行迁移脚本,设置此环境变量可以略过之前迁移完成的对象。
  2. 迁移完成后,如果你需要删除源存储中的对象,必须设置此环境变量。
删除指定存储后端某资料库中所有的对象
运行 remove-objs.sh 脚本(迁移前,需要设置 OBJECT_LIST_FILE_PATH 环境变量)删除指定存储后端某资料库所有的对象。
            
                
                
./remove-objs.sh repo_id storage_id
  • repo_id : 资料库 id
  • storage_id : 指定的存储后端 storage id
迁移整个存储后端
当您需要把其中一个存储后端上的所有数据,迁移到一个新存储后端上时,可以按照以下步骤执行:
  1. 将新的存储后端加入 seafile_storage_classes.json 文件中。
  2. 禁用旧的存储后端,以避免迁移过程中仍有新的资料库被写入。禁用方式取决于您的映射策略:
    • 如果基于用户角色映射,可以将旧的存储后端从 seahub_settings.py 中去掉。同时可以用新的存储后端替代旧的存储后端。
    • 如果基于资料库 ID 映射,可以将旧的存储后端的 for_new_library 选项设置为 false。同时可以用将新的存储后端配置为 for_new_library = true
  3. migrate-repo.sh 并不指定资料库 ID 来迁移整个存储后端的数据。