适用于 SUSE Enterprise Storage 6

14 缓存分层

缓存层是在客户端与标准存储之间实施的附加存储层。该层用于加快访问低速硬盘中存储的存储池以及纠删码存储池的速度。

通常,缓存分层涉及到创建一个由相对快速的存储设备(例如 SSD 驱动器)组成且配置为充当缓存层的存储池,以及一个由较慢但较便宜的设备组成且配置为充当存储层的后备存储池。缓存池大小通常是存储池大小的 10-20%。

14.1 分层存储的相关术语

缓存分层识别两种类型的池:缓存池存储池

提示
提示

有关池的一般信息,请参见第 11 章 “管理存储池

存储池

在 Ceph 存储集群中存储一个对象的多个副本的标准副本存储池,或纠删码存储池(请参见第 13 章 “纠删码存储池)。

存储池有时称为“后备”存储或“冷”存储。

缓存池

标准副本存储池,存储在相对较小但速度较快的存储设备上,在 CRUSH 索引中具有自己的规则组。

缓存池也称为“热”存储。

14.2 需考虑的要点

缓存分层可能会降低特定工作负载的集群性能。以下几点指出了您需要考虑的有关缓存分层的几个方面:

  • 取决于工作负载:缓存能否提高性能取决于工作负载。由于将对象移入或移出缓存会耗费资源,因此,如果大多数请求只涉及到少量的对象,则使用缓存可能更高效。缓存池的大小应该足以接收工作负载的工作集,以避免性能大幅波动。

  • 难以进行基准测试:大多数性能基准测试可能会反映使用缓存分层时性能会较低。原因在于,这些基准测试请求了大量的对象,而缓存的“预热”需要较长时间。

  • 性能可能较低:对于不适合进行缓存分层的工作负载而言,其性能往往比不启用缓存分层的普通副本存储池更低。

  • librados 对象枚举:如果应用直接使用 librados 并依赖于对象枚举,则缓存分层可能无法按预期工作(对于对象网关、RBD 或 CephFS 而言,这不会造成问题)。

14.3 何时使用缓存分层

在以下情况下,请考虑使用缓存分层:

  • 您的纠删码存储池存储在 FileStore 上,并且您需要通过 RADOS 块设备访问它们。有关 RBD 的详细信息,请参见第 12 章 “RADOS 块设备

  • 您的纠删码存储池存储在 FileStore 上,并且您需要通过 iSCSI 访问它们。有关 iSCSI 的详细信息,请参见第 18 章 “Ceph iSCSI 网关

  • 您的高性能存储数量有限,而低性能存储众多,您需要更快地访问存储的数据。

14.4 缓存模式

缓存分层代理可处理缓存层与后备存储层之间的数据迁移。管理员可以配置如何进行这种迁移。主要有两种方案:

写回模式

在写回模式下,Ceph 客户端将数据写入缓存层,并从缓存层接收确认响应。一段时间后,写入缓存层的数据将迁移到存储层,并从缓存层中清除。从概念上讲,缓存层叠加在后备存储层的“前面”。当 Ceph 客户端需要驻留在存储层中的数据时,缓存分层代理会在读取时将数据迁移到缓存层,然后,数据将发送到 Ceph 客户端。因此,在数据变为不活跃状态前,Ceph 客户端可以使用缓存层执行 I/O。这种做法非常适合可变的数据,例如,编辑的照片或视频,或事务数据。

只读模式

在只读模式下,Ceph 客户端将数据直接写入后备层。在读取时,Ceph 将请求的对象从后备层复制到缓存层。过时对象将会根据定义的策略从缓存层中删除。这种做法非常适合不可变的数据,例如,在社交网络上呈现的图片或视频、DNA 数据或 X 光成像,因为从可能包含过时数据的缓存池中读取数据会导致一致性很差。不要对可变的数据使用只读模式。

14.5 纠删码存储池和缓存分层

