什么是bcache
转载请注明出处:http://blog.csdn.net/liumangxiong
bcache是linux内核块层cache。它使用类似SSD来作为HDD硬盘的cache,从而起到加速作用。
HDD硬盘便宜并且空间更大,SSD速度快但更贵。如果能两者兼得,岂不快哉?bcache能做到。
bcache使用SSD作为其他块设备cache。类似ZFS的L2Arc,但bcache还增加了写回策略,并且是与文件系统无关的。bcache被设计成只需要最小的代价,无需配置就能在所有环境中工作。默认状态下bcache不缓存顺序IO,只缓存随机读写。bcache适用于桌面、服务器,高级存储阵列,甚至是嵌入式环境。
设计bcache目标是让被缓存设备与SSD一样快(包括缓存命中、缓存不命中、透写和回写)。现在还未达到初衷,特别是顺序写。同时测试结果表明离目标很接近,甚至有些情况下表现更好,例如随机写。
bcache是数据安全的。对于写回策略缓存来说,可靠性是非常重要的,出错就意味着丢失数据。bcache是用电池备份阵列控制器的替代选择,同时也要求bcache在异常掉电时也是数据安全的。对于写而言,必须在所有数据写到可靠介质之后才能向上层返回写成功,在异常掉电情况下,写不能是部分完成的。大量工作已经投入到这部分数据安全的工作中。
bcache性能设计目标是等同于SSD。最大程度上去最小化写放大,并避免随机写。bcache将随机写转换为顺序写,首先写到SSD,然后回写缓存使用SSD缓存大量的写,最后将写有序写到磁盘或者阵列上。对于RAID6阵列,随机写性能很差,还要花费不菲的价格购买带有电池保护的阵列控制器。现在有了bcache,你就可以直接使用linux自带的优秀软RAID,甚至可以在更廉价的硬件上获取更高的随机写性能。
特性
1、一个缓存设备可以作为多个设备的缓存,并且可以在设备运行时动态添加和删除缓存。
2、异常关机恢复,只有当写到磁盘后缓存才会确认写完成。
3、正确处理写阻塞和刷缓存
4、支持writethrough, writeback和writearound
5、检测并避开顺序IO(可配置关闭该选项)
6、当检测到SSD延迟超过配置边界值,减少到SSD流量(当一个SSD作为多个磁盘缓存时使用)
7、缓存不命中时预读(默认关闭)
8、高性能的writeback实现:脏数据都是排序后再回写。如果设置了writeback水位线,PD控制器会根据脏数据比例来平滑处理到
后台writeback流量。
9、使用高效率了B+树,bcache随机读可以达到1M IOPS
10、稳定,已经有产品应用
性能
7/25/12 随机测试
7/25/12 随机测试
在我的测试机上,我将SSD盘划分为两个相同大小的分区,一个分区用于测试SSD裸盘,另一个作为硬盘缓存。
bcache配置修改:cache_mode设置为writeback,writeback_percent设置为40。(如果writeback_percent不为0,bcache使用PD控制器根据缓存的脏数据块来平滑处理下发到磁盘的流量)。同时还关闭了拥塞阀值,因为当SSD延迟达到极限时,
如果bcache切换到writethrough将会影响结果。
SSD盘为Intel 160G MLC SSD,也就是Intel SSDSA2M160。
FIO作为性能测试,测试脚本如下:
[global] randrepeat=1 ioengine=libaio bs=4k ba=4k size=8G direct=1 gtod_reduce=1 norandommap iodepth=64
FIO运行在SSD裸设备上,但对于这类性能测试软件来说应该没有影响。
裸SSD设备上随机写测试结果如下:
root@utumno:~# fio ~/rw4k
randwrite: (g=0): rw=randwrite, bs=4K-4K/4K-4K, ioengine=libaio, iodepth=64
fio 1.59
Starting 1 process
Jobs: 1 (f=1): [w] [100.0% done] [0K/49885K /s] [0 /12.2K iops] [eta 00m:00s]
randwrite: (groupid=0, jobs=1): err= 0: pid=1770
write: io=8192.3MB, bw=47666KB/s, iops=11916 , runt=175991msec
cpu : usr=4.33%, sys=14.28%, ctx=2071968, majf=0, minf=19
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
issued r/w/d: total=0/2097215/0, short=0/0/0
Run status group 0 (all jobs):
WRITE: io=8192.3MB, aggrb=47666KB/s, minb=48810KB/s, maxb=48810KB/s, mint=175991msec, maxt=175991msec
Disk stats (read/write):
sdb: ios=69/2097888, merge=0/3569, ticks=0/11243992, in_queue=11245600, util=99.99%
添加了bcache:
root@utumno:~# fio ~/rw4k
randwrite: (g=0): rw=randwrite, bs=4K-4K/4K-4K, ioengine=libaio, iodepth=64
fio 1.59
Starting 1 process
Jobs: 1 (f=1): [w] [100.0% done] [0K/75776K /s] [0 /18.5K iops] [eta 00m:00s]
randwrite: (groupid=0, jobs=1): err= 0: pid=1914
write: io=8192.3MB, bw=83069KB/s, iops=20767 , runt=100987msec
cpu : usr=3.17%, sys=13.27%, ctx=456026, majf=0, minf=19
IO depths : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
submit : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
complete : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
issued r/w/d: total=0/2097215/0, short=0/0/0
Run status group 0 (all jobs):
WRITE: io=8192.3MB, aggrb=83068KB/s, minb=85062KB/s, maxb=85062KB/s, mint=100987msec, maxt=100987msec
Disk stats (read/write):
bcache0: ios=0/0, merge=0/0, ticks=0/0, in_queue=0, util=0.00%
添加了bcache之后IOPS为18.5K,裸SSD设备为12.2K。bcache表现更佳是因为bcache按顺序将写请求发送到SSD,但额外加入了更新索引的开销。bcache对随机写做了优化,bcache还从高IO深度(64)获益,因为在高IO深度的情况下就可以将多次下标更新合并为一次写请求。
高IO深度就代表着高系统负载,当IO深度下调时IOPS也出现变化:
IO depth of 32: bcache 20.3k iops, raw ssd 19.8k iops
IO depth of 16: bcache 16.7k iops, raw ssd 23.5k iops
IO depth of 8: bcache 8.7k iops, raw ssd 14.9k iops
IO depth of 4: bcache 8.9k iops, raw ssd 19.7k iops
SSD性能在不同IO深度时出现了波动。对于不同的写模型会有不同的结果,我们只关注两者的相对数值。
当测试随机4K写,IO深度为1时,bcache写次数是裸SSD设备的两倍:每一次写都需要再更新一次索引。
随机读
IO depth of 64: bcache 29.5k iops, raw ssd 25.4k iops
IO depth of 16: bcache 28.2k iops, raw ssd 27.6k iops
bcache略胜一筹,可能跟要读的数据相关。这里的结论是随机读时bcache与裸SSD读性能是相同的。
这里要注意的是,读4K随机写下去的数据,这样的测试模型对于bcache是不好的。这意味btree都是4K大小,btree将比通常时候大得多。在实际应用中,平均大小是100K。btree变大就意味着索引占用更大的内存空间,并且有一部分是在二级索引。根据个人经验这些开销在大型机器IOPS超过500K时才会有实际影响。
如果大家有其他的测试方法或者我的测试方法中有什么问题请通知邮件告诉我。
常见问题
关机、设备移除
系统关机时cache仍然是脏的,就是说后端磁盘的数据并不可靠。如果要保证后端磁盘数据是安全的,就需要手动移动cache或者将cache设置为writethrough模式。
自动挂载
bcache会自动匹配cache和后端设备。匹配过程与设备对系统可用的次序没有关系。
带bcache的根目录分区
为了让根分区能够使用bcache,需要添加rootdelay=3到启动参数,这样才能让udev规则在系统mount根文件系统之前运行。
已格式化过的磁盘或分区
如果一个分区或者磁盘设备启动时没有创建bcache,可能是因为超级块发生错误。为了让bcache能够正确检测到之前的设备,udev规则会首先检查是否符合bcache规则和blkid检查。udev规则检查设备超级块从而识别文件系统类型,如果该超级块不符合bcache文件系统类型那么就不会添加bcache。
# cat /usr/lib/udev/rules.d/61-bcache.rules
....
# Backing devices: scan, symlink, register
IMPORT{program}="/sbin/blkid -o udev $tempnode"
# blkid and probe-bcache can disagree, in which case don't register
ENV{ID_FS_TYPE}=="?*", ENV{ID_FS_TYPE}!="bcache", GOTO="bcache_backing_end"
...
# lsblk -o NAME,MAJ:MIN,RM,SIZE,TYPE,FSTYPE,MOUNTPOINT,UUID,PARTUUID
NAME MAJ:MIN RM SIZE TYPE FSTYPE MOUNTPOINT UUID PARTUUID
sda 8:0 0 111.8G disk
├─sda1 8:1 0 3G part vfat /esp 7E67-C0BB d39828e8-4880-4c85-9ec0-4255777aa35b
└─sda2 8:2 0 108.8G part ext2 93d22899-cd86-4815-b6d0-d72006201e75 baf812f4-9b80-42c4-b7ac-5ed0ed19be65
sdb 8:16 0 931.5G disk
└─sdb1 8:17 0 931.5G part ntfs FAD2B75FD2B71EB7 90c80e9d-f31a-41b4-9d4d-9b02029402b2
sdc 8:32 0 2.7T disk bcache 4bd63488-e1d7-4858-8c70-a35a5ba2c452
└─bcache1 254:1 0 2.7T disk btrfs 2ff19aaf-852e-4c58-9eee-3daecbc6a5a1
sdd 8:48 0 2.7T disk bcache ce6de517-7538-45d6-b8c4-8546f13f76c1
└─bcache0 254:0 0 2.7T disk btrfs 2ff19aaf-852e-4c58-9eee-3daecbc6a5a1
sde 8:64 1 14.9G disk
└─sde1 8:65 1 14.9G part ext4 / d07321b2-b67d-4daf-8022-f3307b605430 5d0a4d76-115f-4081-91ed-fb09aa2318d
在上面的例子中有一个分区之前是ext2文件系统。bcache将通过以下指令自动构建:
# make-bcache -B /dev/sdc /dev/sdd -C /dev/sda2
因为设备/dev/sdc和/dev/sdd标识了bcache文件系统,因此会在系统启动时自动添加,而/dev/sda2则需要手动添加。在/dev/sda2偏移1024处仍残留有之前文件系统的超级块信息,而bcache信息是从4096偏移开始记录,修复的方法是:
# dd if=/dev/zero count=1 bs=1024 seek=1 of=/dev/sda2
在系统重启之后所有磁盘被正确识别:
# lsblk -o NAME,MAJ:MIN,RM,SIZE,TYPE,FSTYPE,MOUNTPOINT,UUID,PARTUUID
NAME MAJ:MIN RM SIZE TYPE FSTYPE MOUNTPOINT UUID PARTUUID
sda 8:0 0 111.8G disk
├─sda1 8:1 0 3G part vfat /esp 7E67-C0BB d39828e8-4880-4c85-9ec0-4255777aa35b
└─sda2 8:2 0 108.8G part bcache 93d22899-cd86-4815-b6d0-d72006201e75 baf812f4-9b80-42c4-b7ac-5ed0ed19be65
├─bcache0 254:0 0 2.7T disk btrfs 2ff19aaf-852e-4c58-9eee-3daecbc6a5a1
└─bcache1 254:1 0 2.7T disk btrfs 2ff19aaf-852e-4c58-9eee-3daecbc6a5a1
sdb 8:16 0 931.5G disk
└─sdb1 8:17 0 931.5G part ntfs FAD2B75FD2B71EB7 90c80e9d-f31a-41b4-9d4d-9b02029402b2
sdc 8:32 0 2.7T disk bcache 4bd63488-e1d7-4858-8c70-a35a5ba2c452
└─bcache1 254:1 0 2.7T disk btrfs 2ff19aaf-852e-4c58-9eee-3daecbc6a5a1
sdd 8:48 0 2.7T disk bcache ce6de517-7538-45d6-b8c4-8546f13f76c1
└─bcache0 254:0 0 2.7T disk btrfs 2ff19aaf-852e-4c58-9eee-3daecbc6a5a1
sde 8:64 1 14.9G disk
└─sde1 8:65 1 14.9G part ext4 / d07321b2-b67d-4daf-8022-f3307b605430 5d0a4d76-115f-4081-91ed-fb09aa2318dd
同样地,残留超级块还会引起类似的其他错误。