Ceph缓存分层可以为在后端存储数据层对客户端提供更好的I/O性能。缓存分层包含了使用快速/昂贵的存储设备来创建一个池,用这个存储池作为缓存层;同时包含了一个使用低速/便宜设备组成的池作为经济的存储层。Ceph决定对象存放的位置,分层代理决定什么时间将对象从缓存刷新到后端存储层,因此缓存层和后端存储层对客户端来说是完全透明的。


缓存分层代理负责缓存层和后端存储层之间数据的自动迁移。而且,admins可以配置这些迁移在什么时候发生。这里主要有两种情景:

  • Writeback Mode: 当管理员配置层为writeback模式时,Ceph客户端负责写入数据到缓存层并且从缓存层得到写入的确认。在缓存层中的数据会及时迁移到存储层并且会在缓存层刷新。概念上来说,缓存层是在后端存储层的前端。当一个Ceph客户端需要从存储中获取数据时,缓存分层代理会将数据迁移到缓存层,再发送给Ceph客户端。在此之后,客户端可以对缓存层的数据进行I/O操作,直到数据变为不活跃的。这种情景适合与经常变化的数据(例如图片和视频编辑,事务型数据等)
  • Read-only Mode: 当管理员配置层为readonly模式时,Ceph客户端会直接将数据写入到后端存储层。当进行读取时,Ceph会将请求的对象从后端存储层复制到缓存层。旧的对象会根据预设策略从缓存层中移除。这种场景适用于不经常变化的数据(例如,在网络中获取图片和视频,DNA数据,X光图像等),因为从缓存层中读取的数据可能会包含旧的数据,因此提供了弱一致性。对于经常变化的数据,不要使用readonly模式。

下面的模式使用不同的配置:

  • Read-forward Mode: 该模式下,对于客户端写请求与writeback模式一致,但是当读取数据时,对象没有在缓存层复制,ceph会通过重定向消息将读请求发送到后端存储层,客户端会从后端存储获取到数据。这种模式适用于后端存储的读性能与缓存层类似,但是写入性能差距较大的情景。
  • Read-proxy Mode: 该模式与readforward模式相似:同样都是在客户端请求的对象不在缓存层中存在时,不会复制对象到缓存层。但与readforward不同的时,不会将请求重定向到后端存储,缓存层会像客户端一样从存储读取对象。在某项条件下,这个模式会减少延迟。

因为所有的客户端都使用缓存分层,这会有机会为Ceph块设备、对象存储和文件系统提高I/O性能。


SETTING UP POOLS建立池

为了建立缓存分层,你必须有两个池,其中一个为后端存储,另外为缓存。



建立一个后端存储池

建立一个后端存储池典型的包含两种情景:


  • Standard Storage(标准存储): 这情景下,存储池中会复制一个对象的多个副本。
  • Erasure Coding(纠删编码): 这种情景下,存储池会使用纠删编码来保证数据的有效性,会牺牲一部分性能。

在标准存储场景下,你可以通过CRUSH规则建立失效域(例如osd、host、chassis、rack、row等)。Ceph OSD进程在使用同样大小、速度(转速、吞吐)、类型的磁盘时,表现会更好。查看CRUSH Maps获取更多创建规则的细节。一旦你已经创建了一个规则,就可以创建后端存储池。

在就删代码场景下,池创建参数会根据规则自动生成,查看Create a Pool 获取等多信息。

在后面的章节中,我们会将后端存储池成为cold-storage。



SETTING UP A CACHE POOL

建立一个缓存池的步骤和标准存储池一样,区别在于缓存层使用了高性能的磁盘并且有自己的规则集。当建立规则集时,需要考虑到有高性能磁盘的主机,忽略没有高性能磁盘的主机。查看Placing Different Pools on Different OSDs获取更多详情。

在下面的例子中,我们将缓存吃称为host-storage,后端存储称为cold-storage。

对于缓存分层的配置和默认值,参考Pools - Set Pool Values


CREATING A CACHE TIER创建一个缓存层

创建一个缓存层包含将一个后端存储关联到一个缓存池:



ceph osd tier add {storagepool} {cachepool}



For example



ceph osd tier add cold-storage hot-storage



位置设置缓存模式,执行以下命令:



ceph osd tier cache-mode {cachepool} {cache-mode}



For example:



ceph osd tier cache-mode hot-storage writeback



由于缓存层在后端存储层前,因此要求一个额外的步骤:你需要将所有客户端的流量从存储池重定向到缓存池。为了重定向到缓存池,执行以下命令:



ceph osd tier set-overlay {storagepool} {cachepool}



For example:



ceph osd tier set-overlay cold-storage hot-storage


CONFIGURING A CACHE TIER配置缓存层

缓存层有多个可以配置的选项。你可以通过以下方式进行缓存层的配置:



ceph osd pool set {cachepool} {key} {value}



See Pools - Set Pool Values for details.



TARGET SIZE AND TYPE目标大小和类型

Ceph生产环境缓存层的hit_set_type算法使用了 Bloom Filter算法:



ceph osd pool set {cachepool} hit_set_type bloom



For example:



ceph osd pool set hot-storage hit_set_type bloom



hit_set_count和hit_set_period定义了HiSet达到的次数和HitSets存储的时间。



ceph osd pool set {cachepool} hit_set_count 1 ceph osd pool set {cachepool} hit_set_period 3600 ceph osd pool set {cachepool} target_max_bytes 1000000000000



Binning accesses over time allows Ceph to determine whether a Ceph client accessed an object at least once, or more than once over a time period (“age” vs “temperature”).把超时的数据丢弃的方法允许Ceph决定一个Ceph客户端可以取出一个对象一次还是在一个时间段取出多次(“时间”和“热度”)。