纠删码存储池需要的资源比副本存储池多。要克服这些限制,建议在纠删码存储池的前面设置一个缓存层。使用 FileStore 时需要这么做。

例如,如果 hot-storage 存储池由高速存储设备构成,则可使用以下命令来加速第 13.3 节 “纠删码配置”中创建的ecpool

cephadm@adm > ceph osd tier add ecpool hot-storage
cephadm@adm > ceph osd tier cache-mode hot-storage writeback
cephadm@adm > ceph osd tier set-overlay ecpool hot-storage

这会将充当 ecpool 的一个层的 hot-storage 存储池置于写回模式,以便每次在 ecpool 中写入和读取数据时实际使用的都是热存储,从而受益于热存储的灵活性和速度。

cephadm@adm > rbd --pool ecpool create --size 10 myvolume

有关缓存分层的详细信息,请参见第 14 章 “缓存分层

14.6 设置示例分层存储

本节举例说明如何在标准硬盘(冷存储)的前面设置一个高速 SSD 缓存层(热存储)。

提示
提示

下面的示例仅用于说明目的,其中的设置包含单个 Ceph 节点上存在的 SSD 部件的一个根及一条规则。

在生产环境中,集群设置通常包含热存储以及混合节点(配有 SSD 和 SATA 磁盘)的更多根项和规则项。

  1. 创建两个额外的 CRUSH 规则“replicated_ssd”和“replicated_hdd”,前者用于较快的 SSD 缓存设备类型,后者用于较慢的 HDD 设备类型:

    cephadm@adm > ceph osd crush rule create-replicated replicated_ssd default host ssd
    cephadm@adm > ceph osd crush rule create-replicated replicated_hdd default host hdd
  2. 将所有现有存储池都切换为使用“replicated_hdd”规则。这样可防止 Ceph 将数据存储到新添加的 SSD 设备:

    cephadm@adm > ceph osd pool set POOL_NAME crush_rule replicated_hdd
  3. 使用 DeepSea 将该计算机转变成 Ceph 节点。根据第 2.1 节 “添加新的集群节点”中所述安装软件并配置主机计算机。我们假设此节点名为 node-4。此节点需要有 4 个 OSD 磁盘。

    [...]
    host node-4 {
       id -5  # do not change unnecessarily
       # weight 0.012
       alg straw
       hash 0  # rjenkins1
       item osd.6 weight 0.003
       item osd.7 weight 0.003
       item osd.8 weight 0.003
       item osd.9 weight 0.003
    }
    [...]
  4. 编辑热存储池(已映射到基于高速 SSD 驱动器的 OSD)的 CRUSH 索引。定义另一个包含 SSD 的根节点的层次结构(命令为“root ssd”)。此外,请为 SSD 更改权重并添加一个 CRUSH 规则。有关 CRUSH 索引的详细信息,请参见第 9.5 节 “CRUSH 索引操作”

    使用 getcrushmapcrushtool 等命令行工具直接编辑 CRUSH 索引:

    cephadm@adm > ceph osd crush rm-device-class osd.6 osd.7 osd.8 osd.9
    cephadm@adm > ceph osd crush set-device-class ssd osd.6 osd.7 osd.8 osd.9
  5. 创建用于缓存分层的热存储池。对该池使用新的“ssd”规则:

    cephadm@adm > ceph osd pool create hot-storage 100 100 replicated ssd
  6. 使用默认的“replicated_ruleset”规则创建冷存储池:

    cephadm@adm > ceph osd pool create cold-storage 100 100 replicated replicated_ruleset
  7. 然后,设置缓存层的过程涉及到将后备存储池关联到缓存池,在本例中,需要将冷存储(即存储池)关联到热存储(即缓存池):

    cephadm@adm > ceph osd tier add cold-storage hot-storage
  8. 要将缓存模式设置为“写回”,请执行以下命令:

    cephadm@adm > ceph osd tier cache-mode hot-storage writeback

    有关缓存模式的详细信息,请参见第 14.4 节 “缓存模式”

    写回缓存层叠加在后备存储池上,因此需要执行一个额外的步骤:必须将来自存储池的所有客户端流量定向到缓存池。例如,要将客户端流量直接定向到缓存池,请执行以下命令:

    cephadm@adm > ceph osd tier set-overlay cold-storage hot-storage

