基于go实例网络存储协议详解

主要内容

一.网络存储是什么?

二.iSCSI是什么?

三.RDMA是什么?

四.NVME-oF是什么?

一.网络存储是什么?

网络存储是一种将存储资源连接到网络上,以便多台计算机可以共享和访问这些存储资源的技术。网络存储可以是基于本地网络的存储(如局域网),也可以是基于广域网的存储(如云存储)。

网络存储通常使用网络文件系统(NFS)或存储区域网络(SAN)等协议来实现存储资源的共享和访问。网络存储具有高可用性、可扩展性和灵活性等优点,可以满足不同场景下对存储资源的需求。

二.iSCSI是什么?

iSCSI(Internet Small Computer System Interface)是一种基于网络的存储协议,它可以将远程存储设备映射为本地磁盘,使得计算机可以像访问本地磁盘一样访问远程存储设备。iSCSI协议可以在以太网、光纤通道等网络上运行,它可以在计算机和存储设备之间建立虚拟的SCSI总线,从而实现数据的传输和管理。iSCSI协议可以简化存储系统的管理和部署,提高存储系统的可靠性和性能。

iSCSI 可以运行在用户态或内核态。在 Linux 系统中,iSCSI 的实现通常是使用内核模块,即 iscsi_tcp.ko 和 scsi_transport_iscsi.ko,它们负责处理 iSCSI 传输和 SCSI 命令处理。但是,还有一些用户态的 iSCSI 实现,如 open-iscsi,它使用用户态的 iSCSI 守护进程(iscsid)和 iSCSI 库(libiscsi)。用户态的 iSCSI 实现可以提供更灵活的配置和管理,但通常性能不如内核态的实现。

Go 语言实现的 iSCSI 库和工具可以用于构建和管理 iSCSI 存储系统,例如:

  • go-iscsi:一个基于 Go 语言实现的 iSCSI 库,支持创建和管理 iSCSI 目标和 LUN(逻辑单元)。它可以用于构建自己的 iSCSI 存储系统或集成到其他应用程序中。
  • iscsid:一个基于 Go 语言实现的 iSCSI 守护进程,可以用于创建和管理 iSCSI 目标和 LUN。它支持多个后端存储引擎,包括本地文件系统、Ceph、GlusterFS 等。
  • open-iscsi:一个开源的 iSCSI 实现,包括 iSCSI 客户端(initiator)和服务器端(target)。它基于 C 语言实现,但也有一些 Go 语言的工具和库可以用于与之交互。
  • dqlite:一个基于 Go 语言实现的分布式 SQLite 数据库,支持多节点复制和高可用性。它可以用于构建分布式 iSCSI 存储系统或其他分布式应用程序。

iscsid

iscsid 是 iSCSI 协议的守护进程,主要负责与 iSCSI initiator(客户端)通信,并将 iSCSI 请求转发给 SCSI 设备。在文件系统中,iscsid 通常是使用内核模块实现的。

iscsid 的内核模块通常由两部分组成:iscsi_tcp.ko 和 scsi_transport_iscsi.ko。其中,iscsi_tcp.ko 负责处理 iSCSI 的传输层协议,如建立和维护 TCP 连接、处理 iSCSI 登录和退出等。而 scsi_transport_iscsi.ko 则负责处理 iSCSI 的 SCSI 命令,如将 iSCSI 请求转发给 SCSI 设备、处理 SCSI 命令的响应等。

当 iscsid 启动时,它会加载 iscsi_tcp.ko 和 scsi_transport_iscsi.ko 内核模块,并创建对应的字符设备文件,如 /dev/sda、/dev/sdb 等。这些字符设备文件对应着 iSCSI target(服务器)上的 SCSI 设备,它们可以被当作普通的硬盘使用,可以格式化、挂载、读写等。

当 iSCSI initiator 发送 SCSI 命令时,iscsid 守护进程将命令转发给对应的字符设备文件,比如 /dev/sda。字符设备文件将命令转发给 SCSI 设备,如硬盘。SCSI 设备执行命令并返回结果。字符设备文件将结果返回给 iscsid 守护进程。iscsid 守护进程将结果返回给 iSCSI initiator。

三.RDMA是什么?

RDMA(Remote Direct Memory Access)是一种高性能、低延迟的网络传输技术,它可以让计算机之间直接访问彼此的内存,从而避免了数据在传输过程中的不必要的拷贝和上下文切换。RDMA 技术主要包括两种协议:InfiniBand 和 RoCE(RDMA over Converged Ethernet)。

在 RDMA 技术中,计算机之间的数据传输不再需要 CPU 的介入,而是直接通过网络适配器和内存控制器之间的 DMA 传输实现。这种方式可以大大减少 CPU 的负载和数据传输的延迟,从而提高传输的效率和性能。

RDMA 的工作流程通常包括以下几个步骤:

  • 应用程序将数据写入内存中的缓冲区。
  • 应用程序通过 RDMA API 发送数据传输请求。
  • 网络适配器将数据传输请求发送到目标计算机。
  • 目标计算机的网络适配器接收到数据传输请求。
  • 目标计算机的内存控制器将请求的数据从内存中读取,并通过网络适配器将数据传输给源计算机的内存控制器。
  • 源计算机的内存控制器将数据写入内存中的缓冲区,并通知应用程序传输完成。

RDMA 技术需要硬件和软件的支持,包括网络适配器、内存控制器、驱动程序和 RDMA API 等。此外,RDMA 技术也有一些限制和注意事项,比如需要保证数据传输的顺序和一致性,需要避免内存泄漏和数据溢出等。

