Slide 1

Slide 1 text

/ by Igor Lozynskyi Deep Dive into Reactive Relational Database Access

Slide 2

Slide 2 text

For whom this talk: / Want to build reactive apps? / Like to work with databases? / Want to learn about R2DBC? / I assume, you know what Reactive is

Slide 3

Slide 3 text

Реактивный Хардкор / Oleh Dokuka 3 3 Igor Lozynskyi

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Agenda / Why reactive database access? / Look at R2DBC components / Build R2DBC driver

Slide 6

Slide 6 text

Part 1: Why Reactive DB access?

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

Why Reactive? / New frontier for high-efficiency apps / Fundamentally non-blocking / Paired with asynchronous behaviors / Complex stream processing / Reactive Streams Standard / Pull-push back pressure

Slide 9

Slide 9 text

MySQL DB MySQL Driver in ZD service data

Slide 10

Slide 10 text

MySQL DB MySQL Driver in ZD service

Slide 11

Slide 11 text

Why Reactive? / New frontier for high-efficiency apps / Fundamentally non-blocking / Paired with asynchronous behaviors / Complex stream processing / Reactive Streams Standard / Pull-push back pressure

Slide 12

Slide 12 text

technology radar vol. 20 by ThoughtWorks

Slide 13

Slide 13 text

Reactive Programming does NOT like blocking threads

Slide 14

Slide 14 text

Spring (5.0+) is reactive now

Slide 15

Slide 15 text

Spring WebClient Netty Cloud Messaging WebFlux …

Slide 16

Slide 16 text

Reactive Spring Data MongoDB Cassandra Couchbase Redis Neo4j* *1.0.0-beta01

Slide 17

Slide 17 text

What about SQL?

Slide 18

Slide 18 text

ADBA R2DBC vs by Oracle by Pivotal

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

ADBA / Async API for relational data access in Java / Implemented with CompletableFuture / Uses Java 9’s Flow API

Slide 21

Slide 21 text

Criticism / Does not imply back pressure / Has only ADBA-over-JDBC implementation / Slow development / Authors have neglected Reactive approach for a long time / Tiny interest in async-only API

Slide 22

Slide 22 text

ADBA https://www.oracle.com/technetwork/database/application-development/jdbc/ documentation/adba-devnexus-5391648.pdf

Slide 23

Slide 23 text

implications…

Slide 24

Slide 24 text

Part 2: R2DBC

Slide 25

Slide 25 text

R2DBC https://r2dbc.io

Slide 26

Slide 26 text

R2DBC Design principles / Based on Reactive Streams Types and Patterns / Completely non-blocking, up to the DB / Utilize wire-protocol for non-blocking implementations / Divide Client API and Driver SPI / Shrink Driver SPI

Slide 27

Slide 27 text

image credits: Pivotal

Slide 28

Slide 28 text

image credits: Pivotal

Slide 29

Slide 29 text

JDBC API vs R2DBC SPI / JDBC has the same API for: / Driver authors / Human users / Inhuman users like JPA, Jdbi, jOOQ, etc. / No-one likes using JDBC API / Many methods, most useless / Too low-level for human users / Too verbose for driver implementors

Slide 30

Slide 30 text

R2DBC SPI / ConnectionFactory / Connection / Statement / Result / RowMetadata / Row

Slide 31

Slide 31 text

R2DBC SPI - Connection / Batch createBatch() / Statement createStatement(String sql) / Publisher beginTransaction() / Publisher commitTransaction() / Publisher rollbackTransaction() / Publisher rollbackTransactionToSavepoint(String name) / Publisher setTransactionIsolationLevel(IsolationLevel level) / Publisher createSavepoint(String name) / Publisher releaseSavepoint(String name) / Publisher close()

Slide 32

Slide 32 text

R2DBC SPI - Statement / Statement add() / Statement bind(Object identifier, Object value) / Statement bindNull(Object identifier, Class type) / Publisher execute() / Statement returnGeneratedValues(String... columns)

Slide 33

Slide 33 text

R2DBC SPI - Result / Publisher getRowsUpdated() / Publisher map(BiFunction f)

Slide 34

Slide 34 text

R2DBC SPI - Row / T get(Object identifier, Class type)

Slide 35

Slide 35 text

SPI: Connection factory H2ConnectionConfiguration conf = H2ConnectionConfiguration.builder() .url("mem:db;DB_CLOSE_DELAY=-1;TRACE_LEVEL_FILE=4") .build(); ConnectionFactory connectionFactory = new H2ConnectionFactory(conf);

Slide 36

Slide 36 text

SPI: Simple select connectionFactory .create() .flatMapMany(conn -> conn.createStatement("SELECT currency, price FROM trades") .execute() .flatMap(result -> result .map((row, metadata) -> row.get("currency"))))

Slide 37

Slide 37 text

SPI: Batch insert connectionFactory .create() .flatMapMany(conn -> conn.createStatement( “INSERT INTO trades (currency, market, price) “ + "VALUES (?, ?, ?)") .bind(0, "EUR").bind(1, "TD").bind(2, 7.0).add() .bind(0, "UAH").bind(1, "TX").bind(2, 6.0).add() .execute())

Slide 38

Slide 38 text

SPI: Transactions connectionFactory .create() .flatMapMany(conn -> conn.beginTransaction() .thenMany(conn.createStatement( "INSERT INTO trades (currency, market, price) " + "VALUES (?, ?, ?)") .bind(0, "UAH").bind(1, "TX").bind(2, "B") .execute()) .delayUntil(p -> conn.commitTransaction()) .onErrorResume(t -> conn .rollbackTransaction() .then(Mono.error(t)))) try-with-resources