14.7 配置缓存层

可以使用多个选项来配置缓存层。使用以下语法:

cephadm@adm > ceph osd pool set cachepool key value

14.7.1 命中集

使用命中集参数可以优化缓存池。Ceph 中的命中集通常是布隆过滤器,提供节省内存用量的方式来跟踪已存放于缓存池的对象。

命中集是一个位数组,用于存储针对对象名称应用的一组哈希函数的结果。最初,所有的位都设为 0。将对象添加到命中集后,该对象的名称将经过哈希处理,结果将映射在命中集中的不同位置,那时,位的值便会设置为 1

为了确定某个对象是否存在于缓存中,将会再次对对象名称进行哈希处理。如果有任何位是 0,则表示该对象肯定不在缓存中,需要从冷存储中检索它。

不同对象的结果可能会存储在命中集的同一位置。在巧合的情况下,可能所有位都是 1,而对象却不在缓存中。因此,处理布隆过滤器的命中集只能确定某个对象是否一定不在缓存中,需要从冷存储检索它。

一个缓存池可以使用多个命中集来跟踪各时间段的文件访问。设置 hit_set_count 定义所用的命中集数量,hit_set_period 定义每个命中集已使用了多长时间。该期限过期后,将使用下一个命中集。如果用尽了命中集,将会释放最旧命中集的内存,并创建新的命中集。将 hit_set_counthit_set_period 的值相乘可定义已跟踪对象访问的整个时间范围。

包含 3 个存储对象的布隆过滤器
图 14.1︰ 包含 3 个存储对象的布隆过滤器

与哈希处理对象的数量相比,基于布隆过滤器的命中集非常地节省内存用量。只需使用不到 10 个位即可将误报率降低到 1% 以下。可以使用 hit_set_fpp 定义误报率。Ceph 可根据归置组中的对象数量及误报率自动计算命中集的大小。

可以使用 min_write_recency_for_promotemin_read_recency_for_promote 限制缓存池中所需的存储。如果将值设置为 0,则所有对象在被读取或写入后,会立即提升到缓存池,并且在被赶出之前会一直保持这种模式。使用大于 0 的任何值可定义在其中搜索对象的命中集(已按期限排序)的数量。如果在某个命中集中找到了该对象,会将该对象提升到缓存池。请记住,对对象执行备份操作也可能导致对象被提升到缓存中。如果执行值设置为“0”的完全备份,可能会导致所有数据都被提升到缓存层,而活跃数据会从缓存层中删除。因此,根据备份策略更改此设置的做法可能会有帮助。

注意
注意

期限越长,min_read_recency_for_promotemin_write_recency_for_promote 的值越大,ceph-osd 守护进程耗费的 RAM 就越多。特别是,当代理正在刷新或赶出缓存对象时,所有 hit_set_count 命中集都会加载到 RAM 中。

14.7.1.1 对命中集使用 GMT

缓存层设置包含一个称作命中集的布隆过滤器。该过滤器测试某个对象是属于一组热对象还是冷对象。对象将添加到命中集,其名称后面附有时戳。

如果集群计算机位于不同的时区,且时戳根据当地时间派生,则命中集中对象的名称可能包含将来或过去的时戳,致使用户产生误解。在最坏的情况下,对象可能根本不在命中集中。

为防止这种问题发生,在新建的缓存层设置中,use_gmt_hitset 默认设为“1”。这样,您便可以在创建命中集的对象名称时,强制 OSD 使用 GMT(格林威治标准时间)时戳。

警告
警告:保留默认值

