0%

什么是流式计算

流式计算一般被用来和批量计算做比较。批量计算往往有一个固定的数据集作为输入并计算结果。而流式计算的输入往往是“无界”的(Unbounded Data),持续输入的,即永远拿不到全量数据去做计算;同时,计算结果也是持续输出的,只能拿到某一个时刻的结果,而不是最终的结果。(批量计算是全量的:拿到一批数据,计算一个结果;流式计算是增量的:数据持续输入,持续计算最新的结果)

流式计算框架

Storm Trident Spark Streaming Flink Samza Kafka streams
数据流模型 原生 微批 微批 原生 原生 原生
状态存储 不支持状态管理 本地存储,外部数据库 多种状态存储方式 多种状态存储方式 本地存储,Kafka主题 本地存储,日志变更主题
时延
吞吐量
保障机制 at-least-once exactly-once exactly-once exactly-once at-least-once exactly-once
容错机制 record ack record ack RDD based,checkpoint checkpoint Kafka log-base Kafka log
成熟度 较多不足,但实际应用比较广泛 Storm基础上改进 流行的框架之一,Spark大环境 较新的流处理框架,性能非常优秀 基于Kafka作为数据源 完全基于Kafka集群实现
定位 框架 框架 框架 框架 框架 类库

Kafka Streams

Kafka Streams is a client library for building applications and microservices, where the input and output data are stored in Kafka clusters. It combines the simplicity of writing and deploying standard Java and Scala applications on the client side with the benefits of Kafka’s server-side cluster technology.

Kafka Streams是一个构建应用程序和微服务的客户端库,并且输入数据个输出数据均是保存在Kafka集群上的。Kafka Streams主要有如下特点:

  • 非常简单的客户端库,可以非常容易的嵌入到任何java应用程序与任何应用程序进行封装集成。
  • 使用Kafka集群作为消息层,没有外部依赖。
  • 支持本地状态存储。
  • 提供了快速故障切换分布式处理和容错能力。
  • 提供了非常方便的API。
  • 支持exactly-once语义
  • 支持纪录级的处理,实现毫秒级的延迟
  • 提供High-Level的Stream DSL和Low-Level的Processor API

采用one-record-at-a-time的消息处理方式,实现消息处理的低延迟。
但是Kafka Streams的设计目标是足够轻量,所以很难满足对大体量的复杂计算需求,并且数据的输入和输出均是依靠Kafka集群,对于其他的数据源需要借助Kafka connect将数据输入到Kafka主题中,然后在通过Kafka Streams程序进行处理,并通过Kafka connect将主题中的数据转存到其他数据源。

所以Kafka Streams更适合计算复杂度较小,数据流动过程是Kafka->Kafka的场景。

Storm

在Storm中,需要先设计一个实时计算结构,我们称之为拓扑(topology)。之后,这个拓扑结构会被提交给集群,其中主节点(master node)负责给工作节点(worker node)分配代码,工作节点负责执行代码。在一个拓扑结构中,包含spout和bolt两种角色。数据在spouts之间传递,这些spouts将数据流以tuple元组的形式发送;而bolt则负责转换数据流。

  • 状态管理:无状态,需用户自行进行状态管理
  • 窗口支持:对事件窗口支持较弱,缓存整个窗口的所有数据,窗口结束时一起计算
  • 消息投递:At Most Once/At Least Once
  • 容错方式:对每个消息进行全链路跟踪,失败或超时进行重发。

Spark Streaming

采用微批的方式,提高了吞吐性能。Spark streaming批量读取数据源中的数据,然后把每个batch转化成内部的RDD。Spark streaming以batch为单位进行计算,而不是以record为单位,大大减少了ack所需的开销,显著满足了高吞吐、低延迟的要求,同时也提供exactly once功能。但也因为处理数据的粒度变大,导致Spark streaming的数据延时不如Storm,Spark streaming是秒级返回结果(与设置的batch间隔有关),Storm则是毫秒级。

但是Spark Streaming的优点是可以与Spark大环境进行有效的结合。

Flink

Flink 是一种可以处理批处理任务的流处理框架。Flink 流处理为先的方法可提供低延迟,高吞吐率,近乎逐项处理的能力,并且提供了复杂计算的能力。