Slide 39

Slide 39 text

image credits: Pivotal

Slide 40

Slide 40 text

R2DBC Client R2dbc r2dbcClient = new R2dbc(connectionFactory);

Slide 41

Slide 41 text

R2DBC Client r2dbcClient .withHandle(handle -> handle.createUpdate( "INSERT INTO trades (currency, market, price) " + "VALUES ($1, $2, $3)") .bind("$1", "UAH").bind("$2", "TX").bind("$3", 3.4) .execute())

Slide 42

Slide 42 text

R2DBC Client: Transactions r2dbcClient .inTransaction(handle -> handle.createUpdate( "INSERT INTO trades (currency, market, price) " + "VALUES ($1, $2, $3)") .bind("$1", "UAH").bind("$2", "TX").bind("$3", 3.4) .execute())

Slide 43

Slide 43 text

Spring Data Repository public interface UsSalesR2dbcRepository extends R2dbcRepository { @Query("select * from us_sales_by_districts") Flux findAll(); @Query("select * from us_sales_by_districts, where code=:code") Mono findById(@Param("code") String code); }

Slide 44

Slide 44 text

image credits: Pivotal

Slide 45

Slide 45 text

Drivers: supported databases

Slide 46

Slide 46 text

2018 StackOverflow survey Reactive Spring Data R2DBC

Slide 47

Slide 47 text

How R2DBC drivers work?

Slide 48

Slide 48 text

r2dbc-postgres PostgreSQL wire-protocol TCP

Slide 49

Slide 49 text

r2dbc-postgres PostgreSQL

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

Where is back pressure?

Slide 52

Slide 52 text

Portal - Pg protocol feature handles back pressure

Slide 53

Slide 53 text

Using R2DBC with Spring Data

Slide 54

Slide 54 text

public interface UsSalesR2dbcRepository extends R2dbcRepository { @Query("select * from us_sales_by_districts") Flux findAll(); @Query("select * from us_sales_by_districts, where code=:code") Mono findById(@Param("code") String code); } Spring Data R2DBC

Slide 55

Slide 55 text

Spring Data Repository & Transactions? @Transactional

Slide 56

Slide 56 text

Spring Data Repository & Transactions? @Component class TransactionalService { private CustomerRepository repository; @Transactional public Mono save(Customer customer) { return repository.save(customer).map(it -> { if (it.firstname.equals("Dave")) { throw new IllegalStateException(); } else { return it; } }); } }

Slide 57

Slide 57 text

Downsides of R2DBC

Slide 58

Slide 58 text

JPA? / No Hibernate / No EclipseLink / No JPA so far? / No JPA at all?

Slide 59

Slide 59 text

Longer Queries / DBs rushing to deliver data / Back pressure may delay data delivery

Slide 60

Slide 60 text

Longer Transactions / Back pressure may cause more contention / JDBC may be faster than R2DBC / R2DBC may impact DB internals

Slide 61

Slide 61 text

Wire-protocol / Should allow data streaming / Should allow back pressure / Cancellation / Implement Reactive Streams semantics / Multiplexing? / RSocket?

Slide 62

Slide 62 text

Fun Part: Demo

Slide 63

Slide 63 text

App (WebFlux) PostgreSQL TCP Reactive Spring Data R2DBC Driver

Slide 64

Slide 64 text

Dirty Part: Writing code!

Slide 65

Slide 65 text

PrestoDB R2DBC Driver

Slide 66

Slide 66 text

source: https://stackshare.io/presto

Slide 67

Slide 67 text

PrestoDB vs PrestoSQL

Slide 68

Slide 68 text

source: http://starburstdata.com

Slide 69

Slide 69 text

source: http://starburstdata.com HTTP

Slide 70

Slide 70 text

image credits: Pivotal PrestoDB

Slide 71

Slide 71 text

r2dbc-presto Presto wire-protocol HTTP SQL

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

Get hands dirty!

Slide 74

Slide 74 text

r2dbc-presto

Slide 75

Slide 75 text

Last Part: Moral

Slide 76

Slide 76 text

R2DBC Pros / New and shiny / Brings reactive to DB access / Active community, many connectors / Easy to implement drivers

Slide 77

Slide 77 text

R2DBC Cons / Still not GA (current: 0.8 RC1) / No JPA (Hibernate/EclipseLink) / Reactive approach may not fit SQL at all / Reactive programming is under a thread

Slide 78

Slide 78 text

Fibers & Coroutines strike back

Slide 79

Slide 79 text

Fibers/Coroutines Cons / Light-weight threads / Write blocking, synchronous code / Use JDBC/JPA / Don’t use FP, write imperative code / C#, JS has async/await / Go, Kotlin has green threads

Slide 80

Slide 80 text

Why Reactive? vs Fibers/Coroutines / New frontier for high-efficiency apps / Fundamentally non-blocking / Paired with asynchronous behaviors / Complex stream processing / Pull-push back pressure / Reactive Streams Standard Kotlin Coroutine’s Flow Java / JS / C++ / C# … May be simulated with channels

Slide 81

Slide 81 text

Summary / R2DBC won the battle against ADBA / Will have reactive DB access, soon / Spring Data drives R2DBC / Not for production yet? But soon! / It is time to try R2DBC! / Reactive vs Fibers: friends or foes?

Slide 82

Slide 82 text

Takeaways / Web on Reactive Stack (Spring Framework) / www.r2dbc.io

Slide 83

Slide 83 text

Q&A Thank you! /aigor /siromaha /ihor.lozinsky