flashcache的实现与用法

工做须要,看了些flashcache的内容,记录以下: php

实现

flashcache,是facebook技术团队开发的新开源项目,主要目的是用SSD硬盘来缓存数据以加速MySQL的一个内核模块。能够看到,它最初是用来作数据库加速,但同时,它也被做为通用的缓存模块而设计,可以用于任何搭建在块设备上的应用程序。 html

工做原理。基于Device Mapper,它将快速的SSD硬盘和普通的硬盘映射成一个 带缓存的逻辑块设备,做为用户操做的接口。用户直接对这个逻辑设备执行读写操做,而不直接对底层的SSD或者普通硬盘操做。若是对底层的这些块设备操做, 那么会失去做为一个总体提供的缓存功能。 node

内核层次。flashcache,它是经过在文件系统和块设备驱动层中间 增长一缓存层次实现的,这里不得不提到DM层的映射机制。因为DM是做为虚拟的块设备驱动在内核中被注册的,它不是一个真实的设备驱动,不能完成bio的 处理,所以,它主要是基于映射表对bio进行分解、克隆和重映射,而后,bio到达底层真实的设备驱动,启动数据传输。在Device mapper中,引入了target_driver,每一个target_driver由target_type类型描述,表明了一类映射,它们分别用来具 体实现块设备的映射过程。经过调用某一target_driver的map方法,来映射从上层分发下来的bio,也便是,找到正确的目标设备,并将bio 转发到目标设备的请求队列,完成操做。flashcache_target就是这样一个新的target_driver(做为一个新的映射类 型,target_type是必须的),以模块化的方式加入到了DM层。 linux

逻辑架构。从源代码层次分析,能够将flashcache分为这个四个模 块,调度模块(也称‘读写模块’)、逻辑处理模块(也称“读写后处理模块”)、底层存储模块、以及后台清理模块,它们都是基于SSD Layout实现的,构建在SSD布局(后面会分析)之上。其中,调度模块,在代码中对应flashcache_map映射函数,它是 flashcache缓存层次数据入口,因此到达逻辑设备的读写请求,最终都会通过DM层的处理,经过flashcache_map进入调度模块。称之为 “调度”,主要是指,接收到数据后,它会根据bio请求的读写类型、是否命中缓存等因素,选择不一样的处理分支,如 flashcache_read/write或者flashcache_uncached_io,在read和write中会选择是 flashcache_read_hit/miss仍是flashcache_write_hit/miss。通过不一样分支的读写,会调用底层存储模块来 完成磁盘或cache的数据读写。逻辑处理模块,在代码中对应flashcache_io_callback,它在调度模块经过底层存储模块执行数据读写 操做完成后回调执行,因此说它是“读写后处理模块”,它是采用状态机实现的,根据调度模块中的读写类型进行后续的处理,如读未命中状况下,磁盘读完成后, 回调到逻辑处理模块,由它负责将从磁盘读取的数据写回到SSD,或者写未命中状况下,写SSD完成后,回调到逻辑处理模块执行元数据的更新,再有就是对调 度模块中读写操做的错误进行处理。底层存储模块,主要提供了两种方式来完成真实的数据读写,一是由DM提供的dm_io函数,它最终仍是经过 submit_bio的方式,将由调度模块处理过的bio提交到通用块层,进行转发到真实的设备驱动,完成数据读写;另外,一种方式,kcopyd,是由 内核提供的一种底层拷贝函数,主要负责脏块的写回(从SSD到磁盘),会引发元数据的更新。然后台清理模块,是针对每一个set进行数据清理,它会基于两种 策略对脏块作回收:(1)set内脏块超过了阈值;(2)脏块超过了设定的空闲时间,即fallow_delay,通常是15分钟,在15分钟没有被操做 则会被优先回收。要注意的是,并无单独的线程在后台作按期空闲块回收,必须由IO操做触发,若是长时间没有对某set操做,则其中的脏数据很长期保持, 容易危害数据安全。 ios