Flink 完全支持流处理,也就是说作为流处理看待时,输入数据流是无界的;批处理被作为一种特殊的流处理,只是它的输入数据流被定义为有界的。这与 Spark streaming 不同,Spark streaming 是将流处理视为无限个有界的批处理(microbatch)。

  • 有状态计算的 Exactly-once 语义。状态是指 flink 能够维护数据在时序上的聚类和聚合,同时它的 checkpoint 机制可以方便快速的做出失败重试;
  • 支持带有事件时间(event time)语义的流处理和窗口处理。事件时间的语义使流计算的结果更加精确,尤其在事件到达无序或者延迟的情况下;
  • 支持高度灵活的窗口(window)操作。支持基于 time、count、session,以及 data-driven 的窗口操作,能很好的对现实环境中的创建的数据进行建模;
  • 轻量的容错处理(fault tolerance)。它使得系统既能保持高的吞吐率又能保证 exactly-once 的一致性。通过轻量的 state snapshots 实现;
  • 支持高吞吐、低延迟、高性能的流处理;
  • 支持 savepoints 机制(一般手动触发),可以将应用的运行状态保存下来;在升级应用或者处理历史数据上,能够做到无状态丢失和最小停机时间;
  • 支持大规模的集群模式,支持 yarn、Mesos。可运行在成千上万的节点上;
  • 支持具有 Backpressure 功能的持续流模型;
  • Flink 在 JVM 内部实现了自己的内存管理,包括完善的内存架构和 OOM error prevention;
  • 支持迭代计算;
  • 支持程序自动优化:避免特定情况下 Shuffle、排序等昂贵操作,中间结果进行缓存。

说明一

通常来说,对于单独的消息系统而言,语义分为如下三种:

至多一次(At most once):不管 Writer 在等待 ACK 时是否发生超时或者得到错误异常,Writer 都不会重新发送 Event,因此会有数据丢失的风险。在具体的实现过程中,这一种语义无需做任何额外的控制,实现起来最为简单,因此也通常有着最优的性能。在某些特定的场景中,我们只希望追求极致的性能而不关心数据的丢失,可能会选用此方案。

至少一次(At least once):如果 Writer 在等待 ACK 时发生超时或者得到错误异常,Writer 将会重新发送消息,这样能保证每个 Event 至少被处理一次,保证了数据不会丢失,从而提高了系统的可靠性,但同时会带来数据重复的问题,例如,当 Writer 往 Stream 中成功写入一个 Event,但是当系统尝试给 Writer 返回 ACK 的时候出现网络异常,Writer 因没有收到 ACK 而判断为写入 Event 失败,因此 Writer 还是会重新发送此 Event,导致数据重复。

仅一次(Exactly once):在系统发生异常时,Writer 可以尝试多次重新发送 Event,同时能保证最终每个 Event 只被写入一次。一些对数据准确性要求非常高的系统需要保证 exactly-once 语义,譬如支付系统,当用户在移动端付款时,很有可能会因为网络原因导致延时较长甚至超时,用户可能会手动进行刷新操作,如果没有 exactly-once 的语义支持,很有可能会发生两次扣费,我们绝对不希望此类错误发生。

说明二

美团flink测试

测试结论

推荐使用 Flink 的场景

  • 实时计算场景建议考虑使用 Flink 框架进行计算:
  • 要求消息投递语义为 Exactly Once 的场景;
  • 数据量较大,要求高吞吐低延迟的场景;
  • 需要进行状态管理或窗口统计的场景。

说明三 - 语言支持

Spark和flink都是JVM语言开发,在API层对java和Scala语言支持较好,python语言API支持,但是效率不高,其它语言几乎不支持。

什么是serverless?

简单的定义

Serverless(无服务器架构)指的是服务端逻辑由开发者实现,运行在无状态的计算容器中,由事件触发,完全被第三方管理,而业务层面的状态则记录在数据库或存储资源中。

进阶的定义

Serverless是由事件(event)驱动(例如 HTTP、pub/sub)的全托管计算服务。用户无需管理服务器等基础设施,只需编写代码和选择触发器(trigger),比如 RPC 请求、定时器等并上传,其余的工作(如实例选择、扩缩容、部署、容灾、监控、日志、安全补丁等)全部由 serverless 系统托管。用户只需要为代码实际运行消耗的资源付费——代码未运行则不产生费用。

对比serverful

Serverless 相对于 serverful,对业务用户强调 noserver(serverless 并不是说没有服务器,只是业务人员无需关注服务器了,代码仍然是运行在真实存在的服务器上)的运维理念,业务人员只需要聚焦业务逻辑代码。

Serverless 相比 serverful,有以下 3 个改变(来自 Berkeley 的总结):

  • 弱化了存储和计算之间的联系。服务的储存和计算被分开部署和收费,存储不再是服务本身的一部分,而是演变成了独立的云服务,这使得计算变得无状态化,更容易调度和扩缩容,同时也降低了数据丢失的风险。
  • 代码的执行不再需要手动分配资源。不需要为服务的运行指定需要的资源(比如使用几台机器、多大的带宽、多大的磁盘等),只需要提供一份代码,剩下的交由 serverless 平台去处理就行了。当前阶段的实现平台分配资源时还需要用户方提供一些策略,例如单个实例的规格和最大并发数,单实例的最大 CPU 使用率。理想的情况是通过某些学习算法来进行完全自动的自适应分配。
  • 按使用量计费。Serverless按照服务的使用量(调用次数、时长等)计费,而不是像传统的 serverful 服务那样,按照使用的资源(ECS 实例、VM 的规格等)计费。

