分享

什么是流式思维?

52Pig 发表于 2014-10-17 23:27:18 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 16 28794
本帖最后由 pig2 于 2014-10-18 00:39 编辑

阅读导读:
1.为什么会提出流式思维?
2.面向函数流式特点?
3.流式思维应用在架构设计上有哪些好处?




架构治理如同大禹治水,以疏代堵,顺势而为,大道如水,那我们的思维也要切合如水。

首先什么是流?最先联想到的是“水流”,潺潺不断,流是一种动态过程,如果你想截断水流,最简单的是堵住它,所以,流是不能被堵塞的,也就是非堵塞,只有非堵塞才会形成流。

中国有句古话:百川入海,如果水流没有被堵塞,随着时间推移,再多的水都会流入大海,如果把水看成是数据,很显然,流处理方式可以处理无限的数据,只需要消耗时间。因此,流式是对数据量开放的。

流式这种不畏惧数据量的特点在现实生活中比比皆是,比如我们看电视,这是通过流式获得大量信息的输入;比如我们逛大型超市,从入口一直溜(流)到出口,通过这种流式我们能获得大量商品信息。

那么为什么要提出一种流式思维呢?因为思维决定软件设计,设计决定系统,而我们的系统是模拟真实客观规律运行的,因此我们的思维必须采取最贴近客观规律的方式去思考,那么客观规律是什么特点?

量子力学的波粒二象性和薛定谔猫理论认为:当我们观察量子时它是一颗颗有边界的粒子,而我们不观察它时其实是连续的波。也就是说,在微观世界,客观规律隐式的其实是一种流式的波,连续而不间断。

那么为什么我们在日常生活中没有觉察到这一现象呢?那是因为我们人类自己作为观察者身在其中,所以,我们看到的都是一颗颗有边界的“粒子性”的对象。但是,身在庐山中不识庐山真面貌,别忘记客观规律可能还会有连续流式的特点,因为世界是运动的。

我个人斗胆将波粒二象性这一物理理论推广到思维哲学世界,认识世界不只是需要面向对象思维,还需要流式思维。

客观世界是一种类似波的流式系统,流式思维是最接近隐式的客观规律。

前面扯了那么多咸蛋,回归到软件领域,如果说粒子性的面向对象是采取空间上隔离的方式,那么流式思维正好相反,是一种空间上连续没有隔离堵塞的思考方式,这其实代表了面向函数的一种思维方式。面向对象和面向函数代表了我们两种思考方式,这两种思考方式不同,因此针对不同领域采取不同方式。

面向对象特点
我们前面说过,当我们观察量子时,它是粒子,因此,粒子性的面向对象方法适合从人的角度观察分析世界,比如我们看到一个实体如电视机,这个电视机是有实在大质量的物体(大粒子),因此,我们会在软件设计中建立一个对象叫电视机:
  1. public class TV{
  2.      private String name;
  3.      …
  4. }
复制代码
这个电视机有名称和规格等等,其功能特点是能开机,播放,换频道,关机等。
  1. public class TV{
  2.      private String name;
  3.      …
  4.      public void powerOn(){
  5.         ..
  6.      }
  7.      public void play(){
  8.         ..
  9.      }
  10.      public void powerOff(){
  11.         ..
  12.      }
  13. }
复制代码
有了电视机的这个实体和它的功能是不够的,因为我们是为了利用它的这些功能,当然不同的人会有不同的用法,一些人用电视机是为了看电视剧;一些人是为了看新闻;一些人是为了看娱乐节目等等,如何让一个实体为这些不同的人群服务?
我们为这些不同应用场景设计不同的微服务即可,如下:
  1. public interface DramaService
  2. public interface NewsService
  3. public interface EntertainmentService
复制代码
然后设计一个界面列表出上面这些服务让用户选择进入。那么这个系统是否就完成了呢?很显然,还有一个很重要的问题我们没有考虑,那就是如果这些人合用一台电视机怎么办?一台电视机不可能同时播放几个频道啊,只能在某个时刻播放一个频道,这种在某个时刻的状态是我们必须关心的重点,那我们添加一个状态到TV中:
  1. public class TV{
  2.        private ChannelState state;  //当前这台电视机正在播放的频道
  3. }
复制代码
有了状态这个值对象,我们就能有序控制这台电视机为不同人服务,如果两个人想同时看不同节目,我们的业务规则会告诉他:“非法”操作。我们用面向对象的方式封装了规则和法律。

