bcache总结
参考链接
https://www.bbsmax.com/A/ZOJPXRpxJv/
https://blog.csdn.net/tao_627/article/details/78296332
https://www.cnblogs.com/zimufeng/p/6640439.html
https://www.cnblogs.com/sunhaohao/archive/2017/07/03/sunhaohao.html
https://www.pianshen.com/article/397441087/
https://ypdai.github.io/2018/07/13/bcache%E9%85%8D%E7%BD%AE%E4%BD%BF%E7%94%A8/
定义:
bcache是linux内核块层cache.它使用类似SSD来作为HDD硬盘的cache,从而起到加速作用。
bcache使用SSD作为其他块设备的cache.类似ZFS的L2Arc,但bcache还增加了写回策略,并且是与文件系统无关的。默认状态下bcache不缓存顺序IO,只缓存随机读写。
bcache是数据安全的。对于写回策略缓存来说,可靠性是非常重要的,出错就意味着丢失数据。bcache是用电池备份阵列控制器的替代选择,同时也要求bcache在异常掉电时也是数据安全的。对于写而言,必须在所有数据写到可靠介质之后才能向上层返回写成功。如果在写一个大文件时掉电了,则写入是失败的。异常掉电数据安全是指 cache 中的脏数据是不会丢的,不像内存中的脏数据掉电就没了。
特性:
- 一个缓存设备可以作为多个设备的缓存,并且可以在设备运行时动态添加和删除缓存。
- 只有当写到磁盘后缓存才会确认写完成。
- 正确处理写阻塞和刷缓存。
- 支持writethrough, writeback和writearound等写缓存模式。
- 检测并避开顺序IO(可配置关闭该选项)。
- 当检测到SSD延迟超过配置边界值,减少到SSD流量(当一个SSD作为多个磁盘缓存时使用)。
- 缓存不命中时预读(默认关闭)
- 高性能的 writeback 实现:脏数据都是排序后再回写。如果设置了 writeback 水位线,PD控制器会根据脏数据比例来平滑处理到后台的writeback流量。
- 使用高效率的B+树,bcache随机读可以达到1M IOPS。
- 稳定。
设计细节:
- bcache针对SSD的性能测试设计--它仅分配可擦写块(erase block size)的bucket,使用混合bree/log去追踪缓存内容(从单个扇区到bucket大小的任何地方),它以不惜任何代价来设计避免随机写;它顺序地填满一个个可擦写块(erase block), 然后在重用该块之前清除该块。
- 支持writethrough和writeback缓存模式。writeback默认关闭,但可以在运行时随时打开或关闭。bcache竭尽全力来保护你的数据--它可靠地处理unclean的关闭。(甚至根本就没有clean shutdown的概念,因为数据写到可靠的磁盘,完成之前不会返回)。
- writeback缓存能用于绝大部分buffering write的缓存--总是顺序地write脏数据到后端设备,从index的起始到末尾扫描。
- writeback缓存能用于绝大部分buffering write的缓存--总是顺序地write脏数据到后端设备,从index的起始到末尾扫描。
- SSD擅长随机IO,通常对缓存大序列化IO,没有优化空间,Bcache会探测顺序IO并跳过它,SSD只优化随机IO。bcache也会对每次task中的IO size的平均大小持续跟踪,只要平均大小超过cutoff,它将会跳过该task中的所有IO,而非在每次查找后缓存前512K字节,备份和大文件复制会整个跳过缓存设备。
- 当flash闪存上发生data IO error时,它会尽量从磁盘读取数据来恢复,恢复失败就使缓存对象失效。对不可恢复的错误(元数据或脏数据),caching设备会自动禁用;假如caching设备中有脏数据存在,首先会禁用writeback,等所有的脏数据都写到磁盘里。
使用操作:
你需要使用bcache-tools代码库中的make-bcache,在使用之前,cache设备和backing设备都必须格式化:
-
make-bcache -B /dev/sdb make-bcache -C /dev/sdc
-
make-bcache可以同时格式化多个设备,假如你同时格式化后端设备和缓存设备,无须手动绑定
make-bcache -B /dev/sda /dev/sdb -C /dev/sdc -
bcache-tools现在加入了udev rules,bcache设备能立即被内核探测到,如果没有udev,你需要手动这样注册
echo /dev/sdb > /sys/fs/bcache/register echo /dev/sdc > /sys/fs/bcache/register注册后端设备将可在/dev中看到bcache,然后你可以格式化它,之后可以像普通磁盘一样使用。
注意:第一次使用全新
bcache设备,它通常会运行在passthrough模式,所有读写的操作都在硬盘上,直到你将他板到一台缓存设备,如果你想以后使用bcache,推荐你搭建所有的慢速设备为bcache的后端设备,不带caching设备,你能在以后选择追加一台caching设备。 -
设备实现
/dev/bcache
以及(和udev)
/dev/bcache/by-uuid//dev/bcache/by-label/
错误处理
总体原则:
Bcache尝试透明地处理来自缓存设备的 IO 错误,而不会影响正常操作;如果它看到太多错误(阈值可配置,并且默认为0),它将关闭缓存设备并将所有 backing device 切换到 passthrough 模式。
- 对于从缓存读取,如果它们出现错误,将从 backing device 重新尝试读取
- 对于 writethroungh writes,如果写入缓存错误,我们只需切换到缓存中的 lba(Logical Block Address, LBA) 上使数据无效(即我们为绕过 cache write 将数据写到后端设备)
- 对于writeback writes,我们目前将该错误传递给文件系统/用户空间。这可以改进 - 我们可以尝试绕过缓存的写入,所以小心避免写入错误。
- 对于分离操作,我们首先尝试刷新任何脏数据到后端设备(如果我们以 writeback 模式运行)。但是,如果它无法读取脏数据,当前它将不会做任何操作。
How to
-
从一个丢失的
caching设备启动bcacheecho /dev/sdb1 > /sys/fs/bcache/register [ 119.844831] bcache: register_bcache() error opening /dev/sdb1: device already registered # 下一步,如果有cache设备的话,你尽量注册它,然而假如没有,或是cache设备因为某种原因注册失败,在没有cache设备的情况下,你仍然能够启动bcache,像下面这样 host:/sys/block/sdb/sdb1/bcache echo 1 > running # 注意如果当前在writeback模式下,这会导致数据丢失。 -
bcache找不到cacheecho 0226553a-37cf-41d5-b3ce-8b1e944543a8 > attach [ 1933.455082] bcache: bch_cached_dev_attach() Couldn't find uuid for md5 in set[ 1933.478179] bcache: __cached_dev_store() Can't attach 0226553a-37cf-41d5-b3ce-8b1e944543a8 [ 1933.478179] : cache set not found 这种情况,cache设备可能在系统启动时没有注册,或是消失后又回来了,需要再次注册一下 echo /dev/sdh2 > /sys/fs/bcache/register -
擦除缓存设备
wipefs -a /dev/sdh 216 bytes were erased at offset 0x1018 (bcache)they were: c6 85 73 f6 4e 1a 45 ca 82 65 f5 7f 48 ba 6d 81 在重启系统后,开启bcache,重建cache设备并开启它: make-bcache -C /dev/sdh UUID: 7be7e175-8f4c-4f99-94b2-9c904d227045Set UUID: 5bc072a8-ab17-446d-9744-e247949913c1version: 0nbuckets: 106874block_size: 1bucket_size: 1024nr_in_set: 1nr_this_dev: 0first_bucket: 1[ 650.511912] bcache: run_cache_set() invalidating existing data[ 650.549228] bcache: register_cache() registered cache device sdh2 /sys/block/md5/bcache echo 1 > running 绑定新的cache设备 host:/sys/block/md5/bcache echo 5bc072a8-ab17-446d-9744-e247949913c1 > attach [ 865.276616] bcache: bch_cached_dev_attach() Caching md5 as bcache0 on set 5bc072a8-ab17-446d-9744-e247949913c1 -
移除或是替换缓存设备
host:/sys/block/sda/sda7/bcache echo 1 > detach [ 695.872542] bcache: cached_dev_detach_finish() Caching disabled for sda7 host:~#wipefs -a /dev/nvme0n1p4wipefs: error: /dev/nvme0n1p4: probing initialization failed: Device or resource busyOoops, it's disabled, but not unregistered, so it's still protected我们需要取消注册host:/sys/fs/bcache/b7ba27a1-2398-4649-8ae3-0959f57ba128# ls -l cache0lrwxrwxrwx 1 root root 0 Feb 25 18:33 cache0 -> ../../../devices/pci0000:00/0000:00:1d.0/0000:70:00.0/nvme/nvme0/nvme0n1/nvme0n1p4/bcache/host:/sys/fs/bcache/b7ba27a1-2398-4649-8ae3-0959f57ba128# echo 1 > stopkernel: [ 917.041908] bcache: cache_set_free() Cache set b7ba27a1-2398-4649-8ae3-0959f57ba128 unregistered现在我们才能清除数据host:~# wipefs -a /dev/nvme0n1p4/dev/nvme0n1p4: 16 bytes were erased at offset 0x00001018 (bcache): c6 85 73 f6 4e 1a 45 ca 82 65 f5 7f 48 ba 6d 81 -
dm-crypt和bcache首先搭建非加密的bcache,然后在/dev/bcache
上层安装dmcrypt,这会更快,假如你dmcrypt后端和caching设备的时候,同时在顶层安装bcache。[需要benchmarks?] -
停止并释放一个注册过的bcache,擦除之后重新生成
假如你需要释放所有的bcache引用,以便你能运行fdisk并重新注册一个变动的分区表,假如上面有任何活跃的backing或是caching设备,这都不会成功 1)/dev/bcache*有东西吗?(有时没有) 假如存在,很简单: host:/sys/block/bcache0/bcache# echo 1 > stop 2)但是假如你的后端设备不在,这不会成功: host:/sys/block/bcache0# cd bcachebash: cd: bcache: No such file or directory 这种情况,你或许必须注销引用该待释放bcache的dmcrypt的块设备 host:~# dmsetup remove oldds1bcache: bcache_device_free() bcache0 stoppedbcache: cache_set_free() Cache set 5bc072a8-ab17-446d-9744-e247949913c1 unregistered 这导致后端bcache从/sys/fs/bcache中移除,然后再次重用,This would be true of any block device stacking where bcache is a lower device. 3)另一方面,你也能看看/sys/fs/bcache/ host:/sys/fs/bcache# ls -l */{cache?,bdev?}lrwxrwxrwx 1 root root 0 Mar 5 09:39 0226553a-37cf-41d5-b3ce-8b1e944543a8/bdev1 -> ../../../devices/virtual/block/dm-1/bcache/lrwxrwxrwx 1 root root 0 Mar 5 09:39 0226553a-37cf-41d5-b3ce-8b1e944543a8/cache0 -> ../../../devices/virtual/block/dm-4/bcache/lrwxrwxrwx 1 root root 0 Mar 5 09:39 5bc072a8-ab17-446d-9744-e247949913c1/cache0 -> ../../../devices/pci0000:00/0000:00:01.0/0000:01:00.0/ata10/host9/target9:0:0/9:0:0:0/block/sdl/sdl2/bcache/ 设备名将显示哪个UUID是相关的,在该目录下cd,然后stop the cache: host:/sys/fs/bcache/5bc072a8-ab17-446d-9744-e247949913c1# echo 1 > stop 这将会释放bcache引用,让你重用其它目的的分区。
性能调优
-
Backing device 对齐
bcache中的默认(metadata)元数据大小为8k。
如果你的 Backing device 是基于 RAID 的,那么请务必使用
make-bcache --data-offset将其与你的 RAID 条带大小对齐(即设置为 raid 条带大小的倍数)。--可避免写放大。如果考虑未来RAID的扩展,则用RAID条带大小乘以一序列素数,来得到你想要的磁盘倍数,建议这样计算data-offset的值。For example: If you have a 64k stripe size, then the following offset
would provide alignment for many common RAID5 data spindle counts:
64k * 2223357 bytes = 161280k -
写入性能差
假如写入性能不达预期,你或许想运行在writeback模式下面,这并非默认的模式。(writeback模式之所以不是默认模式,不是因为不成熟,而是因为该模式可能在某些情况下丢失数据。)
默认 bcache 的 cache_mode 是 writeround,改成 writeback,提高写入性能。echo writeback > /sys/block/bcache0/bcache/cache_mode
-
性能差,或者到SSD的流量未达预期
默认情况下,bcache不会缓存所有内容.它尝试跳过顺序IO,因为你真正想要缓存的是随机IO。
如果你复制一个10GB的文件,你可能也不希望将 cache 中10GB 的随机访问数据从缓存中刷新走(cache 可用空间不够时,根据lru算法将冷数据回写到backing device)。
但是假如你要对读缓存进行基准测试,使用 fio写一个8 GB的测试文件,你需要禁用它(允许顺序IO):
echo 0 > /sys/block/bcache0/bcache/sequential_cutoff
调整 backing 设备的顺序IO 阈值,表示 bcache0 设备的顺序IO大于4MB 时,大于 4MB 的部分不会走 SSD 设备,也不会缓存到 ssd,而是直接读写 backing 设备。(default:4M)
echo 4M > /sys/block/bcache0/bcache/sequential_cutoff -
流量仍然进入后端设备(spindle)/仍旧得到cache miss
现实中SSD并不总是能跟上硬盘的速度,特别是那些慢速的SSD,在一块SSD为很多HDD做缓存设备,或者出现大比例的序列化IO的情况下。假如你想避免SSD成为瓶颈,就让每件事慢下来。
bcache会跟踪每个IO,如果IO的时间超过阈值,则旁路cache设备,直接读写backing设备。 -
为避免bcache追踪缓存设备的延迟,假如延迟超过阈值时,逐步阻塞流量(通过降低顺序旁路来实现)
如果你的SSD足够强大,可以不跟踪,减少跟踪的开销。
如果你需要的话,可以设置阈值为0来禁用它echo 0 > /sys/fs/bcache/
/congested_read_threshold_us echo 0 > /sys/fs/bcache/
/congested_write_threshold_us 关闭旁路的另一个好处是,所有的离散读写都会经过cache设备,从而不会导致cache missing。
默认情况下当读请求超过2ms,写请求超过20ms时,旁路cache设备。
The default is 2000 us (2 milliseconds) for reads, and 20000 for writes. -
某些数据仍然cache miss
最后一个困扰人们的问题事实上是个老bug,由于缓存连贯性(cache coherency)对cache miss的处理方式。
当btree node慢了之后,cache miss时并不能对新数据插入key,对应数据也不能写到cache中。
事实上这并不是问题,因为只要cache写到来,将会导致btree node分裂(split),根本无需可观的
写流量,这很难观察到(特别当bcache的btree nodes很多,要索引设备上大部分区域的时候)
但当benchmark的时候,假如你想通过大量数据,让它成为缓存中的热点时,不需要其它流量,这可能是个问题。解决方法:
通过写操作来让cache形成热点,或使用测试分支的代码(那里对该问题做了修复)
实际操作
知识点:
lsblk看到的是后端存储,缓存只是在配置那里。
# 查询缓存盘信息
bcache-super-show
# 配置前端缓存盘。
make-bcache -C /dev/sdb
# 删除前端缓存盘
echo 1 >/sys/fs/bcache/8cae4fac-1312-4b0a-8bf7-2142dae5a334/unregister
# 配置后端缓存盘之前先擦除数据
wipefs -a /dev/sdc /dev/sdbd
# 配置后端存储盘
make-bcache -B /dev/sdb
# 移除后端存储盘
echo 1 > /sys/block/bcache0/bcache/stop
# 将缓存盘给bcache0, 将缓存盘给bcache1
# 建立映射关系
echo "8cae4fac-1312-4b0a-8bf7-2142dae5a334" > /sys/block/bcache0/bcache/attach
#将缓存盘从bcache0中移除。
# 解除映射关系
echo "8cae4fac-1312-4b0a-8bf7-2142dae5a334" > /sys/block/bcache0/bcache/detach

浙公网安备 33010602011771号