专栏首页云存储技术团队裸盘存储引擎的实现(一)
原创

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

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

什么是裸盘存储引擎

单机存储引擎负责高效的组织数据、索引数据、保存数据,为上层应用提供易用的接口。有一类存储引擎为了得到更高的性能,会跨过文件系统这一层调用,直接操作裸盘。那么如何实现这类存储引擎呢?本文希望以 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

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Linux系统消息队列框架Kafka单机搭建

    前言 Kafka简介 Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala编写,它以可水平扩展和高吞吐率而被广泛使用。目前越来越多的...

    用户1208223
  • 搭建腾讯云Linux服务器(Centos6)入门教程

    因为腾讯云性能还可以,而且有学生价,博主目前也算是个学生哈,学生价的话可以¥1/月,所以对学生来说还是很优惠的!所以本文就说搭建腾讯云

    用户1208223
  • 部署项目到linux

    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20181213203725979.png?x-oss-proce

    微醺
  • win10+1080Ti+双硬盘(SSD+HDD)下安装Ubuntu16.04双系统

    环境: * SSD上已经装的win10 * 另一块机械硬盘上有空余的200G,用来装Ubuntu * 1080Ti显卡 * 技嘉b150m主板

    对角巷法师
  • 腾讯云服务器web环境配置教程

    腾讯云服务器是现在越来越多站长以及企业建站的首选了,因为腾讯云背靠腾讯这颗大树,有10亿微信用户和10亿QQ用户流量考验验做为背书,有足够的技术实力和奖金实力让...

    追梦者
  • Linux常用命令及获取帮助

    who am i ~ 除了用户名,还显示登陆的终端、当前的日期和时间以及所使用的计算机的IP地址

    于小勇
  • Linux系统安装配置MongoDB数据库

    用户1208223
  • Oracle递归查询start with connect by prior

    start with:表示以什么为根节点,不加限制可以写1=1,要以id为123的节点为根节点,就写为start with id =123

    用户1208223
  • UNIX和Linux操作系统概述

    UNIX的设计理念:在UNIX系统中所有的东西都是文件,所有系统配置数据都存储在正文文件中,每个系统命令都很小、只完成单一功能,避免使用俘获用户的接口,将多个程...

    于小勇
  • Linux搭建gcc编辑器教程

    ##前言## 对于预装了yum的Linux系统安装gcc编辑器就及其简易,只需执行如下命令即可

    用户1208223

扫码关注云+社区

领取腾讯云代金券