Ceph管理缓存池

1、缓存池简介

1.1 缓存池原理

ceph的缓存分层特性是在ceph的F版当中正式发布的。所谓的缓存分层其实就是在更快的磁盘(通常是ssd)上创建一个存储池。然后将这个存储池放置在常规的复制池或者纠删码池的前端充当缓存。这样所有的客户端I/O操作都首先由缓存池处理,之后再将数据写回到现有的数据存储池中,使得客户端能够在缓存池上享受更好的性能,而最终数据还是写回到常规池中。

ceph10

一般来说,缓存池会被构建在更昂贵的或者说速度更快的ssd盘上,这样才能提供更好的I/O性能。而缓存池后端的存储池则由普通的hdd盘组成。在这种类型的设置中,客户端将I/O请求提交至缓存池,不管是读还是写操作,它的请求都能立即获得响应。速度更快的缓存层为客户端请求提供响应。一段时间后,缓存层将所有数据再写回后端的存储存,以便它可以缓存来自客户端的新请求。在缓存层和数据层之间的数据迁移都是自动触发且对客户端透明的。

1.2 缓存池的工作模式

缓存池能以以下两种模式进行配置:

  • writeback模式:当缓存池配置为writeback模式时,客户端将数据写至缓存池,然后立即接收写入确认。缓存池基于我们为其设置的flushing/evicting策略,将数据从缓存池迁移至后端存储池,并最终由缓存代理将其从缓存层中删除。处理来自客户端的读操作时,首先由缓存分层代理将数据从存储层迁移至缓存层,然后再将其返回给客户端。只到数据变得不再活跃或者成为冷数据时,再将其从缓存池中删除。
  • read-only模式:当缓存池配置为read-only模式时,它只适用于处理客户端的读操作。客户端的写操作不涉及缓存分层,所有的客户端写都在存储层上完成。在处理来自客户端的读操作时,缓存分层代理将请求的数据从存储层复制到缓存层。缓存池基于我们为其配置的策略,将不活跃的对象从缓存池中删除。这种方法非常适合多个客户端需要读取大量类似数据的场景。

2、配置缓存池

2.1 创建一个缓存池

假设我们已经有了一个基于ssd的crush_rule,我们创建一个存储池,使用该crush rule即可。关于如何创建一个基于ssd的crush_rule,可直接参考《crushmap磁盘智能分组》

下面是创建一个基于ssd的存储池的示例:

1
2
# 假设ssd_rule即基于ssd的cursh_rule
ceph osd create pool cache 64 64 ssd_rule

2.2 设置缓存层

1
2
3
4
5
6
7
8
# 将上面创建的cache池绑定至存储池的前端,cephfs_data即为我们的后端存储池
ceph osd tier add cephfs_data cache

# 设置缓存模式为writeback
ceph osd tier cache-mode cache writeback

# 将所有客户端请求从标准池引导至缓存池
ceph osd tier set-overlay cephfs_data cache

此时,我们分别查看存储池和缓存池的详情,可以看到相关的缓存配置信息:

1
2
3
root@ceph:~# ceph osd dump |egrep 'cephfs_data|cache'
pool 2 'cephfs_data' replicated size 3 min_size 1 crush_rule 0 object_hash rjenkins pg_num 128 pgp_num 128 last_change 3079 lfor 3079/3079 flags hashpspool tiers 4 read_tier 4 write_tier 4 stripe_width 0 application cephfs
pool 4 'cache' replicated size 3 min_size 1 crush_rule 1 object_hash rjenkins pg_num 64 pgp_num 64 last_change 3100 lfor 3079/3079 flags hashpspool,incomplete_clones tier_of 2 cache_mode writeback target_bytes 1099511627776 hit_set bloom{false_positive_probability: 0.05, target_size: 0, seed: 0} 0s x0 decay_rate 0 search_last_n 0 stripe_width 0

2.3 缓存层相关参数说明

  1. 对于生产环境的部署,目前只能使用bloom filters数据结构(看官方文档的意思,好像目前只支持这一种filter):
1
ceph osd pool set cache hit_set_type bloom
  1. 设置当缓存池中的数据达到多少个字节或者多少个对象时,缓存分层代理就开始从缓存池刷新对象至后端存储池并驱逐:
1
2
3
4
5
# 当缓存池中的数据量达到1TB时开始刷盘并驱逐
ceph osd pool set cache target_max_bytes 1099511627776

# 当缓存池中的对象个数达到100万时开始刷盘并驱逐
ceph osd pool set cache target_max_objects 10000000
  1. 定义缓存层将对象刷至存储层或者驱逐的时间:
1
2
ceph osd pool set cache cache_min_flush_age 600
ceph osd pool set cache cache_min_evict_age 600
  1. 定义当缓存池中的脏对象(被修改过的对象)占比达到多少时,缓存分层代理开始将object从缓存层刷至存储层:
1
2
3
4
# 当脏对象占比达到10%时开始刷盘
ceph osd pool set cache cache_target_dirty_ratio 0.4
# 当脏对象占比达到60%时开始高速刷盘
cache_target_dirty_high_ratio: 0.6
  1. 当缓存池的使用量达到其总量的一定百分比时,缓存分层代理将驱逐对象以维护可用容量(达到该限制时,就认为缓存池满了),此时会将未修改的(干净的)对象刷盘:
1
ceph osd pool set cache cache_target_full_ratio 0.8

2.4 测试缓存池

配置好缓存池以后,我们可以先将其驱逐对象的最小时间设置为60s:

1
2
ceph osd pool set cache cache_min_evict_age 60
ceph osd pool set cache cache_min_flush_age 60

然后,我们往存储池中写一个数据

1
rados -p cephfs_data put test /tmp/test.txt

查看存储池,这时应该无法查看到该数据,查看缓存池,则可以看到数据存储在缓存池中:

1
2
rados -p cephfs_data ls |grep test
rados -p cache ls |grep test

等60s之后,数据刷盘,此时即可在存储池中看到该数据,则缓存池中,该数据即被驱逐。

3、删除缓存池

需要说明的是,根据缓存池类型的不同,删除缓存池的方法也不同。

3.1 删除read-only缓存池

由于只读缓存不具有修改的数据,因此可以直接禁用并删除它,而不会丢失任何最近对缓存中的对象的更改。

  1. 将缓存模式个性为none以禁用缓存:
1
ceph osd tier cache-mode cache none
  1. 删除缓存池:
1
2
# 解除绑定
ceph osd tier remove cephfs_data cache

3.2 删除writeback缓存池

由于回写缓存可能具有修改的数据,所以必须采取措施以确保在禁用和删除缓存前,不丢失缓存中对象的最近的任何更改。

  1. 将缓存模式更改为转发,以便新的和修改的对象刷新至后端存储池:
1
ceph osd tier cache-mode cache forward
  1. 查看缓存池以确保所有的对象都被刷新(这可能需要点时间):
1
rados -p cache ls
  1. 如果缓存池中仍然有对象,也可以手动刷新:
1
rados -p cache cache-flush-evict-all
  1. 删除覆盖层,以使客户端不再将流量引导至缓存:
1
ceph osd tier remove-overlay cephfs_data
  1. 解除存储池与缓存池的绑定:
1
ceph osd tier remove cephfs_data cache

参考: https://blog.csdn.net/weixin_34364135/article/details/87528549

-------------本文结束感谢您的阅读-------------