kafka源码分析-00: 实时帝国不是一天建成的

前言

  • 让我们爱上Kafka
  • 简单了解一下kafka
  • kafka是最易学最实用的分布式数据库
  • kafka是最好用的全家桶
  • kafka引领实时计算潮流
  • haskell具有最强大的实时计算技术
  • 下篇: kafka源码分析-01: kafka-client实时数据开天辟地

0. 让我们爱上Kafka

Kafka创造了实时帝国,让人无比激动,我认为每个人都应该认真读懂Kafka。因为,实时帝国将是数据处理的最终归宿。

1. 简单了解一下kafka。

为了便于后面的内容开展,我们先简单介绍一下Kafka的运行机制,具体细节不过多展开,将在后面章节中进一步细述。

Kafka分为server端跟client端。

对于server端来说,每个server节点叫做broker。

其中会选择一位controller, controller broker统一负责整个集群操作,从而使得所有broker保持一致的集群信息。
客户端可以连接任意broker节点,它会根据集群信息代理转发请求,所以我们称之为broker(代理)节点。

Kafka将数据拆分成几份,叫做partition。对于每个partition又会拷贝几份,叫做replica, 这些replica中第一个分配的叫做leader replica。

当创建一个topic的时候,controller根据集群信息,首先分配leader replica至broker一些节点,接着进行错位分配follower replica。follower replica并不能直接参与读入过程,它只是默默地同步leader replica的更新,期待有一天leader replica驾崩接任。
当然目前kafk 2.4版本有意向让follow replica也能进行读取操作,让我们试目以待。

每个kafka broker会负责一部分客户端consumer group的协调消费,这个组件叫做GroupCoordinator。之所以叫做协调,是因为主要逻辑并不在server端完成,而是在client完成,这也是kafka的特色之一。后续会详细介绍。

对于client端来说,分为admin, producer, client。

client会在请求的时候按照周期更新metadata信息,从而获取了整个集群信息。

admin客户端主要负责集群操作,大部分功能由shell封装提供,并不需要使用java api.

producer有个异步线程Sender,producer将数据打包放入Sender的队列中,Sender线程负责发送数据到服务器。发送数据的时候,为了增大吞吐量,我们可以不用逐条发送,而是延迟等待一定时间间隔或者达到一定size之后一起打包更多的数据。

consumer通过offset偏移量读取数据,如果没有偏移量,可以从头读取,或者最近读取。
而偏移量管理则是前面所提到的Consumer Group负责的,client可以发送offset请求至broker请求来完成。当然client也可以外置offset,我们这里不过多展开,后续进行介绍。
第一个连接到server端group coordinator的成为了consumer group的leader。
对于新加入了consumer group client端, server端会发送相关的信息至consumer group leader进行协调,重新rebalance分发所有的partition leader至各个client负载读取数据。

2. kafka是最易学最实用的分布式数据库

分布式数据库包含了网络与存储两部分。

一般来说,存储模块相比会比较复杂, 但是在Kafka里面不是问题。
因为Kafka是顺序读取的,直接采用了系统文件io读取即可。操作系统底层的缓存机制对于性能有着非常高的优化,不需要kafka过多介入。所以,存储模块相当简单,ReplicaManager每次写入时进行判断,如果内存数据达到文件大小或者时间间隔就写入磁盘。当然这里面涉及到状态化的log compact topic,主要用于保持最新的键数据,这里不具体展开,后文将会详细介绍。

Kafka的网络模块也非常简单。
服务端集群选取一个成员成为controller,这个选举过程非常简单,就是通过zookeeper去抢占节点,谁抢到就归谁,其它人等着让位。
当然Kafka打算往数据库模式走,想保留元数据历史,所以目前正在计划替换掉zookeeper,这里就不属于我们的讨论范畴了。

客户端Consumer通过服务端的GroupCoordinator进行协调完成资源分配。进而很简单就完成了负载均衡功能。

客户端Producer网络模块就更简单了,主要涉及打包记录的过程。打包发送即可。当然也不完全是特别简单,这里面涉及到顺序保证,严格一次, 事务性的问题。

整体上来说整体流程并不复杂。

3. kafka是最好用的全家桶

kafka的强大绝不仅仅止步于成为消息队列数据库。kafka有着完备的生态圈。

kafka项目整体分为两部分: apache与confluent两部分。
apache是linked公司的开源版本,confluent是这帮人出去创业的开源版本。
https://github.com/apache/kafka
https://github.com/confluentinc

