存储数据包的一生
最近认认真真学习了一个叫《Life of a Storage Packet》讲座,借助这个讲座将整个存储的过程理解了下,不放过任何一个有疑问的点。
这篇文章算是对讲座的理解和自己收获的总结,同时也为那些对存储系统不够了解又想要了解的初学者,展现一个存储数据包的“生命”。
这个演讲主要聚焦在“整体的存储”,强调存储系统中各个基本元素的关系,并且尽可能简单、清楚地用一种不同的方式可视化一些存储的概念。
先上一张大图,可以说这篇文章目的就是解释这个图:
1. 整体视角
Application------NetWork
| |
| |
| |
Storage---------
可能经过网络,也可能不经过网络。
存储系统从整体的分层一览,包括了主机/应用,存储介质,存储网络。对于存储来说就做了一件事:
Here is a bit of data. Hold onto it. Give that same bit back to me when I ask for it.
2. Application视角
每个系统都有会有很多应用程序运行在CPU上,对于这些Application来说,他们觉得自己有很多很多足够的可用内存。
2.1 CPU和MMU
计算机系统中有一个“内存管理单元”(MMU,Memory Management Unit)的概念,MMU负责与DRAM内存直接通信,并且获得一些可用的“页”。
多租户:内存被某个进程(比如一个应用)独享,这些内存不能被其他进程重写。
地址:将CPU的物理地址翻译成独有的DRAM地址或者是很多行DRAMs
有了MMU以后,对于每个进程来说,他们就像是一个人独占了所有的内存一样。
2.2 访问内存
Application在他需要访问的时候,获取这些内存,在实际进行访问时,会发生如下事情:
-
Application会问操作系统“Hey,我需要一些可用内存”
-
操作系统向MMU说,“能给我一些可以使用内存页不?”
-
MMU把一些可用的内存页给操作系统
-
操作系统把这些可用的内存页给Application。
2.3 分配内存
在 2.2 中,获取的那些内存,实际是可以分布在内存中的任何地方的(非连续),MMU在把这些内存给应用的时候会进行初始化操作,当然,当应用不再访问这些内存页的时候,也会MMU也会负责回收这些内存。
2.4 加速访问
如果Application对内存的访问,每次都要都要从MMU获取的话,那太慢了,因此有个经验法则是:
Always put storage/memory as close to the CPU as possible
可以说在存储中,改善时间的限制是永恒不变的主题,然后访问DRAM的话,需要60-100ns的时间。
我们需要更快的访问,甚至达到“0”时间访问。
2.5 缓存的魔法
于是在CPU中增加了一些缓存,当然缓存也是分级别的,对于L1缓存大概花费1ns以内,L2缓存大概花费3-6ns,没错,这使得每次访问从60-100ns提升了几十倍!
2.6 更多的空间
如果DRAM中也没有足够的空间时,这是你需要更多的持久化存储,比如说磁盘。
当然直接去访问磁盘会非常的昂贵,当然这里指的是时间的花费非常昂贵。
在Jeff Dean大神的Software Engineering Advice from Building Large-Scale Distributed Systems给出了数据:
类型 | 时间 |
---|---|
L1缓存 | 1ns |
L2缓存 | 5ns |
主存 | 100ns |
硬盘 | 10,000,000ns |
- 时间单位
1s=1000 ms
1s=10^9 ns
例子
举个比较形象的例子:你需要快递送个包裹,
快递一个1公里(L1)、5公里(L2)外的包裹,oops,可能马云爸爸保证当日达;
快递100公里(DRAM)的包裹,11点前下单,当日达,不能再快了!;
快递1000万公里(Disk)的快递,啊亲,你真的需要快递吗?这可是从地球到月球(38.4万公里)十几个来回的距离啊亲。
ps: 这个例子仅供参考。只是为了理解 disk 比较慢而已。
2.7 下一站,使用存储设备
存储设备和RAM不太一样,不会和CPU直接进行“对话”,而是有一些其他的部分来帮助他们完成对话,我们在存储视角进一步去讲述。
Storage视角
3.1 块设备的基本概念
块存储的IO流
CPU和内存通过PCI总线(目前通常是PCIe)与存储进行连接,应用会向存储请求一段数据。
系统会将数据转换成地址和位置信息,并转换成某种协议的形式。
数据总线
CPU的指令需要转换或者说是进行适配,以便能够与存储设备进行“交流”,比如SCSI、IDE/ATA
SCSI系统
SCSI是一个很普遍、且向后兼容的,通常主要包含的组件有:
Initiator:一些服务用它发起请求,可以视为登陆或者适配的一部分
Target:物理存储设备,可以是单个磁盘或者磁阵
Service Delivery Subsystem:Initiator和Target之间的通信(通常是网线)
块设备
Block:块是存储介质上的物理或者逻辑单元,也是文件系统或者磁盘写入的最小单元,所有的存储(包括文件存储、对象存储)最终都是需要与block进行对话。
磁盘包括了盘面(Platter)、磁道(Track)、扇区(Sector)。盘面是一个圆,磁道是一个环,扇区是环上的一段,数据的位置影响性能。块由扇区组成,每一个块也有一个唯一的号码,文件系统的一切操作都是由对blocks操作构成。
3.2 文件与块
对于应用来说,他们看到的都是文件;而对于存储来说,看到是块。因此需要某种方式将他们联系起来。
对于文件来说,应用看到的是一个连续的“空间”,然而实际上,文件是由很多块组成的,而这些块就是磁盘上的块,这些块分布在磁盘的不同区域。
3.3 文件系统
在操作系统中,其内核中会有一个文件系统,文件系统维护着在磁盘上的文件名,文件系统知道这些文件与磁盘上块位置的对应关系,同时还需要管理着磁盘空间、权限、所属、加密、文件缓存等等。
驱动控制:硬盘被驱动控制来操控,接收文件系统的通过某种协议(比如SCSI)下发的一些I/O命令
卷管理:文件系统和设备驱动中间存在着卷管理,卷管理负责抽象出一层“假的”磁盘供操作系统使用.
3.4 文件系统与驱动
因此,对于文件系统来说,需要将应用程序所看到的“虚拟地址”翻译到真正的设备地址。
例如访问一个文件时,文件系统会先会先在找到对应的逻辑块地址(Logical Block Adress, LBA),然后通过scsi系统进一步访问,对应到磁盘上的物理块地址。
3.5 INODE
Inode是文件的原数据,用来记录文件的所述、权限、block信息等。
一个Inode会对应一个文件或目录,通过inode就可以将文件与某些block对应起来。
也就是说通过inode信息,就可以完全的找到一个文件,包括这个文件所对应的data block。
对于目录而言,data block包含了目录的内容,即该目录下文件及其这些文件对应inode的列表。
对于文件而言,data block则包含了文件的实际内容。
3.6 举个例子
执行命令的步骤
当执行 cat /home/foo.txt
命令时,会对foo.txt文件进行访问,经历了以下步骤:
-
获取”/“内容;
-
查找”home”的node信息(inode 38);
-
获取”home”目录内容;
-
查找”foo.txt”的inode信息(inode 40);
-
根据inode获得block numbers;
-
文件系统将block number转换为真正的block number(data block 101);
-
通过SCSI Controller读取block内容。
数据存储之路
至此,我们可以看到存储数据是这样走自己的路的:
-
应用程序说我要获取/home/foo.txt的内容
-
操作系统依次检查L1、L2、RAM中是否存在,若均不存在则在文件系统中查找
-
文件系统先检查Unified Buffer Cache中是否存在该文件,如果不存在则去目录中查找“home”文件
-
(访问磁盘)读取”home”目录的内容,并把inode信息放到buffer cache以便下次访问,最后根据目录内容查询到foo.txt的inode
-
(访问磁盘)读取foo.txt的inode,获取到data block号
-
(访问磁盘)文件系统读取data block,最终将数据返回给应用,并且把数据存储在L1、L2、RAM和UBC中,加速下次访问。
三次磁盘访问
我们可以看到,访问/home/foo.txt有3次磁盘访问:
第1次是读取home的inode,获取foo.txt的inode号
第2次是读取foo.txt的inode,获取data block号
第3次是读取data block,获取真正的内容
然而,我们对于机械硬盘来说,每次需要磁盘转到正确的地址才能访问到内容,尤其是这些data block若未按顺序存储,就需要“下一圈”的时候再访问,这样会很耗时,也就是说访问磁盘的时间和数据在磁盘上的位置非常相关。
所以Flash技术(如flash-based SSD)就腾空出世了,可以做到任意数据的随机访问,就大大减少了数据访问时间。
4. Network视角
我们先回顾一下到网络这里都经历了什么:应用、操作系统、文件系统、缓冲缓存、卷管理、设备驱动、硬件控制、SCSI,一层一层递进访问。
4.1 存储网络
应用和存储视角已经可以工作了,而在应用和存储之间加一层网络,因此目前的玩法主要包括以下几种形式:
这些知识在之前的存储基础知识学习中有大概的涉及过。
对于文件存储,常常使用NAS的架构,更灵活;而基于块的存储则常使用SAN的方式,保证性能。
4.2 存储区域网络
下面是存储区域网络(SAN)常见的几种网络协议格式以及组网方式:
5. 最后的大招
总结
至此,我们将所有的的细节都进行了分析。
作为编程者,如果想实现性能非常好的程序,那我们需要对每一个环节都有一定的认识。