面向函数流式特点
以上是面向对象的分析设计过程,这个方法特点是我们首先建立一个TV实体对象,然后在其内部封装了体现业务规则的可变状态。而面向函数的流式方法则正好相反,我们不关心某个TV实体,更不关心实体内部是什么,我们更关心多个TV怎么办?无限个TV怎么办?比如在电视机制造厂希望制造的电视机越多越好,每个电视机内部属性特征最好是不变的,都是一样的,这时电视机生产商就会采取流水线作业来生产无限个电视机。

同样,对于电视台来说,无限个节目数据如何进入电视机播放才是最重要的,因此采取流媒体的方式进行推送无限个节目视频。

所以,流式的面向函数思维会更侧重平台制度性的建设,会忽视个体的差异,拥抱个体的大数据量。从这点来说,流式思维更适合进行大数据处理和分析,比如hadoop和Spark。

建设一个面向流式处理的平台如同铺设自来水水管的建设,更注重管道的规划和有序合理性,防止管道之间汇聚发生堵塞,典型的就是道路这种管道建设,如果两条路交叉,那么在两条路上的车辆就会发生碰撞堵塞,红绿灯设置只是临时之举,正如CPU的线程上下文切换一样,CPU就是线程的红绿灯,可以暂停某条线程,先执行其他线程,然后再唤醒这条线程继续执行。

流式处理最重要的基本要素是事件,事件是一个一旦发生就不再改变的值对象,每个事件结构基本一样,我们不关心事件内部的规则和状态,而是关心无数个事件的处理,因此事件是一个流式系统的基本要素,有了无数个事件就需要有事件的源和目的,掌握这三点就容易帮助我们理解流式系统。

流式思维在大数据架构上应用
比如Storm这个大数据处理框架,其有几个好像陌生的概念:Spout Tuple Bolt,如果单从字面上理解是“嘴” “元组” “螺栓”等意思,但是你从流式角度去思考就很容易理解,Spout嘴是产生事件流的源,而Tuple元组代表一个个小事件,多个事件就是Tuples了,Tuples代表了事件流,而Bolt代表流过程中一个处理器,如同将两个水管接在一起的接头。

流式总是和集合概念相对应的,因为集合一般是很多数据个体的总称,流式不像粒子性面向对象那样注重个体,流式是注重集体集合整体概念的,集合一般是流式的源泉,比如Java中集合处理,以前我们是将连续的波流人为地切断为一个粒子点,就像把线看成是点组成一样,那么就有下面代码:
  1. Collection values = …;
  2. for (Object o;values) {
  3. ...
  4. o.xxx();
  5. }
复制代码

我们使用for循环实际就是将values集合切分点一个个个体的点,然后逐点处理。这是一种粒子性的面向对象方法,用在这里显得笨拙,因为我们并不关注某个对象内部静态特征和属性,而是关注很多个这些对象,这些对象都有一个统一的特征,都是一样的,熟悉访问者模式的人可能会联想到,访问者模式正是通过强制给集合中对象强加一个统一的accept方法。

熟悉访问者模式说明你已经一只腿迈入流式思维的大门中,我们看看使用Java 8的面向函数范式如何实现这个案例的流式处理:
values.parallelStream().filter (..).forEach(..);

流式思维在微观上应用
流式思维不但可以应用在大数据处理上,也能使用在微观的CPU使用上,前面我们谈到CPU类似红绿灯调度员,调度两条线程(水管)的协调,如果我们采取流式思维,设计出不会交汇的多条水管,那么CPU就不会去做红绿灯这种看似高效率实际是低效率的事情。比如我们在安卓编程中,可以采取如下流式编程:
  1. apiService.login() //后端线程
  2. .getUserData() //后端线程
  3. .saveUserData() //后端线程
  4. .subscribe(Subscriber { //UI线程
  5. void onComplete(){}
  6. void onError(Exception e){}
  7. void onNext(Object o){}
  8. });
复制代码
我们在这个代码中相当于启动了四条不会交汇的流,实际是四个线程,这四个线程正好利用四核CPU,这样避免了一个CPU做红绿灯。