首先来看apache kafka部分:

image.png

kafka部分包含以下几个部分:

  • kafka-client
  • kafka-tools
  • kafka-core
  • kafka-streams
  • kafka-connect

a) kafka-client 客户端功能。

admin客户端负责集群管理,主要是topic创建,节点配置consumer group管理等,并不需要编程,大部分都有相应的shell接口封装。
producer客户端,负责发送数据。主要功能包含打包,事务,严格一次,顺序保证,数据一致性保证。
consumer客户端,负责消费数据。主要包括consumer group rebalance 负载均衡, 偏移量管理。

b) kafka-tools 集群管理操作

kafka-tools里面功能与admin客户端类似,都通过shell接口提供,功能更面向应用一点。
主要包括数据迁移,跨集群数据同步,压力测试等。

c) kafka-core 服务端逻辑(scala实现)

kafka-core里面主要是服务端实现逻辑。
包括controller集群管理, GroupCoordinator消费组管理, ReplicaManager日志文件管理, TransactionStateManager事务管理等一系列功能.

d) kafka-streams 超级实时处理库

kafka-streams包含了两部分api,一部分底层实现,一部分dsl构建。kafka-streams建立在kafka-client之上进行操作。

底层部分就是一个dag处理流程,dag工作流主要的逻辑当然是分流branch跟合流merge。然后每个节点包括具体的处理逻辑。当然在topology你可以关联状态存储器进行使用,这个对于实时计算非常重要,将在后文详细介绍。

dsl部分则是抽象出来的逻辑处理,偏向于函数式偏程。主要包括不带状态的map/filter/flatMap,带状态的process/transform,以及stream-stream, stream-table, table-table各种join操作,group操作,以及branch与merge流程控制。

kafka streams有啥特别的呢?
首先, kafka streams是个库。这个特性非常重要。其它的flink, storm实时处理引擎是个框架。框架一般是自我管理的,而库是可以非常方便集成与定制的。当然kafka streams这上也提供了ksql框架,后文再做介绍。

kafka streams与其它流式处理框架有啥差异?
kafka streams的逻辑非常简单,写入topic, 读入topic完成 所有操作。由于这个特性,最终导致下面的一些差异点。
首先kafka streams不是节点对节点进行处理的。比如传统的map/reduce这种处理,是reduce直接接收map的数据。kafka引入了中间内部状态的概念,所有producer的数据写入internal topic, 而consumer读取internal topic,从而达到了解耦合。

除了中间内部状态,还有一种状态,叫做local state,属于每个partition处理过程私有的状态。比如对于每个partition进行处理时,内部的聚合值。
这里面就涉及了一个问题,如果当前partition处理的client挂掉了,在其它机器重启会怎么样呢? 本地的local store是无法跨机器读取的。所以我们这里要联想到之前kafka存储模块提供的log compact topic。对于local store里面的状态变化,kafka提供了相应的backlog,一旦节点挂掉,从其它机器是可以完全重建的。

kafka streams的前身samza就是这种处理逻辑,已经在商业应用上有了非常多的应用案例。由于状态的恢复,以及内部状态的开销比其它实时计算大很多, 所有这种机制也不乏有批评者。当然kafka 2.3也在积极改善这种情况,通过instance.group以及static member来尽量规避不同节点状态的切换,使得本机故障之后最好能够本机恢复来避免状态迁移操作。

kafka streams的扩展性是其它实时计算引擎不可比拟的!
如果我们把前面的kafka-core当作存储层,那么kafka streams就是计算层, kafka-stream与kafka-core。
所以,完全有理由相信,我们可以通过rust重写kafka-core加快性能, 而kafka stream依赖可以原样使用。同理,我们可以通过haskell重写kafka-streams,而原样使用kafka-core。
这个绝不是空想的,现在rust已经实现了自己的kafka client, 自然也可以实现自己的kafka streams。

之所以有如此强大的功能,与kafka的group coordinator有着不可区分的联系。首先kafka-core服务端已经协调了资源分配功能,而这个具体的实现逻辑在客户端进行定制实现即可。所以我们只关心具体逻辑,而网络层面的东西GroupCoodinator已经帮助我们完成了。

这个功能也是有实际应用案例了,也就是我们下文要介绍的kafka connect。kafka connect就是定制了自己的consumerCoordinator逻辑完成了更有趣的功能。

e) kafka-connect 连接一切数据源。

