首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >裸盘存储引擎的实现(一)

裸盘存储引擎的实现(一)

原创
作者头像
刘畅__
修改2019-02-21 17:48:06
4K1
修改2019-02-21 17:48:06
举报

导读:如何打开、读写块设备。如何知道块设备大小以及设备属性?

什么是裸盘存储引擎

单机存储引擎负责高效的组织数据、索引数据、保存数据,为上层应用提供易用的接口。有一类存储引擎为了得到更高的性能,会跨过文件系统这一层调用,直接操作裸盘。那么如何实现这类存储引擎呢?本文希望以 Ceph BlueStore 为例子,介绍一下其中的实现方法。

怎么实现一个裸盘存储引擎

读写块设备

裸盘对于操作系统来说,就是一个类型为block的文件,也称之为块设备。在 BlueStore 的实现中,对于块设备作了一个抽象,声明了一个基类 BlockDevice,并实现了两个子类 KernelDevice 和 NVMEDevice,来分别对应普通的块设备以及 NVMe 块设备。

在 KernrlDevice::open 方法中,包含了打开块设备以供读写的实现。

open(path.c_str(), O_RDWR |  O_DIRECT);

通过阅读代码可以知道,BlueStore 使用 DirectIO 加上 libaio 的方式来进行读写操作。使用 O_DIRECT 是为了跨过 page cache 的影响,所有的存储与缓存逻辑都由我们自己实现。使用 aio 是因为用了 O_DIRECT 直接操作块设备,操作肯定会被这些IO操作阻塞。通过 libaio 来避免数据IO阻塞前台操作。

O_DIRECT (since Linux 2.4.10)
              Try to minimize cache effects of the I/O to and from this
              file.  In general this will degrade performance, but it is
              useful in special situations, such as when applications do
              their own caching.  File I/O is done directly to/from user-
              space buffers.  The O_DIRECT flag on its own makes an effort
              to transfer data synchronously, but does not give the
              guarantees of the O_SYNC flag that data and necessary metadata
              are transferred.  To guarantee synchronous I/O, O_SYNC must be
              used in addition to O_DIRECT.  See NOTES below for further
              discussion.

aio 简单介绍

说到 aio,会有三个东西:

  1. posix aio,在用户态使用 glic 实现,维护一个线程池来模拟异步IO。接口为 aio_read/aio_write/aio_xxxx。性能较差。
  2. linux aio,linux 特有的 aio 实现,接口为 aio_submit/aio_cancel 等5个函数。
  3. libaio,oracle 对 linux aio 的包装。

取块设备大小

作为一个存储引擎,应当为上层调用方提供当前存储空间利用率接口。那么如何获取一个块设备有多大呢?

可以使用 ioctl 函数的 BLKGETSIZE/BLKGETSIZE64 来获取。BLKGETSIZE 返回的是有多少块(每块是512字节)。所以最多获取 2TB 块设备的大小(2*32 512 byte = 2TB)。为了支持更大的设备,在较新的内核上支持了 BLKGETSIZE64,返回一个 int64 类型的数字,表示块设备有多少字节。

#include <fcntl.h>
#include <linux/fs.h>

main(int argc, char **argv)
{
  int fd;
  unsigned long numblocks=0;

  fd = open(argv[1], O_RDONLY);
  ioctl(fd, BLKGETSIZE, &numblocks);
  close(fd);
  printf("Number of blocks: %lu, this makes %.3f GB\n", numblocks, 
        (double)numblocks * 512.0 / (1024 * 1024 * 1024));
}

microHOWTO: Get the size of a Linux block special device in C

如何获取设备的属性

属性包括块设备是否是SSD?是否支持 discard?在 linux 环境下提供了 procfs 的方式来获取这些信息。设备的属性在 /sys/block/{device name}/queue/ 目录下,例如我们可以通过 /sys/block/sda/queue/rotational 文件来获取块设备是不是SSD。

➜  ~ ll /sys/block/sda/queue/                         
total 0
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 add_random
-r--r--r-- 1 root root 4.0K 8月  28 19:41 chunk_sectors
-r--r--r-- 1 root root 4.0K 8月  28 19:41 dax
-r--r--r-- 1 root root 4.0K 8月  28 19:41 discard_granularity
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 discard_max_bytes
-r--r--r-- 1 root root 4.0K 8月  28 19:41 discard_max_hw_bytes
-r--r--r-- 1 root root 4.0K 8月  28 19:41 discard_zeroes_data
-r--r--r-- 1 root root 4.0K 8月  28 19:41 hw_sector_size
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 io_poll
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 io_poll_delay
drwxr-xr-x 2 root root    0 8月  28 19:41 iosched
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 iostats
-r--r--r-- 1 root root 4.0K 8月  28 19:41 logical_block_size
-r--r--r-- 1 root root 4.0K 8月  28 19:41 max_discard_segments
-r--r--r-- 1 root root 4.0K 8月  28 19:41 max_hw_sectors_kb
-r--r--r-- 1 root root 4.0K 8月  28 19:41 max_integrity_segments
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 max_sectors_kb
-r--r--r-- 1 root root 4.0K 8月  28 19:41 max_segments
-r--r--r-- 1 root root 4.0K 8月  28 19:41 max_segment_size
-r--r--r-- 1 root root 4.0K 8月  28 19:41 minimum_io_size
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 nomerges
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 nr_requests
-r--r--r-- 1 root root 4.0K 8月  28 19:41 optimal_io_size
-r--r--r-- 1 root root 4.0K 8月  28 19:41 physical_block_size
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 read_ahead_kb
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 rotational
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 rq_affinity
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 scheduler
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 wbt_lat_usec
-rw-r--r-- 1 root root 4.0K 8月  28 19:41 write_cache
-r--r--r-- 1 root root 4.0K 8月  28 19:41 write_same_max_bytes
-r--r--r-- 1 root root 4.0K 8月  28 19:41 write_zeroes_max_bytes
-r--r--r-- 1 root root 4.0K 8月  28 19:41 zoned
➜  ~ cat /sys/block/sda/queue/rotational 
1

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是裸盘存储引擎
  • 怎么实现一个裸盘存储引擎
    • 读写块设备
      • 取块设备大小
        • 如何获取设备的属性
        相关产品与服务
        对象存储
        对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档