@inponomarev
Иван Пономарёв, КУРС/МФТИ
![]() | Лекция 1.
Лекция 2.
| ![]() |
Местонахождение пользователя

Количество посещенных мест

Производная и интеграл
Martin Kleppmann, “Designing Data Intensive Applications”

KTable<String, Long> totals = input.groupByKey().aggregate(
() -> 0L,
(k, v, a) -> a + Math.round(v.getAmount() * v.getOdds()),
Materialized.with(Serdes.String(), Serdes.Long())
);
$kafka-topics --zookeeper localhost --describe
Topic:
table2-demo-KSTREAM-AGGREGATE-STATE-STORE-0000000001-changelog
PartitionCount:10
ReplicationFactor:1
Configs:cleanup.policy=compactKStream<String, Score> scores =
eventScores.flatMap((k, v) ->
Stream.of(Outcome.H, Outcome.A).map(o ->
KeyValue.pair(String.format("%s:%s", k, o), v))
.collect(Collectors.toList()))
.mapValues(EventScore::getScore);
KTable<String, Score> tableScores =
scores.groupByKey(Grouped.with(...).reduce((a, b) -> b);
$kafka-topics --zookeeper localhost --list
table2-demo-KSTREAM-REDUCE-STATE-STORE-0000000006-repartition
table2-demo-KSTREAM-REDUCE-STATE-STORE-0000000006-changelogKTable<String, String> joined =
totals.join(tableScores,
(total, eventScore) ->
String.format("(%s)\t%d", eventScore, total));Join работает

Join не работает (Runtime Exception)

Join не работает молча!

Реплицируется всюду целиком
GlobalKTable<...> global = streamsBuilder.globalTable("global", ...);

ForeignKeyExtractor

![]() | Лекция 1.
Лекция 2.
| ![]() |
WindowKeySchema.java
static Bytes toStoreKeyBinary(byte[] serializedKey,
long timestamp,
int seqnum) {
ByteBuffer buf = ByteBuffer.allocate(
serializedKey.length
+ TIMESTAMP_SIZE
+ SEQNUM_SIZE);
buf.put(serializedKey);
buf.putLong(timestamp);
buf.putInt(seqnum);
return Bytes.wrap(buf.array());
}
«Послегольщик» — игрок, пытающийся протолкнуть правильную ставку в момент смены счёта в матче
Штамп времени ставки и события смены счёта должны «почти совпадать».

KStream<String, Bet> bets = streamsBuilder.stream(BET_TOPIC,
Consumed.with(
Serdes...)
.withTimestampExtractor(
(record, previousTimestamp) ->
((Bet) record.value()).getTimestamp()
));
(Ещё время можно извлечь из WallClock и RecordMetadata.)
По событию смены счёта понимаем, какая ставка будет «правильной»:
Score current = Optional.ofNullable(stateStore.get(key))
.orElse(new Score());
stateStore.put(key, value.getScore());
Outcome currenOutcome =
value.getScore().getHome() > current.getHome()
?
Outcome.H : Outcome.A;KStream<String, String> join = bets.join(outcomes,
(bet, sureBet) ->
String.format("%s %dms before goal",
bet.getBettor(),
sureBet.getTimestamp() - bet.getTimestamp()),
JoinWindows.of(Duration.ofSeconds(1)).before(Duration.ZERO),
StreamJoined.with(Serdes....
));TimeWindowedKStream<..., ...> windowed =
stream.groupByKey()
.windowedBy(TimeWindows.of(Duration.ofSeconds(20)));

TimeWindowedKStream<..., ...> windowed =
stream.groupByKey()
.windowedBy(TimeWindows.of(Duration.ofSeconds(20)));
KTable<Windowed<...>, Long> count = windowed.count();
/*
* Windowed<K> interface:
* - K key()
* - Window window()
* -- Instant startTime()
* -- Instant endTime()
*/TimeWindowedKStream<..., ...> windowed =
stream.groupByKey()
.windowedBy(TimeWindows.of(Duration.ofSeconds(20))
.advanceBy(Duration.ofSeconds(10)));

SessionWindowedKStream<..., ...> windowed =
stream.groupByKey()
.windowedBy(SessionWindows.with(Duration.ofMinutes(5)));


![]() | |
![]() | Лекция 1.
Лекция 2.
| ![]() |
Пора закругляться!
![]() |
|
![]() |
|
Телеграм: Грефневая Кафка
Kafka Summit Conference
Kafka StreamsAPI — это удобная абстракция над «сырой» Кафкой
Чтобы начать пользоваться, надо настроить мышление под потоковую обработку
Технология переживает бурное развитие
+ живой community, есть шанс повлиять на процесс самому
- публичные интерфейсы изменяются очень быстро
Спасибо!