Go-IPoIB库是一个Go语言实现的RDMA over IPoIB协议库,其底层原理主要是通过RDMA-CM API来实现RDMA通信。RDMA-CM是一种基于InfiniBand网络的RDMA通信管理器,它提供了一种通用的RDMA通信接口,可以在不同的RDMA网络上运行。RDMA-CM API包括RDMA-CM库和RDMA-CM头文件,可以在Linux系统上使用。

Go-IPoIB库提供了一种使用RDMA-CM API来实现RDMA over IPoIB协议的方法。在使用Go-IPoIB库时,需要使用ipoib.DialIB函数来创建RDMA连接,并指定本地和远程的IP地址和端口号等参数。然后,可以使用RDMA通信的Write和Read函数来进行数据的发送和接收。在数据传输过程中,Go-IPoIB库会自动封装和解封装IPoIB数据包,并使用RDMA-CM API来管理RDMA通信。

Go-IPoIB库的实现涉及到网络协议、硬件设备、系统调用等多个方面,比较复杂。使用Go-IPoIB库需要有一定的计算机网络和系统编程基础,并且需要详细了解RDMA-CM API的使用方法和相关的网络协议规范。

以下是一个简单的示例程序,实现了一个基本的RDMA写操作:

package main
import (
        "fmt"
        "log"
        "net"
        "time"
        "github.com/infiniband/go-ipoib"
)
func main() {
        // 创建RDMA连接
        conn, err := ipoib.DialIB("192.168.1.1", "ib0", "192.168.1.2", "ib0", 1024)
        if err != nil {
                log.Fatal(err)
        }
        defer conn.Close()
        // 发送数据
        data := []byte("hello world")
        err = conn.Write(data)
        if err != nil {
                log.Fatal(err)
        }
        // 接收数据
        buf := make([]byte, len(data))
        err = conn.Read(buf)
        if err != nil {
                log.Fatal(err)
        }
        fmt.Println(string(buf))
}

在此示例中,我们使用ipoib.DialIB函数创建了一个RDMA连接,指定了本地和远程的IP地址和端口号,并设置了缓冲区大小为1024字节。然后,我们使用conn.Write函数向对方发送了一条消息,并使用conn.Read函数从对方接收了一条回复消息。最后,我们将接收到的数据转换为字符串并打印出来。

在实际应用中,需要根据具体的需求进行更复杂的RDMA通信实现,如RDMA读操作、多个连接的管理等。同时,还需要考虑RDMA通信的安全性和稳定性,避免出现数据丢失、死锁等问题。

四.NVME-oF是什么?

NVMe-oF(Non-Volatile Memory Express over Fabrics)是一种将NVMe协议扩展到网络存储中的技术。它可以让远程计算机通过网络访问本地存储设备,从而实现高性能、低延迟、高可用的存储访问。

NVMe-oF技术的实现需要硬件和软件的支持,包括网络适配器、存储控制器、驱动程序和协议栈等。在NVMe-oF架构中,存储设备被分为两个部分:NVMe-oF Target和NVMe-oF Initiator。

NVMe-oF Target是存储设备的服务端,负责响应NVMe-oF Initiator的请求,并将数据传输到本地存储设备中。NVMe-oF Initiator是存储设备的客户端,负责向NVMe-oF Target发送请求,并从本地存储设备中读取数据。

在NVMe-oF技术中,数据传输是通过RDMA(Remote Direct Memory Access)技术实现的,可以实现高带宽、低延迟的数据传输。同时,NVMe-oF技术还支持多种传输协议,包括RoCE(RDMA over Converged Ethernet)、iWARP(Internet Wide Area RDMA Protocol)等。

总的来说,NVMe-oF技术是一种将NVMe协议扩展到网络存储中的技术,可以实现高性能、低延迟、高可用的存储访问。如果你需要更详细的信息,可以查看相关的文档或参考其他相关资料。谢谢!

要在Go中实现NVMe-oF,可以使用GoNVMe库。GoNVMe库是一个基于Go语言实现的NVMe命令行工具和库,可以用于管理和测试NVMe设备和驱动程序。

使用GoNVMe库时,需要先安装NVMe设备和驱动程序,并安装GoNVMe库。然后,可以使用GoNVMe命令行工具来执行各种NVMe操作,如列出NVMe设备、读取NVMe设备的属性、执行NVMe命令等。

以下是一个使用GoNVMe库读取NVMe设备属性的示例程序:

package main
import (
        "fmt"
        "github.com/chenjie199234/GoNVMe/nvme"
)
func main() {
        // 打开NVMe设备
        dev, err := nvme.Open("/dev/nvme0")
        if err != nil {
                panic(err)
        }
        defer dev.Close()
        // 读取NVMe设备属性
        id, err := dev.Identify()
        if err != nil {
                panic(err)
        }
        // 输出NVMe设备属性
        fmt.Printf("%+v\\n", id)
}

在此示例中,我们使用nvme.Open函数打开了一个NVMe设备,并使用dev.Identify函数读取了NVMe设备的属性。然后,我们将读取到的属性信息转换为字符串并打印出来。

使用GoNVMe库需要有一定的计算机存储和系统编程基础,并且需要了解NVMe协议和相关的存储技术。同时,NVMe设备和驱动程序的支持也是使用GoNVMe库的前提条件。

以上就是基于go实例网络存储协议详解的详细内容,更多关于go网络存储协议的资料请关注其它相关文章!

原文地址:https://juejin.cn/post/7206871218032853029