前面讲了kafka streams所有数据处理读写都是通过topic以及internal topic完成。那么自然需要从外部数据源读取数据到topic,写出topic到外部数据源。所以kafka-connect登场了。

kafka-connect是一个插件模式,可以加载不同的数据源插件,可以加载不同的transform转换器。

kafka-connect真正的强大来自于它支持单机模式与集群模式。而集群模式它提供了非常强大的分布式任务管理功能,可以非常方便地通过restful服务进行任务运行控制,任务错误排查等。

apache kafka里面仅仅提供了基本的kafka-connect模块接口,真正的大部分插件是由confluent团队开源完成的。
目前kafka-connect插件非常全面,异常强大,可以说应有尽有。
https://docs.confluent.io/current/connect/managing/connectors.html

These supported connectors are packaged and available natively with Confluent Platform:

*   [Active MQ Source Connector](https://docs.confluent.io/current/connect/kafka-connect-activemq/index.html#activemq-source-connector)
*   [Amazon S3 Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-s3/index.html#connect-s3)
*   [Confluent Replicator](https://docs.confluent.io/current/connect/kafka-connect-replicator/index.html#connect-replicator)
*   [Elasticsearch Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-elasticsearch/index.html#elasticsearch-overview)
*   [FileStream Connector](https://docs.confluent.io/current/connect/filestream_connector.html#connect-filestreamconnector) (Development and Testing)
*   [IBM MQ Source Connector](https://docs.confluent.io/current/connect/kafka-connect-ibmmq/index.html#ibmmq-source-connector)
*   [JDBC Connector (Source and Sink)](https://docs.confluent.io/current/connect/kafka-connect-jdbc/index.html#connect-jdbc)
*   [JMS Source Connector](https://docs.confluent.io/current/connect/kafka-connect-jms/index.html#jms-source-connector)

These supported connectors must be installed separately via [Confluent Hub](https://www.confluent.io/hub/):

*   [ActiveMQ Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-activemq/sink/index.html#activemq-sink-connector)
*   [Amazon S3 Source Connector](https://docs.confluent.io/current/connect/kafka-connect-s3-source/index.html#s3source-connector)
*   [AWS DynamoDB Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-aws-dynamodb/index.html#connect-dynamodb)
*   [AWS Lambda Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-aws-lambda/index.html#lambda-sink-connector)
*   [AWS Redshift Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-aws-redshift/index.html#connect-redshift)
*   [Azure Blob Storage Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-azure-blob-storage/index.html#connect-azure-blob-storage)
*   [Azure Blob Storage Source Connector](https://docs.confluent.io/current/connect/kafka-connect-azure-blob-storage/source/index.html#azure-blob-storage-source-connector)
*   [Azure Data Lake Storage Gen1 Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-azure-data-lake-gen1-storage/index.html#connect-azure-data-lake-gen1-storage)
*   [Azure Data Lake Storage Gen2 Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-azure-data-lake-gen2-storage/index.html#connect-azure-data-lake-gen2-storage)
*   [Azure Event Hubs Source Connector](https://docs.confluent.io/current/connect/kafka-connect-azure-event-hubs/index.html#event-hubs-source-connector)
*   [Azure Functions Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-azure-functions/index.html#connect-azure-functions-connector)
*   [Cassandra Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-cassandra/index.html#cassandra-sink-connector)
*   [Data Diode Connector (Source and Sink)](https://docs.confluent.io/current/connect/kafka-connect-data-diode/index.html#connect-datadiode-connector)
*   [Google BigQuery Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-bigquery/index.html#bigquery-connector)
*   [Google Cloud BigTable Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-gcp-bigtable/index.html#connect-bigtable)
*   [Google Cloud Functions Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-gcp-functions/index.html#connect-gcp-functions-connector)
*   [Google Cloud Spanner Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-gcp-spanner/index.html#connect-spanner)
*   [Google Cloud Storage Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-gcs/index.html#connect-gcs)
*   [Google Cloud Storage Source Connector](https://docs.confluent.io/current/connect/kafka-connect-gcs/source/index.html#connect-gcs-source)
*   [HDFS 2 Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-hdfs/index.html#connect-hdfs)
*   [HDFS 3 Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-hdfs/hdfs3/index.html#hdfs3-connector)
*   [HTTP Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-http/index.html#connect-http-connector)
*   [IBM MQ Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-ibmmq/sink/index.html#ibmmq-sink-connector)
*   [JMS Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-jms/sink/index.html#jms-sink-connector)
*   [Kinesis Source Connector](https://docs.confluent.io/current/connect/kafka-connect-kinesis/index.html#kinesis-source-connector)
*   [MapR DB Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-maprdb/index.html#map-r-d-b-sink-connector)
*   [Microsoft SQL Server Source Connector](https://docs.confluent.io/current/connect/kafka-connect-cdc-mssql/index.html#ms-sql-source-connector) (Deprecated)
*   [MongoDB Source Connector (Debezium)](https://docs.confluent.io/current/connect/debezium-connect-mongodb/index.html#mongodb-source-connector)
*   [MQTT Connector (Source and Sink)](https://docs.confluent.io/current/connect/kafka-connect-mqtt/index.html#connect-mqtt-connector)
*   [MySQL Source Connector (Debezium)](https://docs.confluent.io/current/connect/debezium-connect-mysql/index.html#mysql-source-connector)
*   [Netezza Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-netezza/index.html#netezza-sink)
*   [OmniSci Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-omnisci/index.html#connect-omnisci-connector)
*   [Pivotal Gemfire Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-pivotal-gemfire/index.html#connect-pivotal-gemfire)
*   [PostgresSQL Source Connector (Debezium)](https://docs.confluent.io/current/connect/debezium-connect-postgres/index.html#postgres-source-connector)
*   [RabbitMQ Source Connector](https://docs.confluent.io/current/connect/kafka-connect-rabbitmq/index.html#rabbit-m-q-source-connector)
*   [Salesforce Change Data Capture Source Connector](https://docs.confluent.io/current/connect/kafka-connect-salesforce/change-data-capture/index.html#salesforce-cdc-source-connector)
*   [Salesforce Connector (Source and Sink)](https://docs.confluent.io/current/connect/kafka-connect-salesforce/index.html#salesforce-source-connector)
*   [Splunk Sink Connector](https://docs.confluent.io/current/connect/kafka-connect-splunk/splunk-sink/index.html#splunk-sink-connector)
*   [Spool Dir Connector](https://docs.confluent.io/current/connect/kafka-connect-spooldir/index.html#spooldir-connector)
*   [SQL Server Source Connector (Debezium)](https://docs.confluent.io/current/connect/debezium-connect-sqlserver/index.html#sqlserver-source-connector)
*   [Syslog Source Connector](https://docs.confluent.io/current/connect/kafka-connect-syslog/index.html#syslog-source-connector)

当然我们需要注意到的一点是,kafka connect胜在于集群模式与任务管理。集群模式需要注意到的一个点是它是推送方才能自我管理。

如果数据源没有提供数据实时获取接口自然是没有控制权的。这种情况来自于操作系统文件系统,文件系统本身没有提供远程数据实时获取接口,这个时候我建议采用filebeat来抽取数据到kafka中。

当然也可以使用kafka connect单机版模式,不过目前kafka connect的核心不在于此,所以它的FileSystem数据源接口是远远比不上filebeat的。filebeat扫描文件的inode,所以日志文件切换的时候不会丢数据。filebeat可以支持多行文件模式。filebeat采用go语言编写,性能强悍内存占用极低。

我们可以看到, kafka-client/kafka-core提供了基础的存储服务,kafka-streams提供了实时计算库, kafka-connect提供了外部数据源的集成,已经非常完美了。让我们惊喜的是, Confluent公司的开源让kafka更完美。

接着来看Confluent kafka部分:

前面已经介绍过了Confluent提供了几乎完备的kafka connect 插件,让我们不用再写代码。这里就不过多介绍了。

Confluent更是提供了更强大的三大组件,将简单好用的革命进行到底:


image.png
  • kafka-rest
  • schema-registry
  • ksql

a) kafka-rest 将一切操作简化成http

有了kafka-rest,外部系统集成就非常方便了,只需要发送http请求,任何依赖都不需要,简单感动得不要不要的。。。

b) schema-registry 实时数仓元数据管理

实时数仓是一场革命,虽然任重而道远,国内水平极其低下。但是不可否认的是,它是不可阻挡的未来。对于实时计算来说,有一套统一的元数据管理是至关重要的。所以Confluent公司简直救民于水生火热之中,成了实时数仓前进道路中最鲜明的领军者。

c) ksql 将一切数据处理sql化。

由于实时计算与图计算对于sql地不断扩展,sql远远不是一个语言了,它是实时引擎的一个配置文件。
所以我们可以把实时计算分为三层: 存储+计算+配置。

ksql也是异常强大,它建立在kafka stream之上形成了一套自有的框架体系。它把自己的sql发送到command topic,然后各个ksql server解析生成kafka stream任务进行处理,这里不做过多介绍,我们后面会进行深入剖析。

ksql使用友好度是非常高于flink的,它的命令行接口建立在rest接口这上,非常简单好用。并且支持编写udf。当然目前它的sql成熟度是远远不及flink的,但是并不代表未来ksql不会奋起反击。

4. kafka引领实时计算潮流

很多人对于实时计算比较陌生。
毕竟实时计算是个出来不久的新东西,大部分只是停留在使用层次上。

那么我们首先来介绍一些实时计算术语,便于大家理解加深。

kafka团队的人,曾经说过,实时计算底层有两大难题,一个是顺序保证,一个是严格一次。

1) 数据的顺序保证

如何保证数据的顺序呢,kafka引入了in-flight请求,当in-flight请求值为1的时候,就能保证顺序了。producer发送消息到server的时候,如果已经有1个请求没有得到响应,则不能再进行发送。所以每个请求发送响应之后,才能继续发送,这样就有了顺序保证

2) 数据的严格一次

如果数据直接进行异步处理,那么数据发送不成功,就产生了最多一次。一条记录发送了一次,可能会丢失。

如果我们不想丢数据,我们就会重发,就会产生下游进行了处理,但是网络失败致使下洲却不知道的情况,上游又进行了重发。所以这种情况下,每条记录都要有应答,最终数据可以发送一次就成功,或者多次发送才有应答。最终形成了至少一次。

对于第二种情况,我们想要严格一次的处理,怎么办呢?
一种是业务上的幂等操作,也就是说,消息是可以重复发送的,比如一个人的状态,就算发送多次,始终保留最新值即可。
另一种是底层状态事务性,也就是说,我的上游跟下游的状态同时切换。这样达到了所谓的all-or-nothing效果。

对于kafka streams来说,由于使用的都是kafka自己的状态,所以事务性很容易保证。对于kafka connect数据推送来说, 如果使用外部的偏移量与数据操作同时切换,也可以达到严格一次。对于kafka connect数据抽取来说,kafka producer已经提供了严格一次的功能。

3) 数据的回压

实时处理存在这样一个情形,就是消费速度远远落后于读取速度,数据处理能力跟不上。这样下去导致消息堆压,最终发生内存溢出。

当然我们可以加大数据处理的并行度,但是由于业务的峰值变化,我们是很难预测这个并行度究竟多少是合理的。

所以我们需要处理者能够反馈读取者,使得数据处理吃力的时候,不再读取太多数据。

kafka是不存在这种情况的,首先producer跟consumer是解耦合的。producer不会影响consumer。
而kafka streams的所有处理逻辑都是通过topic, internal topic来处理的,也全部是解耦合的。

4) 状态管理

实时计算与批量计算的最大不同在于状态管理。
状态分为两种,一种是内部状态,一种是外部状态。

批量计算大量采用内部状态,导致的问题就是内存占用率极高。
比如我们计算group by, 如果是批量计算,它会把每一个分组都会用内部状态来存储,如果内部状态过大,可能就涉及io落地的过程,引起极大的磁盘io开销。

而实时计算大量采用外部状态,在状态上它抽象出了table与stream的概念。table就是k-v存储,stream就是k-v数据流, stream可以通过k-v生成table状态,table状态可以通过历史变化生成stream。
kafka为了支持这种逻辑,所以底层添加了rocksdb与log compact topic。

这样,对于group by, join之类的操作,实时计算是通过外部状态来管理,直接找到对应的k-v值进行相应的处理即可。

有了外部状态,我们可以扩展做更多事情。比如我们可以一次遍历处理不同维度的分支结果。在kafka叫做branch/merge,当然比起haskell的conduit zip实时计算组合子模式还是差太远。但是从目前上来说已经可以获得非常高的收益了。

5) 实时join

实时计算经常碰到的问题,就是需要关联不同的数据表信息。
在实时计算领导我们分为三种情况, table-table, table-stream, stream-stream join。
对于table-table, table-stream join,就是简单的遍历以及查询table的kv数据做关联。基本上没有批量处理的那种hash join, merge sort那么大的内存开光彩。
对于stream-stream处理,则是通过store存储各自的滞后窗口信息,使得两个stream之间,可以去关联这个间隔有效期内的数据。主要用于两个流水表之间的关联操作。

6) 资源管理

实时计算对资源管理的要求并不是特别高,这个是由于实时是一直运行的。所以我们完全有理由k8s这种资源分配器,而不是资源调度器有着更广阔的前景。
对于实时计算来说,目前的并行度模式由于资源管理器模式的限制,是不能动态添加改变的。但是相信在未来,实时计算一定可以像微服务一样做到动态伸缩

7) 批量计算的终结者

我们可以看到:
有了外部状态之后,我们不再需要高消耗的内存,并且可以高度定制化解决需要明细查询的非累积聚合的变量逻辑。
有了分流合流特性之后,我们可以一次遍历多次计算
有了实时处理模式之后,所有的数据处理都是同步进行,没有时间延迟。

有没有批量计算做不到实时计算做不到的东西呢?没有!
有没有实时计算做得到批量计算做不到的东西呢?很多!

尽管实时计算还有很长的路要走,我们可以看到前方一片光明。
而kafka在这个方向上,在整体推进上,让我们耳目一新。

5. haskell具有最强大的实时计算技术

不管是kafka streams还是flink也好, 本质上底层都是函数式编程技术。

它们这种函数式技术非常落后,已经落后于haskell两个时代,落后于clojure一个时代。

a) 组合子特性

首先haskell天生具有组合子特性,也就是说两个计算逻辑可以直接合并起来,相当于电流的串联并联。

kafka stream以及flink是做不到这点的,所以必须借助于更复杂的东西来完成,也就是dag topology。

比如我们有两个分支,分别对数据流奇数进行求和,对偶数求最大值。这种分流就不可能有原生的dsl支持。

或者说我们有两个分支,进行不同的数据处理逻辑之后,然后合并到一个流里面。这种合流也不可能有原生的dsl支持。

所以只能通过dag来构造,就引入了非常大的复杂度。

b) 分层处理特性

对于dag topology这种封装,由于缺乏底层原生函数式的支持行为,就会引发很多惨案,写起来非常不便利。

对于dag topology这种数据层次的封装,有个很显然的问题,就是数据是按行来处理的,它并不能按列来处理。

比如我们有个文件,我们找到某个标识的作为第一部分,剩下的作为第二部分处理。这个在topology dsl里面很难做到。
因为它是基于流的,只能按流的状态进行封装。流消耗了就占用了内存,而没法惰性起来。
比如在haskell里面,我们可以takeWhile进行分层产生不同的惰性集合,然后对于惰性集合再分别进行分流合流依次处理。

简单来说,在haskell处理里面我们可以按列来惰性拆分数据,接着按行来处理数据。

c) 状态抽象

haskell具有最强大状态抽象能力,state monad, reader monad, writer monad,并且可以与正常逻辑进行直接复合起来。
目前实时计算的状态封装尚处理非常原始的阶段,haskell未来这方面的发展十分可期。

由于kafka-core提供了基本的协调功能,所以使用haskell重写纯的kafka-client以及kafka-stream,并利用k8s进行资源分配,是非常有趣的一个发展方向。

d) 模式管理

我们可以看到,大部分实时计算框架不具备动态模式类型特性。
所有的数据模式只能通过数组之类的对象去管理,操作起来十分不便。
而haskell具备dependency type,也就是说通过type可以动态生成类型操作。可以参见最为知名的库vinyl。

e) 半结构化数据处理

对于实时计算领域来说,我们更倾向于将数据用半结构化来存储,比如最常见的数据结构就是json, avro。
对于这种数据结构,目前haskell的lens依旧是这个领域的老大。可以深层次钻透数据,通过函数修改操作访问数据。

6. 下篇: kafka源码分析-01: kafka-client实时数据开天辟地

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容

  • Apache kafka是一个分布式流平台。这到底是什么意思? 我们认为流平台具有三个关键功能: 它允许发布和订阅...
    狼牙战士阅读 623评论 0 0
  • Step 1: 下载代码 下载0.10.2.0版本并且解压它。 > tar -xzf kafka_2.10-0.1...
    GK_斯皮利特阅读 1,437评论 0 3
  • 大致可以通过上述情况进行排除 1.kafka服务器问题 查看日志是否有报错,网络访问问题等。 2. kafka p...
    生活的探路者阅读 7,484评论 0 10
  • guān zì zài pú sà , 观 自 在 菩 萨 ,(观察内在,自见菩萨) xíng shēn bō r...
    武丹yoyo阅读 177评论 0 3
  • on the stock exchange ,a woman with short brown hair abov...
    onetwo3go阅读 174评论 0 0