数据管道思考

起因

  • 虽然数据管道各种开源/商业项目的数量上没有OLAP数据库那么多、选型那么复杂
  • 但是在面对flume、rabbitmq、kafka等等的有时候是消息队列、有时候是数据管道/采集的组件总还是存在不少疑惑
  • 我什么时候应该用这个,什么时候应该用那个呢?
  • 最佳的答案可能是一张在所有维度对比所有数据管道项目的大表格,但显然这样的选型表格不存在
  • 因此我们需要了解各数据管道的底层逻辑,从而在自己心里构建选型决策树,才能为面对的场景进行恰当的选型

检索

  • 读综述类论文的时候,文中总是会提出一个属性矩阵,并依此描述当前已有的实体,从而总结归纳当前,继而预测领域未来的发展
  • 当我在各项目的介绍文章,以及各类对比文章中寻找这样的属性时, 发现能够找到很多
  • 17 个方面,综合对比 Kafka、RabbitMQ、RocketMQ、ActiveMQ 四个分布式消息队列
  • 大部分网络上的对比文章过多的陷入了各类实现的细节,
  • 就像台式机与笔记本都是由cpu、gpu、主板、内存、硬盘和外设等组成
  • 这时候对比台式和笔记本内存条的长短和频率是没用的,一定有更接近本质的属性能够完美区分出彼此
  • 台式机和笔记本这个本质属性就是移动性,而在数据管道这个领域,我认为是推拉模型

推拉

  • 推与拉,英文push与pull,用于描述两个实体间传递信息时的双方主动性
    • 无论push/pull,信息传递的方向是不变的,都是由信息发送方传递到信息接收方
    • push与pull描述的是信息传递过程由哪方触发的区别
  • push/pull模型对发送/接收两端的要求
    • push模型由发送方按自己需求主动发起,接收端必须及时响应
      • 因此 push模型对接收方要求更高
    • pull模型由接收端按自己需求主动发起,发送端必须及时响应
      • 同理 pull模型对发送端要求更高
    • 这里的要求包括处理速度、缓存能力、各类保证等等能力的要求
    • 理解push/pull模型对收发双方能力要求的不同,是理解众多数据管道项目底层理念的关键!
  • 数据管道,顾名思义,作为信息传递的管道,有管道入口与管道出口两端
    • 两端均需与其他实体进行信息传递,所以两端也就都存在选择pull还是push的问题
  • 因此如果把入口/出口看作两个维度,把pull/push看作每个维度的定义域,我们可以画出一个平面坐标轴,四个象限,即
                   ^
                   | OUT
                   |
                   |  p
  Data Pump        |  u  Data Queue
  IN.pull OUT.push |  s  IN.push OUT.push
  Flume            |  h  Rabbitmq
                   |
                   |
+--------------------------------------->
        pull       |      push       IN
                   |  p
  Null             |  u  Data River
  IN.pull OUT.pull |  l  IN.push OUT.pull
  Flume + Kafka    |  l  Kafka
                   |
                   +
  • 上图是用ASCIIFlow画的图,中文导出后汉字更宽图会乱,所以用了英文

分析

  • 下面的分析都是围绕上一小节的平面坐标系中的四个象限
  • 每个象限中举例的开源项目与所处象限的关系是
    • 该场景为该项目的最典型使用场景
    • 众多数据管道项目都是跨象限的,但一定有它自己的主场
    • 就像NUC也具有了相当的移动性、便携性,但仍改变不了他是台式机

Data Pump

  • 中文直译数据泵,同样顾名思义
    • 水泵是用来把水从一个水池抽到另一个水池里的
    • 数据泵是用来把信息/事件从一个数据池(sink)抽到另一个数据池里的
  • 举例
    • logstash监控并读取日志文件的末尾,并将其送入elasticsearch
      • 此时不断增长的日志文件是数据池,elasticsearch作为搜索数据库同样也是数据池
    • flume依次读取hdfs中的文件,并将其送入mongodb
      • 此时hdfs作为分布式文件系统是数据池,同时mongodb作为文档nosql数据库也是数据池
  • 分析
    • 入口使用pull模型,对信源有更高的要求(存储缓存等)
    • 出口使用push模型,对信宿有更高的要求
    • 所以数据泵是一个小机灵鬼,把更为复杂的工作都交给了与之通信的实体
    • 他的工作是把信息从一个地方读出,再存到另一个地方,数据泵名副其实
    • 因为数据泵的本质工作是读取并传递,所以绝大部分来说数据泵都会有插件机制
      • 通过source和sink的插件设计,数据泵能够灵活与各类数据池交互,也能够广泛的借用开源社区的力量
      • 当然这也方便了我们对其进行二次开发,一举多得
  • 场景
    • 使用数据泵最常用的场景,就是数据收集
    • 一旦收集到数据,就立马发送给下一个实体
    • 虽然flume、fluentd等数据管道同样提供了基于内存的或者基于硬盘的数据缓存/队列能力
    • 但我们在这里有意的进行忽略,主要关注其本质的部分

