NBD-网络块设备[翻译]
1997年4月,Pavel Machek 写了他的网络块设备代码,并被当时的Linux Kernel 2.1.55接受。Pavel 在随后的四个发行版(对应的内核版本为55、101、111、132)中维护并升级了他的代码。Andrzej M. Krzysztofowicz贡献了64位机上运行的版本,随后Stephen Tweedie 为其提出了许多的专业建议,尤其是引入了基于信号量的锁机制,使得代码在对称多处理器系统中能够安全的运行。作者们已将其增强以便于运用于工业环境之中。本文描述了网络块设备、驱动、以及它的开发历史。
NBD的驱动程序提供了一种在这个面向网络的世界中更为普遍的访问模型。它在本地客户端模拟了一个块设备,比如一个磁盘或者是一块磁盘分区,但实际提供物理支持的却是通过网络连接的远程服务器。在本地,该设备看起来是一个磁盘分区,但那只是远程服务器的表面。远程服务器是一段轻量级的守护进程代码,它提供对远程设备的访问,而且该守护进程并不需要运行在linux平台之上。本地操作系统必须是linux,而且要支持Linux内核NBD驱动,并且能够运行本地客户端进程。安装NBD可被用来进行远程存储和备份,而且能用来在地球的任意一个角落虚拟地传送物理设备。
图1.NBD在本地客户端代表远程资源
NBD有一些UNIX系统组件的经典特征:简单、小巧、多功能。文件系统能被挂载到NBD上(图1),而且NBD设备也能够用来组成冗余磁盘阵列(RAID)。在本地Linux上挂载一个EXT2文件系统到NBD,其传输率要比在同样的远程机器上挂载一个NFS快(表1是接近Pavel最初写的驱动代码的计时)。
图2.使用NBD的冗余磁盘阵列
write cmd. dd=if=/dev/zero of=/dev/nd0 bs=1024 count=32000
NBD bs=1K 0.04user 5.54system 0:26:67elapsed 20.9%CPU 1.23MBps
write cmd. dd=if=/dev/zero of=/dev/nfs bs=1024 count=32000
NFS r/wsize=1K 0.15user 7.46system 0:43.58elapsed 17.0%CPU 0.75MBps
write cmd. dd=if=/dev/zero of=/dev/nfs bs=4096 count=8000
NFS r/wsize=4K 0.03user 3.94system 0:35.18elapsed 11.0%CPU 0.93MBps
表 1. NBD与NFS在一个端口上的写传输速率比较
挂载到NBD上的Linux EXT2文件系统,缓冲区大小接近1.5KB,其性能赶得上默认条件下的NFS。也就是说,它的大小是以太网默认传输单元(MTU/MRU)的大小——1.5KB。这恰好是NFS默认缓冲区大小(1KB)的1.5倍。NBD因为使用TCP而不是UDP作为传输协议而具有很好的恢复力。TCP包含它固有的一致性以及恢复机制,因而比UDP协议庞大。但对NBD来说,TCP的开销会被它节省的重新传输和校正码所需带宽抵消。
NBD能够被用作一个中型邮件服务器A的实时镜像。故障转移可以通过在另一个房间里放置一台用100BT网络连接的备份服务器B来实现。NBD设备将主服务器和备份服务器连接,并提供了主服务器RAID-1镜像的一半(Y),另一般是主服务器自己的用于存放邮件的分区(X)。组合成的设备XY将作为mail spool被挂载。
当服务器A失效时,运行在B上的一个守护进程能够探测到NBD连接的断开,然后检查镜像Y的mail spool, 校验最小的不完整性,并将其在本地作为mail spool挂载,最后在B上启动A广播的邮件交换IP地址的别名。当A修复之后,会被守护进程检测到,别名将会被丢弃。NBD连接随后会被重新修复,A上的分区X将会重新和NBD镜像Y保持同步。主服务器RAID-1设备会被重新调度,NBD镜像也会重新从属于它。邮件服务将会以默认的配置恢复。使主从服务器设置对称是可能的,但不适宜在这里描述细节。
与其他备选方案相比,这种方法具有许多优点。其一,比如说,维护一个空的邮件服务器,在主服务器宕机的时候将其唤醒。这会使得许多已经放到spool中的邮件在停机期间不可被使用。但重新整合是很容易的,将相关的文件连接到恢复后的服务器也很简单。但主服务器上的某些邮件可能会丢失。
另一种解决办法是将邮件服务器分散到一些不同的机器上,这些机器通过NFS挂载同样的spool区域。然而,NFS的文件锁过去从未被证明是完全可靠的,NFS也从未令人满意的支持由于多个用户同时选择下载50MB的邮件目录引起的事件的激增。传输率也会随着文件尺寸成指数地变慢。在不利的网络条件下,软模式的传输率极有可能崩溃。如果NFS在服务启动的时候为了追求高的可靠性而以同步(硬)模式挂载,一旦NFS服务失效,将会导致所有客户端停机。NFS服务不得不独立地建立镜像。
- 在ASP中实现UNIX时间戳
- 【学术】厉害了我的哥,国外技术大咖仿造了谷歌的Arts &Culture,找到古代的“你”
- 【技巧】应赛技巧,教你如何在Kaggle比赛中排在前1%
- 熔断器 Hystrix 源码解析 —— 命令执行(一)之正常执行逻辑
- 智能主题检测与无监督机器学习:识别颜色教程
- 如何下载安装Weka机器学习工作平台
- Dubbo 源码解析 —— LoadBalance
- 如何处理机器学习中类的不平衡问题
- 【死磕Java并发】—– Java内存模型之重排序
- Mask R-CNN源代码终于来了,还有它背后的物体检测平台
- 37个TOP实例命令,超过一半你肯定都没见过
- 利用TensorFlow生成图像标题
- 保存并加载您的Keras深度学习模型
- 简单、通用的JQuery Tab实现
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- docker容器入门最佳教程
- redis实战第五篇 jedis 连接 redis sentinel详解
- redis实战第四篇 手动容灾故障转移记录
- 10条很棒的Python一行代码
- 如何在一个Docker中同时运行多个程序进程?
- 如何在CentOS / RHEL 7上启用IPv6
- Golang中的RegExp正则表达式用法指南
- Golang glog使用详解
- kubernetes使用securityContext和sysctl
- 浅谈分词算法基于字的分词方法(HMM)
- 优雅的重启服务
- Go defer 会有性能损耗,尽量不要用?
- 带入gRPC:分布式链路追踪 gRPC + Opentracing + Zipkin
- 聊聊Golang逃逸分析
- 结构型设计模式:适配器模式和门面模式