Ceph在O版新增了Immutable对象本地缓存的功能。此功能很大程度上是为VDI桌面使用场景设计的,在VDI工作负载中,虚拟机一般是从相同的基本镜像克隆得到的,这些虚拟机在启动引导阶段,将分别从rados中读取母本镜像数据,而这些数据有很大一部分是重复的。如果有母本镜像的本地缓存,将有助于加快虚拟机读取数据的过程,并节省客户端的网络访问流量。
Ceph新增了一个独立的守护进程ceph-immmutable-object-cache,负责将母本镜像数据缓存在本地磁盘上(一个对象对应一个本地文件)。守护进程支持的配置项包括:immutable_object_cache_path(本地缓存目录)、immutable_object_cache_sock(用于librbd客户端和ceph-immmutable-object-cache通信的socket)、immutable_object_cache_max_size(最大缓存大小)、immutable_object_cache_watermark(开始进行LRU缓存淘汰的水位)。
对于Librbd客户端,则通过设置配置项rbd_parent_cache_enabled为true开启。
守护进程ceph-immutable-object-cache承接Librbd客户端访问母本镜像的读请求(不存在访问母本镜像的写请求),当Librbd客户端所请求的数据在本地缓存不存在时,ceph-immutable-object-cache将访问RADOS获取数据,写入本地缓存,并返回给Librbd客户端。核心处理逻辑代码实现如下:
使用tools/immutable_object_cache/CacheController.cc的handle_request方法处理来自客户端的读请求。
ObjectCacheReadData* req_read_data = reinterpret_cast <ObjectCacheReadData*> (req);
int ret = m_object_cache_store->lookup_object(
req_read_data->pool_namespace, req_read_data->pool_id,
req_read_data->snap_id, req_read_data->oid, cache_path);
ObjectCacheRequest* reply = nullptr;
if (ret != OBJ_CACHE_PROMOTED) {
reply = new ObjectCacheReadRadosData(RBDSC_READ_RADOS, req->seq);
} else {
reply = new ObjectCacheReadReplyData(RBDSC_READ_REPLY, req->seq, cache_path);
}
其中tools/immutable_object_cache/ObjectCacheStore.cc的lookup_object方法查询本地缓存是否存在。
std::string cache_file_name = get_cache_file_name(pool_nspace, pool_id, snap_id, object_name);
cache_status_t ret = m_policy->lookup_object(cache_file_name);
switch (ret) {
case OBJ_CACHE_NONE: {
pret = do_promote(pool_nspace, pool_id, snap_id, object_name);
if (pret < 0) {
lderr(m_cct) << "fail to start promote" << dendl;
}
return ret;
}
case OBJ_CACHE_PROMOTED:
target_cache_file_path = get_cache_file_path(cache_file_name);
return ret;
case OBJ_CACHE_SKIP:
return ret;
default:
lderr(m_cct) << "unrecognized object cache status" << dendl;
ceph_assert(0);
}
若本地缓存不存在则调用do_promote方法,访问Rados存储集群得到结果并写入到本地缓存文件,同时返回结果。若命中缓存则直接返回本地缓存文件路径。