Google cloud dataflow 使用状态或计时器时避免重新洗牌?

Google cloud dataflow 使用状态或计时器时避免重新洗牌?,google-cloud-dataflow,apache-beam,Google Cloud Dataflow,Apache Beam,我发现自己在编写Beam管道时需要使用state或timer,其中数据可能已经被我不想干扰的前一个GroupByKey以某种方式分割。但是API说状态或定时器需要KV输入到PTransform。可能有状态/timerful转换在内部执行GroupByKey 有没有一种方法可以使用状态/计时器而无需重新排列/重新排列 下面是一个具体的用例:我在实现自己的度量集合而不是使用beam内置的Stackdriver度量时遇到了性能问题,其中涉及洗牌的转换的系统延迟开始出现,并且通常在一段时间后不会恢复 这

我发现自己在编写Beam管道时需要使用state或timer,其中数据可能已经被我不想干扰的前一个
GroupByKey
以某种方式分割。但是API说状态或定时器需要
KV
输入到
PTransform
。可能有状态/timerful转换在内部执行
GroupByKey

有没有一种方法可以使用状态/计时器而无需重新排列/重新排列

下面是一个具体的用例:我在实现自己的度量集合而不是使用beam内置的Stackdriver度量时遇到了性能问题,其中涉及洗牌的转换的系统延迟开始出现,并且通常在一段时间后不会恢复

这里是相关的代码,我将数据可能以不同方式分割的不同位置的度量值汇集到一个键中,这仅仅是因为我需要使用计时器

    metricsFromVariousPlaces
      .apply(Flatten.pCollections())
      .apply(WithKeys.of(null.asInstanceOf[Void]))
      .apply("write influx points",
             new InfluxSinkTransform(...)
InfluxSinkTransform
需要定时器,以便及时刷新对InfluxDB的写入

我理解这会导致改组,因为现在数据都在一个碎片下。我预计这次改组代价高昂,并希望尽可能避免

我尝试保留上一次变换中的关键点,但看起来仍然存在混洗:

  "stage_id": "S68",
  "stage_name": "F503",
  "fused_steps": [
...
    {
      "name": "s29.org.apache.beam.sdk.values.PCollection.<init>:402#b70c45c110743c2b-write-streaming-shuffle430",
      "originalTransform": "snapshot/MapElements/Map.out0",
      "userName": "snapshot/MapElements/Map.out0/FromValue/WriteStream"
    }
  ]
...
{
  "stage_id": "S74",
  "stage_name": "F509",
  "fused_steps": [
    {
      "name": "s29.org.apache.beam.sdk.values.PCollection.<init>:402#b70c45c110743c2b-read-streaming-shuffle431",
      "originalTransform": "snapshot/MapElements/Map.out0",
      "userName": "snapshot/MapElements/Map.out0/FromValue/ReadStream"
    },
    {
      "name": "s30",
      "originalTransform": "snapshot/write influx points/ParDo(Do)",
      "userName": "snapshot/write influx points/ParDo(Do)"
    }
  ]
“stage_id”:“S68”,
“阶段名称”:“F503”,
“熔合步骤”:[
...
{
“名称”:“s29.org.apache.beam.sdk.values.PCollection.:402#b70c45c110743c2b-write-streaming-shuffle430”,
“原始转换”:“快照/MapElements/Map.out0”,
“用户名”:“快照/MapElements/Map.out0/FromValue/WriteStream”
}
]
...
{
“阶段id”:“S74”,
“阶段名称”:“F509”,
“熔合步骤”:[
{
“名称”:“s29.org.apache.beam.sdk.values.PCollection.:402#b70c45c110743c2b-read-streaming-shuffle431”,
“原始转换”:“快照/MapElements/Map.out0”,
“用户名”:“快照/MapElements/Map.out0/FromValue/ReadStream”
},
{
“名称”:“s30”,
“原始转换”:“快照/写入流入点/ParDo(Do)”,
“用户名”:“快照/写入流入点/ParDo(Do)”
}
]

即使在键保持不变的情况下,也无法使用状态或计时器而不引起混乱。

InfluxSink的目标主要是通过创建批处理来减少写入调用的数量吗?Hi Reza,不确定我的InfluxSink目标是什么?相对于什么?如果我只是执行influx wr这是转换执行主管道逻辑的一个副作用,如果捆绑包要重试,那么我们将编写重复的度量。这就是为什么我让它们通过管道并在InfluxSink收集它们,然后在@FinishBundle回调中写入influx一个可能的解决方案可能是用作键,而不是
Void
一个包装元素,它遵从包装元素的编码者,因此将具有相同的编码。但这是否确保数据不会被重新洗牌?(相同的编码,但类型不同…取决于可能分配给不同碎片的实现?)Thanx我明白..您是否尝试过基于散列创建一个密钥,该散列会将工作划分为n个密钥。当然,这仍然会进行无序处理,但性能可能是可以接受的。另一种选择是不使用状态API,而只使用您在StartBundle中创建的本地列表,然后在FinishBundle中使用。请确保在StartBundle中填充列表,因为DoFn可以重用。顺便说一句,我认为仍然存在重复的可能性,例如,如果您的代码运行正常,但它们在FinishBundle代码完成之前失败…您有Guid选项吗?感谢您的建议!我已经没有使用状态API。只有计时器设置点之前的最长时间我将尝试将分区为N个键。