二十几年前学习DOS内核的时候,是可以直接写程序控制磁盘步进电机的,磁头放在什么位置,读写到盘片的哪儿都可以控制。但看看现在的SAN存储,恍若已是隔世。
我们就以一条简单的linux cat 读文件命令,看看要经历怎样的千山万水,才能到达物理磁盘,取到真正的数据。
首先,在linux 命令行中输入cat 命令,系统会调用相应的system call, 进入内核态。在内核里最早接受请求的是VFS(virtual file system)层, VFS 是一层抽象的文件接口,当它发现实际请求是要访问一个磁盘文件时,就会调用对应的真正的文件系统接口,在linux中通常是Ext3. 在这个时候,如果该文件之前已经被读过,还放在buffer 中,那么恭喜你,你可以直接拿到数据了。
如果没有,对不起,继续往下调用块设备存储的驱动,块设备存储驱动会把读取文件的指令转换成读取某个块存储设备的某个数据块,这也是SCSI子系统的最高层接口,系统把存取指令按照SCSI协议命令打包,发给SCSI 控制器。如果linux是非虚拟机,这个时候工作就交给硬件。
但是,如果linux还是台虚拟机(现在大部分情况都是这样,假设这台linux是运行在Vmware 的 EXSi host 上),读取指令则会传递给一个虚拟的SCSI 控制器,这个虚拟SCSI控制器再传递给VMkernel, 对VMkernel而言,虚拟机的一个磁盘其实只是一个文件(datastore), 所以VMkernel还要二次转换,转成物理设备真正的位置,再把这些指令通过调用HBA驱动发给HBA卡。
HBA卡(host bus adapter)是光传输设备,它与光交换机,SAN存储一起构成光纤传输网络,把读取指令传输到相应的存储设备上。
好,总算到目的地了。且慢,这还是万里长征第一步,现在的SAN存储可不仅仅是几块磁盘,就拿IBM8870来说,它其实是由两台高端P系列服务器组成的集群。当我们的读取指令到达SAN 存储,SAN存储会重新解析这些指令,如果该数据块已经放在存储服务器庞大的内存(Cache)中,则这些数据就会经光传输网络返回。否则,就要遍历在linux端同样的过程,一级一级调用底层接口,最后通过SCSI驱动,发出指令来操作实际的物理硬盘。
在这个过程中,存储服务器已经将数据的具体物理位置做了两层封装。首先是做RAID,比如IBM8870 中8个盘为一组,用RAID5,6,或10,实现数据冗余和高性能。所以看似连续的数据块实际可能分布在一组磁盘上。第二层是extend pool, IBM8870可以将SSD盘,SAS盘,SATA 盘都放到同一个extend pool, 再分到同一个逻辑盘里。也就是说我们操作的逻辑盘其实际数据可能放在完全不同类型的盘中,而且,由于IBM78870提供了自动Easy tier 功能,系统可以根据数据的使用频率调整使用不同的盘。如果某数据块频繁地被访问,则该数据块就会从 SAS盘转到SSD盘 。所有这一切都是自动在后台进行,对用户完全不可见。
现在还有一项流行的技术,就是在服务器和物理存储系统间再嵌入一层虚拟层,由它来管理控制所有存储并对服务器提供存储服务。比如IBM SVC (storage volume controller). linux 发出的数据读取指令会先到SVC, SVC 实质也是一台服务器,同时对各物理存储系统的盘有做了一层封装。所有连SVC 的存储系统将自己的磁盘呈现给 SVC组成 MDG (managed disk group),SVC 再将这些盘映射为自己的 VDISK. 当用户需要读取某VDISK 中的数据时,SVC再翻译成对应的实际物理存储系统的的位置,然后通知该物理存储系统读取相应的数据。
我们可以看到,现代基于 SAN 的存储系统其实已经对物理磁盘做了多层封装和虚拟化。在用户这一层几经无法实际定位某一段数据真正放在物理磁盘上的哪个位置。