美文网首页
00-流式编程思想1

00-流式编程思想1

作者: 蜗牛写java | 来源:发表于2019-12-08 22:58 被阅读0次

    00-流式编程思想1

    背景

    • 事件数据的产生随着时间的推移逐渐下降
    • 人们对某件事的理解往往来自基于有效论据的结论。要获得这样的结论,最有效的方法就是沿着事件发生的轨迹进行分析
    • 传统开发建立在有限的数据集基础上;那么随着数据量的增量,开发成本将会飙升
    • 通信行业的发展,促生了很多新生领域,如电商中推荐、物联网、机器学习等,新生的领域对数据的要求天然就是数据低延迟传输

    目标

    • 低延迟

    • 高吞吐

    • 可容错

      系统崩溃之后,重新启动,并产出准确结果

    • 可基于事件发生时间处理

      按照正确的顺序跟踪事件,流处理的结果与事件实际发生的顺序一致

    流式开发

    思考

    谈到流,大家很定会想到IO流;那么我们就先看下IO流;

    IO流:一连串流动的字符,以先进先出方式发送信息的通道

    特点:具有方向(输入流/输出流);具有顺序(字符先进先出);

    随着java8的出现,引入了lambda带来的函数式编程;对多个元素进行操作,可以预先拼接一个“模型”步骤方案,然后再按照方案去执行它。

    如:list.stream.filter.map.collect();

    函数式编程中“Stream流”其实是一个集合元素的函数模型(处理的步骤方法),它并不是集合,也不是数据结构,其本身并不存储元素。

    特点:构建执行步骤,各个算法与算法之间是无状态的

    在生活中我们也会经常遇到流,网页上的点击流、汽车发送的GPS信号、移动通信基站、可穿戴设备的信号等;再具体些,如水流、公路上车流、滚动电梯、直行电梯、生产车间的工作流等等;

    流数据源头广泛,但是流数据更真实的反映了我们的生活方式。

    生活场景流式

    工厂流水线.png

    工厂的流水线是一个比较典型的流式场景;如图传送带就是数据流,传送带旁的每个工位,就相当于流式处理中的filter、map等函数

    Stream流式编程

    Stram流式编程又叫函数式编程,是基于数据的一种声明式编程范式

    函数式编程的核心:

    • 输入:不可变的值
    • 函数:一种映射关系,将一个值映射成另外一个值
    • 输出:映射后的数据

    函数式编程的特征:

    • 不可变:输入数据是不能改变的,返回的是全新的数据
    • 无状态:函数不维护任何状态

    函数式编程的优势:

    • 线程安全
    • 重构代码无伤害
    • 函数执行没有顺序上的问题

    函数式编程思维:

    • 函数式编程是声明式编程,因此关注的是做什么而不是怎么做

    函数式编程小例(java8实现):

    背景:要筛选出学生中,性别为男、年龄在10岁以上、身高大于1.3m的学生名字

    public class Student {
    
        //姓名
        private String name;
        //年龄
        private int age;
        //性别
        private String sex;
        //身高
        private double height;
    
        public Student(String name, int age, String sex, double height) {
            this.name = name;
            this.age = age;
            this.sex = sex;
            this.height = height;
        }
        //忽略get/set...
     }
    
    public static void main(String[] args) {
    
        List<Student> studentList = new ArrayList<>();
        studentList.add(new Student("小明", 11, "男", 15.4));
        studentList.add(new Student("小红", 10, "女", 13.0));
        studentList.add(new Student("小张", 9, "男", 13.5));
        studentList.add(new Student("小王", 11, "男", 12.9));
        studentList.add(new Student("小赵", 12, "男", 15.0));
    
        List<String> names = studentList.stream()
                .filter(student -> student.getSex().equals("男"))
                .filter(student -> student.getAge() > 10)
                .filter(student -> student.getHeight() > 13.0)
                .sorted(Comparator.comparing(student -> student.getHeight()))
                .map(student -> student.getName())
                .collect(Collectors.toList());
    
        for (String name : names) {
            System.out.println(name);
        }
    

    输出:

    小赵
    小明

    例子比较简单,我们主要关注stream编程方式

    概述图:

    Lambda1.png

    详细图:

    Lambda2.png

    撇开java8函数式流实现,其实我们用集合for循环也是能实现的,那么流式操作和集合操作有什么区别呢

    流和集合的区别

    • 流是基于数据的,关注的是一条条数据是什么样的处理;集合是基于存储,关注的是整体
    • 流遍历一次后,返回的是一个新流,之前遍历的流已经不存在了,也就是说这个流已经被消费了,和迭代器一样,不能回头消费;集合循环完之后,集合还是存在的,可以继续重头循环
    • 从哲学的角度来看,流可以看做时间中分布的一组值。集合则是空间中(计算机内存)分布的一组值

    函数式编程用到技术

    • 头等函数

    • 尾递归优化

    • pipeline(管道)

      将函数实例为一个个action,然后action放到一个数组中,再把数据传给这个action list,数据就像一个pipeline一样顺序被这些函数操作,最终得到我们希望的结果

    • 递归

    • 柯里化

    • 高阶函数

    编程范式

    编程范式一般可以分为三类:命令式、声明式、元编程

    编程范式.png
    • 过程式编程:关注的是怎么做;核心在于模块化,实现过程使用了状态,依赖了外部变量,可读性差,维护成本高

    • 面向对象编程:关注的是抽象,提供了清晰的对象边界。封装、继承、多态的特性,降低了代码的耦合度,提升了系统的可维护性

      程序是一些列相互作用的对象

      抽象:怎么为一个模糊不清的问题找到一个恰当的描述就是抽象,抽象也是我们简化复杂问题的一种方式

      在面向对象编程里,计算程序会被设计成彼此相关的对象。对象则是类的实例,它是程序的基本单元。

    • 函数式编程:关注的是做什么;传入数据不可变性,当前函数也不依赖函数外的数据,使得函数具有自描述性,可读性高

      程序是一系列无状态的函数组合序列

      声明式编程不用告诉计算机问题领域,从而避免随之而来的副作用,而命令式编程则需要告诉计算机每一步该怎么做

    对比:

    面向对象 关注抽象和状态;描述对象基本特征 易于抽象和理解<br />代码容易重用<br />代码容易维护<br />具有可扩展性,便于阅读 并发不安全<br />代码易膨胀<br />性能较低
    范式 特征 优点 缺点
    过程式 关注怎么做;易于理解 性能高 依赖外部变量;<br />可读性低
    函数式 关注做什么;不依赖当前函数外的数据 描述问题,易于理解;<br />无副作用(并发安全) 占用资源,性能相对较差

    传统开发与流失开发区别

    传统的开发会将所有数据存放在数据中心中(如一张表),然后进行加工、分析得出结果(如sql);一句话就是统一收集数据,然后进行分析。如果需要对数据中心中每月/每天数据进行分析,还是没有问题;如果需要对数据中心中每小时/每分钟/每秒进行分析,那么就有可能无法满足。

    传统方式.png

    既然对数据中心中的每秒数据不好处理,是否可以转变一下思想,在入数据中心中的时候,就把数据分析好放入到数据中心中呢?

    流式方式.png

    所以流式计算的上游,是数据流,下游是计算中心或者直接对接业务;

    传统开发就是批式处理思想,那么批处理和流处理的区别呢

    批处理 流处理
    数据有限 数据无限
    数据静态 数据动态
    具有周期性 无周期性
    需要时间响应 实时响应

    那么流处理是不是一定优于批量处理呢,答案是否定的;如家庭用水为例,批处理相当于桶装水,流处理相当于接入水管;饮用水一般使用桶装水,生活用水一般使用自来水(接入水管);该例子主要是以使用量来选择使用场景

    数据流

    时间分布和数量上无解的一些列动态数据集合

    流式开发特点

    • 时效性:实时(数据的价值随着时间的流逝而降低,因此必须实时计算给出实时响应)
    • 数据特征:动态、没有边界
    • 场景:实时场景;如推荐、监控等

    概念相关

    • 数据流:连续数据组成的流
    • 流数据:数据流中的数据

    有向无环图(DAG)

    概念

    有向无环图,同一个方向,但不构成闭环

    DAG特点

    • 严密的拓扑性质

      具有很强的流程表达能力;按照拓扑的顺序对零散的组建进行组织执行,就可以得到正确的结果。

      计算领域,基于DAG的计算模型应用还是比较广泛的,如spark/storm/tensorflow

    • 去中心化

      每个组件拥有各自的状态;组件之间状态互不依赖

    • 具有方向

      整体具有方向;一个组件的输出可以是下个组件的输入

    DAG优势

    • 任务模块化
    • 易于调整
    • 结构清晰

    相关文章

      网友评论

          本文标题:00-流式编程思想1

          本文链接:https://www.haomeiwen.com/subject/jmuvgctx.html