栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

零拷贝技术浅浅析【kafka实现百万级吞吐量基础】

零拷贝技术浅浅析【kafka实现百万级吞吐量基础】

家人们,这期的知识点可能会让你掉几根头发,为了尽可能让你理解,进入正题前我们先来看个栗子

给女朋友送礼物

如果,我是说如果啊,你有一个女朋友(没有的不要灰心,认真看完文章可以找博主领取)

情人节来了,你想在网上给女朋友买个礼物,但是吧,网上现成的礼物直接送过去显得没诚意,为了避免被发好人卡,你想先买回来DIY一下再送

受疫情影响,快递员不能进小区,你也不能出小区,快递员先把礼物放到小区快递点,你去快递点拿,拿回家DIY完后再放回快递点,快递员再从快递点拿到礼物送到女朋友家

简单画了个流程图

看看这个流程,有太多不合理的地方,人的时间和精力是宝贵的,应该用来打游戏,而不是送 / 拿快递

时间过了大概好几年,物流公司研发了送快递机器人,从此以后快递小哥不用再上门送件,于是流程变成了

有了快递机器人,快递员解放了,但是你还需要去快递点拿礼物,DIY完了还得送回快递点,显然也不合理,有这时间我玩把中单亚索不香吗

于是你给礼物店老板提了个需求:能不能帮我DIY,然后直接寄到我女朋友家

老板觉得有道理,推出了新服务:需要DIY的用户,只需要在订单备注即可

于是流程变成了

你下单的时候,备注让店家帮你DIY,完事儿直接寄到女朋友家,女朋友收到快递感动到流了两斤眼泪

至此,你的两次出门也省了

回顾一下

从送礼物整个过程来看,最开始快递员需要跑路两次,你也需要跑路两次,到现在只需要机器人跑路两次

简单来说四次跑路变成了两次跑路,而这两次还都是机器人来完成,所以整个过程的人为跑路次数由4次变成了0次,这个过程我姑且称之 为零跑路


ok该来的始终还是来了,上面这个例子只是想引起你的兴趣,想要理解零拷贝,我们现在把术语代入

你家 ==> 应用程序缓存快递点 ==> 操作系统内核缓存durex旗舰店 ==> 磁盘女朋友家 ==> 目标磁盘或者socket 为什么要实现零拷贝

背景:文件操作属于危险操作,操作系统不可能直接把权限交给应用程序或者用户,只有内核才有权限
应用程序操作文件如复制、传输时,需要经历一下几个步骤:
从磁盘把文件复制到系统内核
从系统内核复制到应用程序
从应用程序复制到系统内核
从系统内核复制到磁盘、socket等消费端

简单画个流程图

说明:本文重点在于帮助大家理解零拷贝,关于操作系统内核方面的知识过于偏题,所以流程图画的很简单,如 “操作系统内核缓存” 其实还可细分为 “PageCache” 和 “Socket 缓冲区”,类似这些细节就不画了,而且画复杂了看着头疼
但请放心,虽然简单,但重点都没省略,丝毫不影响理解零拷贝


上面1、2、3、4几个步骤都是由cpu来完成,我们知道,cpu运算效率和磁盘不是一个量级

对服务器而言,cpu资源是很稀缺的,这四个复制操作一直占用cpu,显然会拉低整个系统性能

于是计算机界大佬们想了个办法,在主板上加了一块元件,叫 DMA(全称Direct Memory Access Controller,直接内存访问控制器),它是一块物理硬件,专门用于磁盘到操作系统内核缓存之间的数据复制

于是流程变成

红字解释:目前的网卡几乎都支持 SG-DMA(The Scatter-Gather Direct Memory Access)技术(可以用ethtool -k eth0 | grep scatter-gather命令查看是否支持),关于这点了解即可,不需要深入研究,这已经是嵌入式开发领域的知识点了,咱没必要花太多时间在上面

如果到现在有点懵,没关系,你只需要记住,有了DMA,cpu不再亲自参与整个数据复制或传输过程,只需要给DMA发送指令,告知它应该把哪个文件复制或传输到哪里即可,等DMA完成数据操作后通知cpu


再来说说DMA吧,DMA的实现依赖于操作系统和硬件:

操作系统方面,os提供了sendfile()函数

它接收四个参数:target端文件描述符、source端文件描述符、偏移量、数据长度

我们没有必要研究如何调用这个函数,因为Java已经帮我们做好了封装

你现在不需要管这个方法在哪个类中,我后面会写代码演示

kafka为什么能做到百万级吞吐量,靠的就是零拷贝模型,如果你仔细看过kafka源码,你会发现它最终调用了transferTo()方法

硬件方面,主板上增加了DMAC元件,其实不止主板,计算机发展到今天,几乎所有牵涉到io操作的地方都集成了DMAC

至此,我们可以做个小总结:所谓的零拷贝技术,其实可以理解成软件、硬件、语言的结合,目的在于减少cpu等待时间,提升数据传输效率


Talk is cheap,Show me the code

我们以复制文件为例,测试一下零拷贝模型带来的性能提升

新建一个测试文件

600MB

先来尝试下传统io复制(代码放在最后)

600MB花了800ms,这已经算是io中很快的了,如果用不带buffer的普通io,时间还得加3倍左右

再来看看零拷贝的nio

300ms左右,相对io提升了一倍多,看着不咋地,你想想高并发场景下,动不动上万次类似操作,这节约下来的时间足以让甲方激动到拍打轮椅

代码:

public class ZeroCopyTest {
    public static void main(String[] args) throws IOException, InterruptedException {
        long start = System.currentTimeMillis();
        File source = new File("D:/fileTest/copy.txt");
        File target = new File("D:/fileTest/copy2.txt");

        ioCopy(source, target);
//        ioCopyWithBuffer(source, target);
//        nioCopy(source, target);
        System.out.println(System.currentTimeMillis() - start);
        Thread.sleep(200);
        target.delete();
    }

    public static void ioCopy(File source, File target) throws IOException {
        try (InputStream is = new FileInputStream(source);
             OutputStream os = new FileOutputStream(target)) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
        }
    }

    public static void ioCopyWithBuffer(File source, File target) throws IOException {
        try (InputStream is = new BufferedInputStream(new FileInputStream(source));
             OutputStream os = new BufferedOutputStream(new FileOutputStream(target))) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) > 0) {
                os.write(buffer, 0, length);
            }
        }
    }

    public static void nioCopy(File source, File target) throws IOException {
        try (FileChannel sourceChannel = new FileInputStream(source).getChannel();
             FileChannel targetChannel = new FileOutputStream(target).getChannel()) {
            for (long count = sourceChannel.size(); count > 0; ) {
                long transferred = sourceChannel.transferTo(sourceChannel.position(), count, targetChannel);
                sourceChannel.position(sourceChannel.position() + transferred);
                count -= transferred;
            }
        }
    }
}

两根头发又无了,嘤嘤嘤~


前面说的领女朋友,其实,是骗你们的


ok我话说完

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/748715.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号