源代码布局。两个工做队列。结合device mapper代码,特别是dm.c能够知道,在调用flashcache_create工具建立flashcache设备时,会调用 flashcache_ctl函数,执行建立工具,它会建立一工做队列_delay_clean,主要负责对整个cache设备的脏块清理,由 flashcache_clean_set在特定条件下调用(见代码),经过flashcache_clean_all执行对全部sets的扫描与清理。 另一个工做队列,_kq_xxx(记不清了),在flashcache_init中,由flashcache模块加载时执行,经过对5个job链表进行 处理,执行元数据的更新与完成处理函数、读磁盘后的SSD写入、以及对等待队列的处理,主要就是负责读写后的处理工做隶属于逻辑处理模块,即“读写后处理 模块”,由磁盘或SSD读写后不一样状况下被调度。 git

调度的时机能够看flashcache_map函数,处理逻辑则主要在函数flashcache_io_callback内部判断,the same block的等待队列是否为空,若是不为空,则一样会调用flashcache_do_handler,执行对等待队列的处理。 github

数据调度。对读,接收到bio,首先,根据 bio->bi_sector,即硬盘的扇区号,获得SSD上的set。其次,在set内查找是否命中,若是命中,则将硬盘的扇区号转换为SSD的 扇区号,而后将此bio向SSD提交,进行读取;若是未命中,则首先向硬盘驱动提交bio,从硬盘读数据,读取完成后,由回调函数启动回写SSD操做,将 bio的扇区号转换为SSD的=扇区号,而后向SSD驱动程序提交,将硬盘读取的数据写入SSD。对写,同文件系统页缓冲,并不直接写入硬盘,而是写入 SSD,同时,保持一个阀值,通常为20%,在脏块数目达到此数值时,写回磁盘。 shell

安装

具体的安装过程能够参考这里。我在编译过linux-3.15.5内核的centos-6.5上直接make和make install,安装成功。 数据库

make -j 4 KERNEL_TREE=/usr/src/kernels/2.6.32-131.0.15.el6.x86_64
sudo make install

最第一版本的Flashcache只支持writeback,后来单独开了一个支持writethrough的分支在flashcache-wt目录,但目前最新的版本已经将write through合并到主版本,而且增长了write around策略。 centos

最新的源码能够到Github获取。

env GIT_SSL_NO_VERIFY=true git clone https://github.com/facebook/flashcache.git
建议下载完源码后的第一件事,就是去doc下阅读 flashcache-doc.txtflashcache-sa-guide.txt

模拟实验

不是每一个人都有SSD/PCI-E Flash的硬件,因此这里能够给你们一个构建虚拟混合存储设备的小技巧,这样即便是在本身的笔记本上,也能够轻松的模拟Flashcache的试验环境,并且随便折腾。

首先,咱们能够用内存来模拟一个性能很好的Flash设备,固然这有一个缺点,就是主机重启后就啥都没了,不过用于实验测试这应该不是什么大问题。 用内存来模拟块设备有两种方法,ramdisk或者tmpfs+loop device。因为ramdisk要调整大小须要修改grub并重启,这里咱们用tmpfs来实现。

# 限制tmpfs最大不超过10G,避免耗尽内存(测试机器有24G物理内存)
$sudo mount tmpfs /dev/shm -t tmpfs -o size=10240m
# 建立一个2G的文件,用来模拟2G的flash设备
$dd if=/dev/zero of=/dev/shm/ssd.img bs=1024k count=2048
# 将文件模拟成块设备
$sudo losetup /dev/loop0 /dev/shm/ssd.img

解决了cache设备,还须要有disk持久设备。一样的,可以使用普通磁盘上的文件来虚拟成一个loop device。

# 在普通磁盘的文件系统中建立一个4G的文件,用来模拟4G的disk设备
$dd if=/dev/zero of=/u01/jiangfeng/disk.img bs=1024k count=4096
$sudo losetup /dev/loop1 /u01/jiangfeng/disk.img

这样咱们就有了一个快速的设备/dev/loop0,一个慢速的磁盘设备/dev/loop1,能够开始建立一个Flashcache混合存储设备了。

$sudo flashcache_create -p back cachedev /dev/loop0 /dev/loop1
cachedev cachedev, ssd_devname /dev/loop0, disk_devname /dev/loop1 cache mode WRITE_BACK
block_size 8, md_block_size 8, cache_size 0
Flashcache metadata will use 8MB of your 48384MB main memory

$sudo mkfs.ext3 /dev/mapper/cachedev
mke2fs 1.41.12 (17-May-2010)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
262144 inodes, 1048576 blocks
52428 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=1073741824
32 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736

Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 28 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.

