从 GitHub 上 Clone Ceph 项目,我是基于 (ceph version 12.2.11 luminous 版本) 的代码来分析的
一、Cache Tier(Cache Pool)是什么?
在 Ceph 里创建 pool 时,可以设置一个 pool 为另一个 pool 的 cache 层,做缓存层的 pool 称为 cache pool (也就是 cache tier)。而真正存数据的 pool 就是我们常用的 data pool(代码里叫 base pool)。使用如下命令来创建 Cache Tier:
ceph osd tier add {data_pool} {cache_pool}
该命令行程序发送请求给 Monitor,然后由 Monitor 相关的 pool 设置上述属性值,并由 Monitor 来持久化存储该 pool 信息。**注:**一个 data pool 可以有多个 cache tier (cache pool).
另外,如何在指定的 OSD 上创建 Ceph Pool,请参考 Ceph 进阶系列(二):如何在指定的 OSD 设备上创建 pool
cache tier 相关的命令(属于 monitor command):
命令 | 描述 |
---|---|
ceph osd tier add <data_pool> <cache_pool> {–force-nonempty} | add the tier <tierpool> (the second one) to base pool <pool> (the first one) |
ceph osd tier add-cache <data_pool> <cache_pool> <int[0-]> | add a cache <tierpool> (the second one) of size <size> to existing pool <pool> (the first one) |
ceph osd tier cache-mode <cache_pool> none|writeback|forward|readonly|readforward|proxy|readproxy {–yes-i-really-mean-it} | specify the caching mode for cache tier <pool> |
ceph osd tier remove <data_pool> <cache_pool> | remove the tier <tierpool> (the second one) from base pool (the first one) |
ceph osd tier remove-overlay <data_pool> | remove the overlay pool for base pool <pool> |
ceph osd tier rm <data_pool> <cache_pool> | remove the tier <tierpool> (the second one) from base pool <pool> (the first one) |
ceph osd tier rm-overlay <data_pool> | remove the overlay pool for base pool <pool> |
ceph osd tier set-overlay <data_pool> <overlaypool> | set the overlay pool for base pool <pool> to be <overlaypool> |
二、为什么要有 Cache Tier?
Cache Tier 技术目标在于:把用户访问频率高的热数据放置在高性能、小容量的存储介质中(比如 NVME SSD),把大量冷数据放置在大容量的存储介质中(比如 HDD)。Cache Tier 为用户提供的价值在于:提高热数据访问性能的同时,降低存储成本。实现这样的方法是:Cache Tier 可以让冷数据自由安全地迁移到更低层的存储介质中(data pool),这样达到节约存储成本;让热点数据自动的从低层(data pool)迁移到高层存储层(cache tier),这样达到提高访问热点数据的性能。
三、Cache Tier 的技术实现
- 数据访问行为的追踪、统计与分析:持续追踪与统计每个数据块的存取频率,并通过定期分析,识别出存取频率高的 “热” 区块,与存取频率低的 “冷” 区块。
- 数据迁移:以存取频率为基础,定期执行数据迁移,将热点数据块迁移到高速存储层,把较不活跃的冷数据块迁移到低速存储层。数据迁移一对象(默认为 4MB)为基本单位。
四、Cache Tier 在 Ceph 架构里的位置
例如,cache tier 的 read forward 模式流程如下(一共 6 种模式 writeback|forward|readonly|readforward|proxy|readproxy,每种模式的流程略有不同):
read proxy 模式
五、Cache Tier 的关键代码分析
Cache Tier 的代码分布在 Ceph 源代码的各个模块,其核心在对象的数据读写路径上。
1. 其相关的数据结构:
pool 的数据结构 pg_pool_t,它有两个变量对应相应的 cache pool 和 base pool 配置
//src/osd/osd_types.h
/*
* pg_pool
*/
struct pg_pool_t {
...
set<uint64_t> tiers; ///< pools that are tiers of usint64_t tier_of; ///< pool for which we are a tier
...
}
这两个字段用来设置 pool 的属性:
・如果当前 pool 是一个 cache pool,那么 tier_of 记录了该 cache pool 的 base pool 层。
・如果当前 pool 是 base pool,那么 tiers 就记录该 base pool 的 cache pool 层,一个 base pool 可以设置多个 cache pool 层。
2. Cache Tier 的初始化
Cache Tier 初始化有两个入口,如下所示:
・on_active:如果该 pool 已经设置为 cache pool,在该 cache pool 的所有 PG 处于 activave 状态后初始化。
・on_pool_change:当该 pool 的所有 PG 都已经处于 active 状态后,才设置该 pool 为 cache pool,那么就等待 Monitor 通知 osd map 相关信息的变化,在 on_pool_change 函数里初始化。
3**. 读写路径上的 Cache Tier 处理**
在 OSD 的正常读写路径上,如果该 pool 有 Cache Tier 设置,处理逻辑就发生了变化。如下所示:
// hot/cold tracking
HitSetRef hit_set; ///< currently accumulating HitSet
/** do_op - do an op
* pg lock will be held (if multithreaded)
* osd_lock NOT held.
*/
void PrimaryLogPG::do_op(OpRequestRef& op)
{
......
bool in_hit_set = false;
if (hit_set) {
if (obc.get()) {
if (obc->obs.oi.soid != hobject_t() && hit_set->contains(obc->obs.oi.soid))
in_hit_set = true;
} else {
if (missing_oid != hobject_t() && hit_set->contains(missing_oid))
in_hit_set = true;
}
if (!op->hitset_inserted) {
hit_set->insert(oid);
op->hitset_inserted = true;
if (hit_set->is_full() ||
hit_set_start_stamp + pool.info.hit_set_period <= m->get_recv_stamp()) {
hit_set_persist();
}
}
}
if (agent_state) {
if (agent_choose_mode(false, op))
return;
}
if (obc.get() && obc->obs.exists && obc->obs.oi.has_manifest()) {
if (maybe_handle_manifest(op,
write_ordered,
obc))
return;
}
if (maybe_handle_cache(op,
write_ordered,
obc,
r,
missing_oid,
false,
in_hit_set))
return;
......
参考:《Ceph 源码分析》
转自:https://blog.youkuaiyun.com/don_chiang709/article/details/99727048