serverless分类

Serverless 不如 IaaS 和 PaaS 那么好理解,因为它通常包含了两个领域 BaaS(Backend as a Service)和 FaaS(Function as a Service)。

BaaS

BaaS(Backend as a Service)后端即服务,一般是一个个的 API 调用后端或别人已经实现好的程序逻辑,比如身份验证服务 Auth0,这些 BaaS 通常会用来管理数据,还有很多公有云上提供的我们常用的开源软件的商用服务,比如亚马逊的 RDS 可以替代我们自己部署的 MySQL,还有各种其它数据库和存储服务。

FaaS

FaaS(Functions as a Service)函数即服务,FaaS 是无服务器计算的一种形式,当前使用最广泛的是 AWS 的 Lambada。

Serverless 的使用场景

虽然 Serverless 的应用很广泛,但是其也有局限性,Serverless 比较适合以下场景:

  • 异步的并发,组件可独立部署和扩展
  • 应对突发或服务使用量不可预测(主要是为了节约成本,因为 Serverless 应用在不运行时不收费)
  • 短暂、无状态的应用,对冷启动时间不敏感
  • 需要快速开发迭代的业务(因为无需提前申请资源,因此可以加快业务上线速度)

Serverless 的使用场景示例如:

  • ETL
  • 机器学习及 AI 模型处理
  • 图片处理
  • IoT 传感器数据分析
  • 流处理
  • 聊天机器人

serverless与云原生

Serverless 是云原生技术发展的高级阶段,可以使开发者更聚焦在业务逻辑,而减少对基础设施的关注。
Serverless 在云原生技术中的地位

开源serverless框架

Kubernetes 的蓬勃发展由催生了一系列以它为基础的 Serverless 应用,目前开源的 Serverless 框架大多以 Kubernetes 为基础。

开源框架

  • Apache OpenWhisk,一种多功能、具有行业优势的 Serverless 解决方案
  • Fission,第一个真正的 Kubernetes Serverless 平台
  • Kubeless,在 Serverless 中使用 Kubernetes API 的早期先驱
  • OpenFaaS,Kubernetes 上的简单 serverless
  • Knative,又被戏称为:所有你的 OSS serverless(和 Ingress)均属于我们
  • 其他开源 serverless 平台,仔细观察#serverless 空间,你还会注意到还有很多其他产品,比如 -来自Oracle 的Fn , Pivotal 的Riff, VMWare 的 Dispatch, Galatic Fog , Nuclio , Virtual Kubelet ,PipelineAI, Nuclio ,可能还有更多。对不起,乍一眼看的话,它们中的大多数都很快就会不敌 Knative。

更多请点击…

原文链接

原文链接

安装

kubectl apply -f https://raw.githubusercontent.com/influxdata/docs-v2/master/static/downloads/influxdb-k8-minikube.yaml
kubectl get pods -n influxdb
kubectl describe service -n influxdb influxdb
kubectl port-forward -n influxdb service/influxdb 9999:9999

yaml

---
apiVersion: v1
kind: Namespace
metadata:
    name: influxdb
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
    labels:
        app: influxdb
    name: influxdb
    namespace: influxdb
spec:
    replicas: 1
    selector:
        matchLabels:
            app: influxdb
    serviceName: influxdb
    template:
        metadata:
            labels:
                app: influxdb
        spec:
            containers:
              - image: quay.io/influxdb/influxdb:2.0.0-beta
                name: influxdb
                ports:
                  - containerPort: 9999
                    name: influxdb
                volumeMounts:
                  - mountPath: /root/.influxdbv2
                    name: data
    volumeClaimTemplates:
      - metadata:
            name: data
            namespace: influxdb
        spec:
            accessModes:
              - ReadWriteOnce
            resources:
                requests:
                    storage: 10G
---
apiVersion: v1
kind: Service
metadata:
    name: influxdb
    namespace: influxdb
spec:
    ports:
      - name: influxdb
        port: 9999
        targetPort: 9999
    selector:
        app: influxdb
    type: ClusterIP

docker run --name influxdb -p 9999:9999 quay.io/influxdb/influxdb:2.0.0-beta
docker run -p 9999:9999 quay.io/influxdb/influxdb:2.0.0-beta --reporting-disabled
docker exec -it influxdb /bin/bash

tag的使用

  • 把你经常查询的字段作为tag
  • 如果你要对其使用GROUP BY(),也要放在tag中
  • 如果你要对其使用InfluxQL函数,则将其放到field中
  • 如果你需要存储的值不是字符串,则需要放到field中,因为tag value只能是字符串
  • tags不要包含高度可变的信息,如UUID,哈希值和随机字符串,这将导致数据库中的大量series cardinality。

    series cardinality高是许多数据库高内存使用的主要原因

  • 用tag区分数据比使用详细的measurement名字更好
  • 不要把多条信息放到一个tag里面