$sudo mount /dev/mapper/cachedev /u03

Ok,检查一下,就能够开始作一些模拟测试啦。

$sudo dmsetup table
cachedev: 0 8388608 flashcache conf:
        ssd dev (/dev/loop0), disk dev (/dev/loop1) cache mode(WRITE_BACK)
        capacity(2038M), associativity(512), data block size(4K) metadata block size(4096b)
        skip sequential thresh(0K)
        total blocks(521728), cached blocks(83), cache percent(0)
        dirty blocks(0), dirty percent(0)
        nr_queued(0)
Size Hist: 4096:84 

$sudo dmsetup status
cachedev: 0 8388608 flashcache stats:
        reads(84), writes(0)
        read hits(1), read hit percent(1)
        write hits(0) write hit percent(0)
        dirty write hits(0) dirty write hit percent(0)
        replacement(0), write replacement(0)
        write invalidates(0), read invalidates(0)
        pending enqueues(0), pending inval(0)
        metadata dirties(0), metadata cleans(0)
        metadata batch(0) metadata ssd writes(0)
        cleanings(0) fallow cleanings(0)
        no room(0) front merge(0) back merge(0)
        disk reads(83), disk writes(0) ssd reads(1) ssd writes(83)
        uncached reads(0), uncached writes(0), uncached IO requeue(0)
        uncached sequential reads(0), uncached sequential writes(0)
        pid_adds(0), pid_dels(0), pid_drops(0) pid_expiry(0)

$sudo sysctl -a | grep flashcache
dev.flashcache.loop0+loop1.io_latency_hist = 0
dev.flashcache.loop0+loop1.do_sync = 0
dev.flashcache.loop0+loop1.stop_sync = 0
dev.flashcache.loop0+loop1.dirty_thresh_pct = 20
dev.flashcache.loop0+loop1.max_clean_ios_total = 4
dev.flashcache.loop0+loop1.max_clean_ios_set = 2
dev.flashcache.loop0+loop1.do_pid_expiry = 0
dev.flashcache.loop0+loop1.max_pids = 100
dev.flashcache.loop0+loop1.pid_expiry_secs = 60
dev.flashcache.loop0+loop1.reclaim_policy = 0
dev.flashcache.loop0+loop1.zero_stats = 0
dev.flashcache.loop0+loop1.fast_remove = 0
dev.flashcache.loop0+loop1.cache_all = 1
dev.flashcache.loop0+loop1.fallow_clean_speed = 2
dev.flashcache.loop0+loop1.fallow_delay = 900
dev.flashcache.loop0+loop1.skip_seq_thresh_kb = 0
我是dd一个ssd.img和一个disk.img,而后fio进行测试,效果比非flashcache设备提升3-4倍。

flashcache命令行

假设咱们的ssd盘是/dev/sdb,sas盘是/dev/sdc。

建立flashcache设备:

flashcache_create -p back cachedev /dev/sdb /dev/sdc

-p back:指定cache模式是writeback

cachedev:flashcache设备名

注意将sdd盘放在前面,sas盘放在后面。

这样Linux就虚拟出了一个带缓存的块设备:

[root@osd0 loop2+loop3]# ll /dev/mapper/cachedev 
lrwxrwxrwx 1 root root 7 Aug 18 11:08 /dev/mapper/cachedev -> ../dm-1
这样就能够像使用通常的块设备同样,来使用该设备了。若是原来分区/dev/sdc上已经有文件系统,mount后还能够正常使用;若是没有文件系统,也能够和通常的设备同样作先作文件系统,而后mount并使用之。
mount /dev/mapper/cachedev /mnt
重作Flashcache,首先须要umount相应分区,而后若是须要从新作Flashcache:
umount /mnt
dmsetup remove cachedev
flashcache_destroy /dev/sdb

若是须要重建,再安装上面的flashcache_create重建就能够了。

参考资料:

http://blog.csdn.net/kidd_3/article/category/905673

http://www.sebastien-han.fr/blog/2012/11/15/make-your-rbd-fly-with-flashcache/

http://www.sebastien-han.fr/blog/2014/10/06/ceph-and-enhanceio/

http://www.orczhou.com/index.php/2010/10/how-to-setup-flashcace/

http://www.ningoo.net/html/2012/all_things_about_flashcache_4.html

相关文章
相关标签/搜索