The min_read_recency_for_promote defines how many HitSets to check for the existence of an object when handling a read operation. The checking result is used to decide whether to promote the object asynchronously. Its value should be between 0 and hit_set_count. If it’s set to 0, the object is always promoted. If it’s set to 1, the current HitSet is checked. And if this object is in the current HitSet, it’s promoted. Otherwise not. For the other values, the exact number of archive HitSets are checked. The object is promoted if the object is found in any of the most recentmin_read_recency_for_promote


A similar parameter can be set for the write operation, which is min_write_recency_for_promote.



ceph osd pool set {cachepool} min_read_recency_for_promote 1 ceph osd pool set {cachepool} min_write_recency_for_promote 1



Note

The longer the period and the higher the min_read_recency_for_promote/min_write_recency_for_promote, the more RAM the ceph-osddaemon consumes. In particular, when the agent is active to flush or evict cache objects, all hit_set_count



CACHE SIZING缓存大小

缓存层代理主要有两个功能:

  • Flushing: 代理识别变化(脏)对象,并且将他们发送到存储池来达到持久化存储。
  • Evicting: 代理识别出没有变化的数据并且将不经常使用的数据从缓存中移除。
ABSOLUTE SIZING绝对大小

缓存层代理可以根据总数据量或者总对象数量刷新或者移除对象。为了指定最大数据量(单位bytes),执行以下命令:



ceph osd pool set {cachepool} target_max_bytes {#bytes}



例如在数据量为1TB时刷新或者移除对象,执行以下命令:



ceph osd pool set hot-storage target_max_bytes 1099511627776



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



ceph osd pool set {cachepool} target_max_objects {#objects}



例如,在1M数量个对象时进行刷新或者移除,执行以下命令:



ceph osd pool set hot-storage target_max_objects 1000000



Note

Ceph不能自动决定缓存大小,因此配置绝对大小是必须的,否则刷新/移除将不会工作。如果你设置了两个限制(大小和数量),缓存层代理会在其中一条达到时去执行刷新或者移除操作。



Note

当target_max_bytes或者target_max_objects达到时,所有的客户端请求会被阻塞。



RELATIVE SIZING相对大小

缓存层代理可以在相对于缓存池大小(通过target_max_bytes/target_max_objects设置,绝对大小)的某个值时进行刷新或者移除操作。当缓存池中包含了一个确定百分比的脏数据(对象)时,缓存层代理会刷新这些对象到后端存储池,通过设置cache_target_dirty_radio来进行设置:



ceph osd pool set {cachepool} cache_target_dirty_ratio {0.0..1.0}



例如,设置值为0.4,代理将会在脏对象超过40%时进行刷新操作:



ceph osd pool set hot-storage cache_target_dirty_ratio 0.4



当脏对象达到一个确定百分比时,代理将会以一个相对较快的速度进行刷新。通过设置cache_target_dirty_high_radio:



ceph osd pool set {cachepool} cache_target_dirty_high_ratio {0.0..1.0}



例如,设置该值为0.6,当脏对象达到60%时,将会进行进取型刷新。最好将该值设置到dirty_radio和full_radio之间:



ceph osd pool set hot-storage cache_target_dirty_high_ratio 0.6



当缓存池达到一个具体的百分比时,缓存层代理会移除对象来保持足够的可用空间。通过设置cache_target_full_radio实现:



ceph osd pool set {cachepool} cache_target_full_ratio {0.0..1.0}



例如,当该值设置为0.8时,当达到缓存80%大小时,代理会移除未修改对象。



ceph osd pool set hot-storage cache_target_full_ratio 0.8



CACHE AGE缓存时间

你可以设置一个脏对象刷新到后端存储的最小时间:



ceph osd pool set {cachepool} cache_min_flush_age {#seconds}



例如,在10分钟后刷新脏对象,执行以下命令:



ceph osd pool set hot-storage cache_min_flush_age 600



你可以指定一个对象多久没有访问后从缓存池中移除:



ceph osd pool {cache-tier} cache_min_evict_age {#seconds}



例如,当一个对象30分钟没有被访问,会被移除,通过以下命令设置:



ceph osd pool set hot-storage cache_min_evict_age 1800


REMOVING A CACHE TIER移除缓存层

根据缓存层使用的模式(writeback/read-only)不同,移除的方式也不同。



REMOVING A READ-ONLY CACHE移除一个只读缓存层

因为只读缓存层中不存储脏数据,可以直接禁用和移除:

  1. 设置缓存模式为none进行禁用:
    ceph osd tier cache-mode {cachepool} none
    For example:
    ceph osd tier cache-mode hot-storage none
  2. 从后端存储移除缓存层:
    ceph osd tier remove {storagepool} {cachepool}
    For example:
    ceph osd tier remove cold-storage hot-storage



REMOVING A WRITEBACK CACHE移除一个WRITEBACK缓存层

因为writeback缓存层可能会有脏数据,你必须按照以下的步骤来确保你不会丢失任意在缓存中的脏对象。

  1. 修改缓存模式为forward,任何新的写入对象会直接写入后端存储。
    ceph osd tier cache-mode {cachepool} forward
    For example:
    ceph osd tier cache-mode hot-storage forward
  2. 确认缓存池中所有数据都被刷新,这通常会花费一段时间:
    rados -p {cachepool} ls
    如果缓存池中还有对象,可以手动进行刷新,例如:
    rados -p {cachepool} cache-flush-evict-all
  3. 移除重新向,客户端不会直接发送流量到缓存:
    ceph osd tier remove-overlay {storagetier}
    For example:
    ceph osd tier remove-overlay cold-storage
  4. 最后,从后端存储移除缓存池
    ceph osd tier remove {storagepool} {cachepool}
    For example:
    ceph osd tier remove cold-storage hot-storage