流式思维还可以巧妙避开资源争夺问题,比如回到前面TV 这个案例,这个案例是在家庭应用这个上下文场景下设计的,试图解决一台电视机供不同人作为不同用途的问题,电视机在这里是一个资源,我们通过引入可变的当前的频道状态来协调多人看不同频道的问题,这实际也是类似红绿灯,某个时刻电视机要么播放娱乐频道,要么播放新闻频道,或者电视剧,只能有一个状态,但是如果有两个人同时换频道,电视机到底听谁的呢?代码如下:
  1. public class TV{
  2.        private ChannelState state;  //当前这台电视机正在播放的频道
  3.        public void changeChannel(changeCommand cmd){
  4.             state = cmd.getState(); //修改当前状态为新的状态
  5.        }
  6. }
复制代码

这里就发生了资源争夺问题,传统解决办法也是使用红绿灯方式,也就是加入锁,如引入同步synchronized:
  1. public void synchronized changeChannel(changeCommand cmd){
  2.             state = cmd.getState(); //修改当前状态为新的状态
  3. }
复制代码
这样某个时刻只有一个线程能操作这个方法,这种拍拖式的红绿灯其实是一种堵塞方式,在大量用户同时操作时会产生让浏览器用户产生网络无响应,或者操作失败等各种问题,甚至引起死锁后当机,不少网站系统在承受大量用户访问后瘫痪有不少原因是因此引起的。

相反,流式思维就能我们巧妙回避了资源争夺问题,我们在changeChannel方法调用之前加入一个管道队列Queue,同时无序的混乱操作变成了有序的流式处理,这种性能成本要远远小于同步锁带来的成本。

同样,如果我们在changeChannel 方法中需要再操作其他资源,特别是慢的资源操作容易引发堵塞,就像免费高速通行时总是堵塞在收费口,虽然收费口不设置收费了,但是车辆进入收费口时是需要减速的,同理车流也会堵塞在大桥上面,因为大桥是限速的。比如这里我们会将状态保存到数据库中,数据库操作需要连接池等慢处理:
  1. public void changeChannel(changeCommand cmd){
  2.             state = cmd.getState(); //修改当前状态为新的状态
  3.             repository.save(state); //这个慢速会成为整个方法处理过程的瓶颈。
  4.   }
复制代码

解决这个问题通过引入流式处理,流式方法的特点是事件流,那么我们这里引入事件:
  1. public void changeChannel(changeCommand cmd){
  2.             state = cmd.getState(); //修改当前状态为新的状态
  3.             producer.send(changeEvent en); //触发一个changeEvent事件,没有堵塞
  4. }
复制代码

持续不断地调用changeChannel就会产生持续不断的事件流,在事件流的终点,我们再进行慢速处理,这样不会影响原来的流程,这是在一个水流管道上再分流出一个管道,从而不影响原来水流的操作方式,正如南水北调工程是在长江这个水流中分支出一个通道流向北方。

这种流式处理正是LMAX架构的核心,依靠Disruptor这种管道队列,LMAX能做到每秒处理600万订单的吞吐量,正如设计一个无堵塞的港口,其处理能力只有时间的限制,没有被处理对象数量的限制一样。

上述案例,我们巧妙将慢速的数据库操作转移他处,但是要真正解决数据库的资源争夺,我们还是可以使用流式思维,数据库就不要存储可变的状态数据,因为对同一个数据表记录会存在多个修改的引发的争夺现象,我们只要向数据库或文件中增加新数据,而不是修改原来的数据,永远只是追加Append操作,这种Append是典型的流式操作,我们可以将事件流不断追加到数据库或文件系统等慢速设备上,需要时再通过事件流加载再次播放到指定的状态。这是Event Sourcing/CQRS的基本思路。

总之,流式思维应用在架构设计上大有好处,架构治理如同治水,流式思维类似大禹治水,以疏替堵,顺势而为,面向对象 面向函数 异步编程 并发编程等都只是手段方法而已。

已有(16)人评论

跳转到指定楼层
cometwx 发表于 2014-10-30 17:48:05
说得不错,学习了
回复

使用道具 举报

loreting 发表于 2014-11-7 10:58:40
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

Joker 发表于 2014-12-5 17:53:04
看的我也是醉了这篇文章
回复

使用道具 举报

codefarmer 发表于 2015-4-21 18:53:22
楼上的图像亮了,怎么少了属性?
回复

使用道具 举报

dulei 发表于 2015-4-23 20:05:11
回复

使用道具 举报

zygift 发表于 2015-6-12 07:48:16
回复

使用道具 举报

sqlFocus 发表于 2015-6-12 08:42:18
不错,确实说道点上了
回复

使用道具 举报

叶孤城 发表于 2015-6-15 09:43:48
回复

使用道具 举报

12下一页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条