不要更改 use_gmt_hitset 的默认值“1”。如果与此选项相关的错误不是因集群设置造成,切勿手动更改此选项。否则,集群的行为可能变得无法预测。

14.7.2 缓存大小调整

缓存分层代理执行两项主要功能:

刷新

代理识别已修改的(脏)对象,并将其转发到存储池长期存储。

赶出

代理识别未曾修改的(正常)对象,并将其中最近用得最少的对象从缓存中赶出。

14.7.2.1 绝对大小调整

缓存分层代理可根据字节总数或对象总数来刷新或赶出对象。要指定最大字节数,请执行以下命令:

cephadm@adm > ceph osd pool set cachepool target_max_bytes num_of_bytes

要指定最大对象数,请执行以下命令:

cephadm@adm > ceph osd pool set cachepool target_max_objects num_of_objects
注意
注意

Ceph 无法自动确定缓存池的大小,因此需要配置绝对大小。否则,刷新和赶出功能将无法正常工作。如果这两项限制都指定,则一旦触发任一阈值,缓存分层代理就会开始执行刷新或赶出。

注意
注意

仅当达到 target_max_bytestarget_max_objects 时,才会阻止所有客户端请求。

14.7.2.2 相对大小调整

缓存分层代理可以根据缓存池的相对大小(通过第 14.7.2.1 节 “绝对大小调整”中所述的 target_max_bytestarget_max_objects 指定)刷新或赶出对象。当缓存池中的已修改(脏)对象达到特定百分比时,缓存分层代理会将这些对象刷新到存储池。要设置 cache_target_dirty_ratio,请执行以下命令:

cephadm@adm > ceph osd pool set cachepool cache_target_dirty_ratio 0.0...1.0

例如,如果将值设置为 0.4,则当已修改(脏)对象的大小达到缓存池容量的 40% 时,就会开始刷新这些对象。

cephadm@adm > ceph osd pool set hot-storage cache_target_dirty_ratio 0.4

当脏对象的大小达到容量的特定百分比时,将以更高的速度刷新。使用 cache_target_dirty_high_ratio

cephadm@adm > ceph osd pool set cachepool cache_target_dirty_high_ratio 0.0..1.0

当缓存池的大小达到其容量的特定百分比时,缓存分层代理会赶出对象,以维持可用容量。要设置 cache_target_full_ratio,请执行以下命令:

cephadm@adm > ceph osd pool set cachepool cache_target_full_ratio 0.0..1.0

14.7.3 缓存期限

您可以指定在缓存分层代理将最近修改过的(脏)对象刷回到后备存储池之前,这些对象可保留的最短期限。请注意,此命令仅在缓存确实需要清理/赶出对象时适用:

cephadm@adm > ceph osd pool set cachepool cache_min_flush_age num_of_seconds

您可以指定在将某个对象赶出缓存层之前,该对象至少可保留的期限:

cephadm@adm > ceph osd pool set cachepool cache_min_evict_age num_of_seconds

14.7.4 示例

14.7.4.1 大型缓存池和少量内存

如果有大量的存储,但只有少量的 RAM 可用,则所有对象在被访问后可立即提升到缓存池。命中集保持较小的规模。下面是一组示例配置值:

hit_set_count = 1
hit_set_period = 3600
hit_set_fpp = 0.05
min_write_recency_for_promote = 0
min_read_recency_for_promote = 0

14.7.4.2 小型缓存池和大量内存

如果只有少量的存储,但可用的内存量相对较大,则可以将缓存层配置为将有限数量的对象提升到缓存池。如果有 12 个命中集,并且在 14,400 秒期限内可以使用其中每个命中集,则这些命中集总共可提供 48 小时的跟踪。如果在过去 8 小时内访问了某个对象,该对象将提升到缓存池。这种情况的一组示例配置值如下:

hit_set_count = 12
hit_set_period = 14400
hit_set_fpp = 0.01
min_write_recency_for_promote = 2
min_read_recency_for_promote = 2
打印此页