Ihre Messpipeline verliert Events bei Spitzenlast, und die Attributionszahlen stimmen nie mit den Bidder-Logs überein. Das sind zwei Fehler hinter einem Symptom: Events, die nie ankamen, an einer Nahtstelle, die niemand gezählt hat, und Events, die ankamen und nach einer anderen Regel gezählt wurden. Hier steht, wie Nahtstellen, Schlüssel, Late-Fenster und Abgleichsbrücke gebaut werden.
Eine Event-Pipeline, die bei Spitzenlast Events verliert und sich nie mit den Bidder-Logs abgleichen lässt, kann zwei Fehler hinter einem Symptom sein. Der eine ist Transport: Events, die erzeugt wurden und nie ankamen, an einer Nahtstelle, die niemand gezählt hat. Der andere ist definitorisch: Events, die ankamen und nach einer anderen Regel gezählt wurden als der Auktionsdatensatz.
Die übliche Erzählung - die Pipeline verliert Events, also baut man die Pipeline neu - behebt höchstens eines davon. Was folgt, trennt die beiden und sagt, was ein Abgleich liefert, und das ist keine Gleichheit. Die unten zitierten Defaults sind Kafka auf der Transportseite und ClickHouse auf der Storage-Seite.
Die kurze Antwort ist strukturell: ein Identifier pro Auktion, durchgängig mitgeführt, ein Counter auf beiden Seiten jedes Hops und ein Abgleich über ein bereits geschlossenes Fenster. Was amBrain öffentlich belegen kann, ist die AdTech-Arbeit: DSP-Entwicklung, Real-Time-Bidding-Plattformen und Ad-Exchange-Engineering. In jedem RTB-Stack ist das die Seite, von der die Bid-, Win- und Impression-Records kommen. Die Pipeline unten ist aus der Mechanik des Problems beschrieben, nicht aus einem unserer Fälle.
Der erste Fehler ist Verlust: Das Event wurde erzeugt und kam nie an, an einem bestimmten Hop, aus einem bestimmten Grund. Ein Beacon, der die Seite nie verlassen hat, eine Edge, die mitten im Deploy neu startete, ein Producer-Puffer, der voll lief, ein Consumer, der seinen Offset vor der Verarbeitung committet hat.
Der zweite ist überhaupt kein Fehler. Die Messseite zählt ein clientseitig ausgelöstes Event, der Bidder hält ein serverseitiges Auktionsergebnis fest. Das eine ist ein Zuschlag, das andere eine Beobachtung dessen, was damit geschah. Die MRC-Messrichtlinien behandeln pre-fetch, pre-render und auto-refresh als eigene Dinge, die zu erkennen und offenzulegen sind: eine Zählregel, kein Transportfehler. Die beiden auseinanderzuhalten kostet eine Query und etwas Geduld.
Solange diese Kurve nicht existiert, sind beide Seiten der Diskussion Meinungen. Danach entscheidet ihre Form, welche Hälfte dieses Artikels gilt, und die Hälften schließen sich nicht aus.
Es gibt sieben Stellen, an denen ein Ad-Event erzeugt wird und dann still aufhört zu existieren, dazu eine Einstellung, die wie eine Garantie aussieht und keine ist.
Die Regel ist eine Reporting-Regel, keine Engineering-Regel: Ein Verlust wird einer benannten Nahtstelle zugeordnet oder gar nicht. Zwei Alarme halten die leisen Nahtstellen sichtbar - Consumer Lag, in Zeit gegen die Retention gemessen, und eine Reset-Policy, die fehlschlägt, statt zu springen.
Ein Deduplizierungsschlüssel ist kein bequemer Primärschlüssel, den man am Ziel wählt. Er wird vor jedem Retry vergeben, zur Auktionszeit oder bei der Erzeugung des Events, und der Empfänger erfindet nie einen. Ankunftszeitstempel bleiben draußen: Ein Retry trägt eine neue Ankunftszeit und damit einen neuen Schlüssel.
Der Schlüssel muss über jeden Versuch hinweg identisch sein, und das entscheidet über seine Teile: die Exchange oder das Seat, der Auktions-Identifier, der Impression-Identifier und der Event-Typ. Partitionieren Sie das Topic auf diesen Schlüssel, damit Retries zusammen landen und die Reihenfolge je Schlüssel sie übersteht. Diese Anweisung gilt nur für den Transport: Dasselbe Wort auf den Columnar Store angewandt ergibt eine Partition pro Event, und der Insert stirbt am Limit pro Block. Partitionieren Sie den Storage nach Zeit und ordnen Sie nach dem Schlüssel.
Die tragfähige Form ist also at-least-once-Transport mit idempotenten Schlüsseln. Deduplizierung beim Schreiben hält die Speicherkosten im Rahmen, Deduplizierung beim Lesen macht die Zahl richtig. Merges kombinieren nie Parts aus verschiedenen Partitionen, ein Duplikat, das in der nächsten Partition landet, wird also erst aufgelöst, wenn eine Query danach fragt.
Unter Überlast hat ein System drei Optionen: den Producer bremsen, mit einem Counter abwerfen oder still verlieren. Nur die dritte ist inakzeptabel, und sie ist das Standardverhalten von Code, dem die Frage nie gestellt wurde. Verlust im Peak ist eine Queue, die wuchs, bis der Speicher ausging, oder ein Acknowledgement, das vor der Durability erteilt wurde.
Ein Drop mit einem beschrifteten Counter ist eine bekannte Größe, die sich später abgleichen lässt. Ein Drop ohne Counter ist nicht verlorene Daten, sondern eine verlorene Zahl.
Die OpenRTB-Implementierungs-Guidance sagt es direkt: Die Abfolge von der Ad Request über die Auktion bis zu Rendering und Abrechnung ist grundsätzlich nicht transaktional. Zwischen den beiden Zählwerten sitzen zu viele Parteien.
Verzögerung ist der erwartete Fall, nicht die Ausnahme. Die Bid Request kann einen Ablauf für die Impression tragen und das Gebot die Verzögerung, die der Bidder toleriert, und dieselbe Guidance gibt Faustregeln von der Größenordnung einer Minute für Web bis zu deutlich mehr für gecachte In-App-Formate und stitched Video.
Keines der beiden Felder ist ein Vertrag. Die Guidance sagt klar, dass eine Billing Notice, die später eintrifft als der vom Bidder erklärte Ablauf, trotzdem abrechenbar sein kann - eine Policy-Diskussion zwischen Bidder und Exchange und nichts, was das Protokoll vorschreibt.
Ein Event, das nach dem Fenster ankommt, ist kein Defekt der Pipeline, sondern eine Eigenschaft des Mediums. Die einzige echte Wahl ist, ob sich die Zahl öffentlich bewegt, solange das Fenster offen ist, oder danach im Verborgenen.
Die Identifier, die die Exchange in Notice- und Tracking-URLs einsetzt, sind der Auktions-Identifier aus der Bid Request, der Impression-Identifier und, wo der Bidder einen erzeugt hat, der Bid-Identifier. Keiner der drei ist für sich allein ein Schlüssel.
Die Spezifikation nennt den Auktions-Identifier exchange unique, nicht global eindeutig: Zwei Exchanges können Ihnen am selben Tag dieselbe Zeichenkette geben. Der Impression-Identifier ist nur innerhalb seiner eigenen Bid Request eindeutig, oft die wörtliche 1. Der Bid-Identifier ist optional.
Der Schlüssel, der hält, ist der zusammengesetzte: die Exchange oder das Seat, über die Sie gehandelt haben, plus der Auktions-Identifier, plus der Impression-Identifier. Erzeugen Sie ihn auf der Bidder-Seite zur Auktionszeit und behandeln Sie alles Kürzere als Präfix und nicht als Schlüssel.
Fehlen diese Makros in den Beacons, ist ein Abgleich auf Event-Ebene unmöglich, und es bleibt nur das Matching über Zeit, Placement und Creative. Was Sie stattdessen bauen können, ist eine Brücke aus sechs Zählwerten, von denen jeder den Grund benennt, warum er vom Schritt darüber abweicht.
Ein stabiles Verhältnis zwischen den Schritten ist das Ziel, eine unerklärte Bewegung ist der Alarm. Innerhalb eines Systems gehören die Hop-Verhältnisse auf eins, und jede Abweichung ist das Signal. Über die Grenze von der Auktion zur Messung hinweg ist eins der verdächtige Wert.
Dieselben Counter, als Verhältnisse gelesen, machen aus der Frage Arithmetik: akzeptiert zu gesendet, produziert zu akzeptiert, konsumiert zu produziert, eingefügt zu konsumiert. Vier Verhältnisse in einem Chart sagen, wohin die Events gegangen sind, bevor jemand ein Log öffnet. Ergänzen Sie eine producerseitige Sequenznummer je Quelle und Partition, und aus einem Loch wird ein Beleg statt eines Verdachts.
Eine Frage beantwortet die Brücke nicht, ein Vertrag schon: auf welche dieser Zahlen Sie zahlen. Der Verkäufer verbucht Umsatz auf sein eigenes abrechenbares Event, der Käufer steuert sein Pacing über seines, und die Guidance behandelt eine dauerhafte Lücke als Support-Gespräch zwischen den Parteien.
Entscheiden Sie vorab, welcher Zählwert das System of Record für Spend ist und ab welcher Abweichung aus einer Report-Notiz ein Ticket bei der Exchange wird. Die Arbeit oben erkauft Ihnen die Zuordnung von Verlusten, ehrliche Duplikate und einen Abgleich, der Zeile für Zeile erklärt ist. Sie erkauft Ihnen das Folgende nicht.
Eine Pipeline, die diese Offenlegungsfragen beantworten kann, hat eine Integritätsgeschichte. Eine, die es nicht kann, hat eine Meinung, und über Meinungen wird am Quartalsende gestritten.
Der Fehler, gegen den zu entwerfen sich lohnt, ist nicht die fehlende Stunde, die eine Untersuchung auslöst. Es ist die leise Variante: eine Nahtstelle, die ohne Counter abwirft, ein Insert, das vor seiner Durability bestätigt wurde, und ein Abgleich über ein noch offenes Fenster.
Was amBrain öffentlich belegen kann: amBrain ist ein Software-Engineering-Unternehmen aus Jerewan, Armenien, das Trading-Plattformen mit niedriger Latenz, Matching-Engines und Real-Time-Bidding-Systeme in Rust baut. amBrain baut seit 2019 Software. Der Neubau einer Messpipeline ist keine Arbeit, die hier beschrieben wird. Wenn die Zahlen auf der Bidder- und Exchange-Seite nicht mehr zusammenpassen - die Bid-, Win- und Impression-Records selbst -, dann ist das das Gespräch, das sich lohnt, und es beginnt mit der Settling-Kurve statt mit einem Neubau.
Bringen Sie Ihre aktuelle Architektur und den Fehlerfall mit, der Sie beunruhigt - wir gehen ihn in einer halben Stunde gemeinsam durch.