FlashCache初探(二)

Flashcache : A Write Back Block Cache for Linux
  Author: Mohan Srinivasan
-----------------------------------------------
 
Introduction :
============
Flashcache is a write back block cache Linux kernel module. This
document describes the design, futures ideas, configuration, tuning of
the flashcache and concludes with a note covering the testability
hooks within flashcache and the testing that we did. Flashcache was
built primarily as a block cache for InnoDB but is general purpose and
can be used by other applications as well.

Flashcache设计

flashcache使用了Linux Device Mapper(DM),是Linux 存储栈架构中的一部分,在创建SW-raid和其他组件的时候经常会涉及到,例如,LVM使用的就是DM。

缓存的结构使用了一致性哈希,缓存被划分成多个固定大小的集合(buckets),桶内使用线性地查找block。一致性哈希使用的好处很多(后面的部分将会介绍)并且能够很好的发挥使用。

block size,set size和cache size都是可以配置的参数,在cache创建需要。默认的设置:block size 512,几乎没有什么理由需要修改这个值。(思:意思是推荐使用512)

在以下的内容中,dbn意思是"disk block number",逻辑设备的块号。

计算一个指定的集合属于哪个dbn的方式

target set=(dbn/block size/set size)mod(number of sets)

确认了集合后,在集合内部线性查找block。一个范围的disk block映射在一个指定的集合内。

DM layer在IO发送到cache layer之前将所有的IO操作转化为对block的操作(思:即对其转换等操作)。默认地,flashcache缓存所有的blosksize IO,但是可以配置为之缓存随机IO忽略顺序IO。

Cache  set放置策略是FIFO或者LRU。默认是FIFO但是策略可以在运行期间任何一个点进行切换同时sysctl(see the configuration and tuning section)。

处理缓存的读操作,计算目标集合(根据dbn)现行查找到block。当缓存命中事,就从flash中奖数据读取出来;若未命中,数据则从磁盘中读取数据,将数据写入到flash中,然后返回数据。

由于flashcache采用的写回策略,写操作仅仅写入到flash中,同步更新cache的metadata(标记cache block是脏块),则完成写操作,当block再次被写入事,metadata就不用再更新了。(因为已经标记为脏块了)。

必须注意的是,in the first cut,cache写入不是原子的,例如会有"Torn Page Problem"存在。一旦遇上断电或者写错误,那么有可能部分块以纪念馆写入成功。我们已经有了idea去fix这个问题,并提供原子的cache写入操作(看the Futures section)。

对于每一个缓存块都有一个on-flash metadata为了cache的持久化(是这个意思么?

Each cache block has on-flash metadata associated with it for cache
persistence.),每个block的metadata又dbn(disk block cached in this slot)and flags(Dirty,VALID,INVALID).
cache metadata只有在写操作或者一个cache block被清除的时候需要更新。执行写操作时,将flag标记为dirty;被清除时标记为~dirty。为了最小化flash写操作,cache block metadata在读的时候不需要更新。
另外,我们还有一个0n-flash cache superblock,包含cache的参数(在cache重启时读取),也包含cache关闭是否是clean的(顺序关闭或者节点宕机,断电等等)。
当cache是clean shutdown时,所有cache blocks的metadat都会被写入到flash中。在关机以后,VALID和DIRTY的块在cache重启时将会被持久化(??)。当节点宕机或者断电时,只有dirty cache blocks在cache重新启动时持久化(???)。节点宕机或者断电不会导致数据丢失,但是有可能导致cache丢失valid和non-dirty的cached blocks(为什么?)。
cache 的metadata在可能的时候再批量进行更新。所以如果我们有多个待更新的metadata位于同一个metadata的sector中,可以集中一次更新,当一个文件顺序写入是,我们通常将多个metadata一起更新。
脏的缓存块会在后台写入到disk中。flashcache的延迟写入是由可配置的参数dirty threshold控制的。Flashcache维持每个set中的dirty block的百分比在dirty threshold之下,当set中脏块百分比超过了脏块阈值之后,set将被清理(即写入到disk中并把metadata清空)。
DIRTY blocks的清理选择基于放置策略(FIFO Vs LRU)。当我们选择一个目标set清理时,对这些block进行排序,将块进行合并成大的IO,写入到disk中。
 
之前提到过,在IO操作发送到flashcache之前,DM将IO分裂为blocksize的块操作。对于小IO或者一个IO操作跨两个cache blocks,直接将IO发送到disk中。但是在这之前,我们将cacheblocks中对应这些io的都标记为invalidate。如果覆盖的cacheblock为DIRTY,将数据写入到cacheblock中,并clean。将IO所在的cacheblocks置为invalidate非常容易,使用一致性哈希算法计算io所在set。
Flashcache支持块校验,在cache上计算,并且在每次cache读取时有效。块校验是可以编译选择的,由于“Torn page”的问题,默认是关闭的。如果cache写失败,有的block已经成功提交到flash中,那么block checksum出现错误的block以及之后的所有的block写入都认为是失败的。
 
那么metadata的开销有多大呢?每个cache block在内存中有24字节的状态(64位架构)和在flash上有16字节的状态。对于一个300GB的cache有16KB的blocks,有将近20 Million cacheblocks,内存元数据消耗是480MB,如果我们配置300GB的cache使用4KB的page是,内存消耗为1.8GB。
 
如果一个进程标记他为不是用缓存,当进程退出时flashcache没有办法执行clean操作,(因为Linuxkernel没有at_exit()钩子)。应用程序必须解决这个问题(见下文配置)。关于清理问题的解决方法是,使用缓存控制flashcache伪文件系统,在一个进程退出时最后一个关闭的fd负责清理工作。
In spite of the limitations, we think the ability to mark Direct IOs
issued by a pid will be valuable to prevent backups from wiping out
the cache.
尽管存在这些局限性,我们认为一个pid标记的直接IO能够有效的组织从cache中的擦除。
 
另外,除非特别标注pids不使用缓存,否则用户使用系统调用"skip_seq_thresh_kb"
posted @ 2012-04-16 19:58  remimin  阅读(4457)  评论(0编辑  收藏  举报
ADC·阿里技术嘉年华(7月7-8日·杭州)