Data Queue

  • 中文直译消息队列
    • 下了飞机我们等机场大巴的时候,会在大巴车门口排起长队 ,大巴接满了一车的人开走了,队伍中的人就会一起等下一班车过来,队列用来应对随着航班降落而产生的人流突发性的增长,同时能保证秩序和公平
    • 同样在消息队列中,消息队列被动的接收信源端发送过来的事件/数据并在本地缓存,同时尽可能快的推送给事件的消费端,在事件被消费过后就丢弃此事件相关信息
  • 举例
    • 使用rabbitmq消息队列异步调用远程服务rpc,在openstack各项目中使用的非常多
    • 监控服务产生了告警将其送入消息队列,消息经过路由以及复制后通过短信邮件IM等多种方式通知出去
  • 分析
    • 入口使用push模型,对自己有着更高的要求(存储缓存等)
    • 出口使用push模型,对信宿有更高的要求
    • 消息队列与数据泵相比,在入口处提升了对自己消息排队缓存能力的要求,队列的名称也就从此而来
    • 在队列中除了简单的传递,也能够进行路由、复制、过滤等复杂的逻辑
    • 但消息队列还是希望尽快的将消息传递到信宿(消费)端,从而降低自己的资源负载
    • 若此时消费者端已经过载,则消息会产生积压甚至丢失的情况
  • 场景
    • 最常用的场景就是发布订阅
    • 消息发送者将消息发送给队列,队列将消息推送给所有的订阅者
    • 虽然一般对消息队列的讨论对比都包括了出口处的push/pull模型,但此处依旧选择性忽略,关注其更本质的部分

Data River

  • 中文直译数据河流(我瞎起的)
    • 管道与河流同样是用于传输水资源的,但是河流的蓄水能力要比管道强的多得多,从而对洪峰的容忍能力也要高出N个量级
    • 在这个象限业界只有一个公认的标杆,即Kafka
  • 举例
    • 通过flume采集的数据先全部送入kafka存储削峰,再由另一个flume读取kafka中的消息写入hbase等持久化存储
    • 在OLAP的kappa架构中,一切原始数据、中间结果、最终结果都只落地Kafka,既做队列,又做存储
  • 分析
    • 入口使用push模型,对自己有着更高的要求(存储缓存等)
    • 出口使用pull模型,对自己同样有着更高的要求
    • 为了做到这么高的要求,kafka通过利用操作系统文件缓存、硬盘顺序读写等提高了读写性能
    • kafka通过topic分区、备份等方式提高了系统的可扩展性和可靠性
    • kafka支持消息的永不删除策略,这也是与消息队列和核心区别之一,也是kafka能临时顶起来当数据库的基础
    • 可以看到kafka把累活难活全部留给了自己,这就是kafka牛逼的地方
    • 我想这也是kafka存在于每一个大数据平台方案中的原因,真滴瑞斯拜
  • 场景
    • 所有需要做消息削峰、高性能持久化缓存的地方,都会使用kafka
    • 因为kafka已经做好了最难的部分,入口push、出口pull也只需要别人适配自己,保持自己代码的简洁性
    • 同时kafka与其他系统的对接问题,有众多的数据泵以及kafka connector来做,他们生来就是做这个的

Null

  • 第三象限,即左下角的象限,处于一个比较尴尬的地位
  • 入口使用pull模型,对信源有更高的要求
  • 出口使用pull模型,对自己有更高的要求
  • 然而信宿pull谁都是pull,为什么不去直接pull信源咧?
  • 要说是为了利用此象限项目的信源接口适配丰富性,以及缓存能力
  • 那么这种需求也会被(pull)flume(push) + (push)kafka(pull) = pull pull 完美替代
  • 我目前也没有看到专门为此象限而生的项目,自然也就没有名字了

Finally

  • 当可以用一个坐标系去描述当前数据管道纷繁生态中的每个项目后
  • 只要我们好好考虑一下当前需要的是数据泵,还是消息队列 or kafka
  • 就能够非常方便的去进入对应的领域进行选型了
  • 而在这个时候网上的各类实现细节、性能跑分对比,对我们来说也就更有价值了
  • 坐标系让我有了选型的底气,因为数据管道再怎么样,也逃不出这张图

你可能感兴趣的:(数据管道思考)