Return-Path: X-Original-To: apmail-flink-user-archive@minotaur.apache.org Delivered-To: apmail-flink-user-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 8B9BB10537 for ; Thu, 27 Aug 2015 11:14:44 +0000 (UTC) Received: (qmail 30017 invoked by uid 500); 27 Aug 2015 11:14:44 -0000 Delivered-To: apmail-flink-user-archive@flink.apache.org Received: (qmail 29946 invoked by uid 500); 27 Aug 2015 11:14:44 -0000 Mailing-List: contact user-help@flink.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: user@flink.apache.org Delivered-To: mailing list user@flink.apache.org Received: (qmail 29933 invoked by uid 99); 27 Aug 2015 11:14:44 -0000 Received: from Unknown (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 27 Aug 2015 11:14:44 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id C0E091822B4 for ; Thu, 27 Aug 2015 11:14:43 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 2.881 X-Spam-Level: ** X-Spam-Status: No, score=2.881 tagged_above=-999 required=6.31 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HTML_MESSAGE=3, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, URIBL_BLOCKED=0.001] autolearn=disabled Authentication-Results: spamd3-us-west.apache.org (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com Received: from mx1-us-west.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id YbVg4_IZ1uSB for ; Thu, 27 Aug 2015 11:14:34 +0000 (UTC) Received: from mail-la0-f54.google.com (mail-la0-f54.google.com [209.85.215.54]) by mx1-us-west.apache.org (ASF Mail Server at mx1-us-west.apache.org) with ESMTPS id A23DF20752 for ; Thu, 27 Aug 2015 11:14:33 +0000 (UTC) Received: by labia3 with SMTP id ia3so10051421lab.3 for ; Thu, 27 Aug 2015 04:14:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :content-type; bh=7PP0Nd9Sbsj3rx/rRPpLCrtTnH2KCPYmwLtDYs2/rCI=; b=kR5lXbEkZULXNMd7mmgbA47VqronEncrS9hECq4K+0vK4Cc68lxhfk4Rt65W/4NlBS uzzQomCb6VIx/nnjSMetiDv0Bii+e7LaVsc/7wHlBO88S56QTHm/nG3IMIPs3M8fJdSz 393/PQRzQcjklL+0yKIB/x0qHwl6LdYiBK4obNXwDDu3sOIWyk9zpGt5zQRUS94wo/me PC0kCf3ZgjCX7JeBzcJTJHh8kAKwSzQS9ezbDQp0n2dpPmpaao9zgdMMV+rThHpl1tdr BHpc12aKyS6QfIX+K3RXB/DfGon1JO25gsl4WBqRqVHlyYJpaIOUaiV5f4I7CgCfRwkM mFXw== X-Received: by 10.152.9.37 with SMTP id w5mr1922511laa.43.1440674071865; Thu, 27 Aug 2015 04:14:31 -0700 (PDT) MIME-Version: 1.0 Received: by 10.25.80.142 with HTTP; Thu, 27 Aug 2015 04:14:12 -0700 (PDT) In-Reply-To: References: From: =?UTF-8?Q?M=C3=A1rton_Balassi?= Date: Thu, 27 Aug 2015 13:14:12 +0200 Message-ID: Subject: Re: About exactly once question? To: user@flink.apache.org Content-Type: multipart/related; boundary=089e014946f44adb67051e4912e1 --089e014946f44adb67051e4912e1 Content-Type: multipart/alternative; boundary=089e014946f44adb64051e4912e0 --089e014946f44adb64051e4912e0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Dear Zhangrucong, >From your explanation it seems that you have a good general understanding of Flink's checkpointing algorithm. Your concern is valid, by default a sink C with emits tuples to the "outside world" potentially multiple times. A neat trick to solve this issue for your user defined sinks is to use the CheckpointNotifier interface to output records only after the corresponding checkpoint has been totally processed by the system, so sinks can also provid exactly once guarantees in Flink. This would mean that your SinkFunction has to implement both the Checkpointed and the CheckpointNotifier interfaces. The idea is to mark the output tuples with the correspoding checkpoint id, so then they can be emitted in a "consistent" manner when the checkpoint is globally acknowledged by the system. You buffer your output records in a collection of your choice and whenever a snapshotState of the Checkpointed interface is invoked you mark your fresh output records with the current checkpointID. Whenever the notifyCheckpointComplete is invoked you emit records with the corresponding ID. Note that this adds latency to your processing and as you potentially need to checkpoint a lot of data in the sinks I would recommend to use a HDFS as a state backend instead of the default solution. Best, Marton On Thu, Aug 27, 2015 at 12:32 PM, Zhangrucong wrote: > Hi: > > The document said Flink can guarantee processing each tuple > exactly-once, but I can not understand how it works. > > For example, In Fig 1, C is running between snapshot n-1 and snapshot > n(snapshot n hasn=E2=80=99t been generated). After snapshot n-1, C has pr= ocessed > tuple x1, x2, x3 and already outputted to user, then C failed and it > recoveries from snapshot n-1. In my opinion, x1, x2, x3 will be processed > and outputted to user again. My question is how Flink guarantee x1,x2,x3 > are processed and outputted to user only once? > > > > > > Fig 1. > > Thanks for answing. > --089e014946f44adb64051e4912e0 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Dear Zhangrucong,

From your explana= tion it seems that you have a good general understanding of Flink's che= ckpointing algorithm. Your concern is valid, by default a sink C with emits= tuples to the "outside world" potentially multiple times. A neat= trick to solve this issue for your user defined sinks is to use the Checkp= ointNotifier interface to output records only after the corresponding check= point has been totally processed by the system, so sinks can also provid ex= actly once guarantees in Flink.

This would mean th= at your SinkFunction has to implement both the Checkpointed and the Checkpo= intNotifier interfaces. The idea is to mark the output tuples with the corr= espoding checkpoint id, so then they can be emitted in a "consistent&q= uot; manner when the checkpoint is globally acknowledged by the system. You= buffer your output records in a collection of your choice and whenever a s= napshotState of the Checkpointed interface is invoked you mark your fresh o= utput records with the current checkpointID. Whenever the notifyCheckpointC= omplete is invoked you emit records with the corresponding ID.
Note that this adds latency to your processing and as you pote= ntially need to checkpoint a lot of data in the sinks I would recommend to = use a HDFS as a state backend instead of the default solution.
Best,

Marton

On Thu, Aug 27, 2015 at 12:32 = PM, Zhangrucong <zhangrucong@huawei.com> wrote:

Hi:

=C2=A0= =C2=A0=C2=A0 =C2=A0=C2=A0The document said Flink can guarantee processing each tuple exactly-once, but I can not understand how it works.

=C2=A0=C2=A0 For example, In Fig 1, C= is running between snapshot n-1 and snapshot n(snapshot n hasn=E2=80=99t b= een generated). After snapshot n-1, C has processed tuple x1, x2, x3 and already outputted to user,=C2=A0 then C failed and it recov= eries from snapshot n-1. In my opinion, x1, x2, x3 will be processed and ou= tputted to user again. My question is how Flink guarantee x1,x2,x3 are proc= essed and outputted to user only once?

=C2=A0

=C2=A0

=

Fig 1.

Thanks for answing.


--089e014946f44adb64051e4912e0-- --089e014946f44adb67051e4912e1 Content-Type: image/png; name="image001.png" Content-Disposition: inline; filename="image001.png" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: fc4e5d687d69c29f_0.1 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 j1wezv8f1DKxpdKEBIsAAAAASUVORK5CYII= --089e014946f44adb67051e4912e1--