Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

Era dos MAINFRAMEs

Slide 3

Slide 3 text

Cliente Funcionaria Sistema Database

Slide 4

Slide 4 text

solicita Cliente Funcionaria Sistema Database

Slide 5

Slide 5 text

request Cliente Funcionaria Sistema Database solicita

Slide 6

Slide 6 text

request response Cliente Funcionaria Sistema Database solicita

Slide 7

Slide 7 text

request response Cliente Funcionaria Sistema Database responde solicita

Slide 8

Slide 8 text

Era dos Microsserviços

Slide 9

Slide 9 text

request response Cliente Funcionaria Sistema Database responde Solicita

Slide 10

Slide 10 text

request response Sistema Database

Slide 11

Slide 11 text

request response Sistema Database

Slide 12

Slide 12 text

request response Sistema Database

Slide 13

Slide 13 text

request response Sistema Database

Slide 14

Slide 14 text

Como o aumento de acesso simultâneo afeta os negócios?

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

Surface Web Deep Web Dark Web

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

Fundamentos

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 25

Slide 25 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 26

Slide 26 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 27

Slide 27 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 28

Slide 28 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 29

Slide 29 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 30

Slide 30 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 31

Slide 31 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 32

Slide 32 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 33

Slide 33 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 34

Slide 34 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 35

Slide 35 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 36

Slide 36 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 37

Slide 37 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 38

Slide 38 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 39

Slide 39 text

E se mais de um usuário tentar reservar a mesma poltrona simultaneamente?

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

João

Slide 42

Slide 42 text

João Maria

Slide 43

Slide 43 text

João Maria select p.* from poltrona p where id = 1

Slide 44

Slide 44 text

João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 45

Slide 45 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 46

Slide 46 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara:

Slide 47

Slide 47 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João Maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara:

Slide 48

Slide 48 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João Maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: update poltrona set reservado = true, reservadoPara = ‘maria’ where id = 1

Slide 49

Slide 49 text

1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao João Maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: update poltrona set reservado = true, reservadoPara = ‘maria’ where id = 1

Slide 50

Slide 50 text

1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao João Maria Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: update poltrona set reservado = true, reservadoPara = ‘maria’ where id = 1 1 linha atualizada

Slide 51

Slide 51 text

1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao João Maria Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: update poltrona set reservado = true, reservadoPara = ‘maria’ where id = 1 1 linha atualizada

Slide 52

Slide 52 text

Race Conditions

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

Race Conditions em Microsserviços: Desmistificando um Problema Comum em Arquiteturas Distribuídas

Slide 56

Slide 56 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { //read val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //process if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; //write manager.merge(poltrona); return ok(); } }

Slide 57

Slide 57 text

Solução Ingênua

Slide 58

Slide 58 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { //read val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //process if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; //write manager.merge(poltrona); return ok(); } }

Slide 59

Slide 59 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { //read val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //process if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; //write manager.merge(poltrona); return ok(); } }

Slide 60

Slide 60 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { //read val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //process if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; //write manager.merge(poltrona); return ok(); } }

Slide 61

Slide 61 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { //read val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //process if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; //write manager.merge(poltrona); return ok(); } }

Slide 62

Slide 62 text

read

Slide 63

Slide 63 text

read

Slide 64

Slide 64 text

read process

Slide 65

Slide 65 text

read process

Slide 66

Slide 66 text

read process write ANTI-PATTERN

Slide 67

Slide 67 text

Soluções

Slide 68

Slide 68 text

No content

Slide 69

Slide 69 text

Syncronized?

Slide 70

Slide 70 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 71

Slide 71 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

Thread 1

Slide 74

Slide 74 text

Thread 1 Thread 2

Slide 75

Slide 75 text

POST /poltronas/1/reservas Thread 1 Thread 2

Slide 76

Slide 76 text

POST /poltronas/1/reservas Thread 1 Thread 2

Slide 77

Slide 77 text

POST /poltronas/1/reservas Thread 1 Thread 2 POST /poltronas/1/reservas

Slide 78

Slide 78 text

POST /poltronas/1/reservas Thread 1 Thread 2 POST /poltronas/1/reservas

Slide 79

Slide 79 text

POST /poltronas/1/reservas HTTP 200 Thread 1 Thread 2 POST /poltronas/1/reservas

Slide 80

Slide 80 text

POST /poltronas/1/reservas HTTP 200 Thread 1 Thread 2 POST /poltronas/1/reservas

Slide 81

Slide 81 text

POST /poltronas/1/reservas HTTP 200 HTTP 422, “Poltrona indisponível” Thread 1 Thread 2 POST /poltronas/1/reservas

Slide 82

Slide 82 text

No content

Slide 83

Slide 83 text

No content

Slide 84

Slide 84 text

No content

Slide 85

Slide 85 text

No content

Slide 86

Slide 86 text

Lock Distribuído?

Slide 87

Slide 87 text

No content

Slide 88

Slide 88 text

Você ou seu time domina essa tecnologia?

Slide 89

Slide 89 text

Já possui alguma destas tecnologias na sua infraestrutura?

Slide 90

Slide 90 text

No content

Slide 91

Slide 91 text

No content

Slide 92

Slide 92 text

No content

Slide 93

Slide 93 text

No content

Slide 94

Slide 94 text

No content

Slide 95

Slide 95 text

Pessimistic Locking

Slide 96

Slide 96 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //RESTANTE DO CODIGO OMITIDO } }

Slide 97

Slide 97 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //RESTANTE DO CODIGO OMITIDO } }

Slide 98

Slide 98 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") //RESTANTE DO CODIGO OMITIDO } }

Slide 99

Slide 99 text

select p.* from poltrona p where p.id = :poltronaId for update

Slide 100

Slide 100 text

select p.* from poltrona p where p.id = :poltronaId for update

Slide 101

Slide 101 text

No content

Slide 102

Slide 102 text

João

Slide 103

Slide 103 text

João Maria

Slide 104

Slide 104 text

João Maria select p.* from poltrona p where id = 1 for update

Slide 105

Slide 105 text

João Maria select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update

Slide 106

Slide 106 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João Maria select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update

Slide 107

Slide 107 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João Maria select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update

Slide 108

Slide 108 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João Maria select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update

Slide 109

Slide 109 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João Maria update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update

Slide 110

Slide 110 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: João Maria COMMIT update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update

Slide 111

Slide 111 text

1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao João Maria COMMIT update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update

Slide 112

Slide 112 text

1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao João Maria Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao COMMIT update poltrona set reservado = true, reservadoPara = ‘joao’ where id = 1 select p.* from poltrona p where id = 1 for update select p.* from poltrona p where id = 1 for update

Slide 113

Slide 113 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 114

Slide 114 text

No content

Slide 115

Slide 115 text

Se houver alto volume de requisições causando alta espera por acesso da linha?

Slide 116

Slide 116 text

É possível diminuir o tempo do lock?

Slide 117

Slide 117 text

E Se ...

Slide 118

Slide 118 text

... Trocarmos a estratégia de evitar conflitos para detectar conflitos?

Slide 119

Slide 119 text

Optimistic Locking

Slide 120

Slide 120 text

@Entity class Poltrona( @field:Column(nullable = false) val descricao: String, @field:Column(nullable = false) var reservadoPara: String, @field:Column(nullable = false) var reservado: Boolean = false @field:Version var version: Long ) { @Id @GeneratedValue var id: Long? = null; }

Slide 121

Slide 121 text

@Entity class Poltrona( @field:Column(nullable = false) val descricao: String, @field:Column(nullable = false) var reservadoPara: String, @field:Column(nullable = false) var reservado: Boolean = false, var version: Long ) { @Id @GeneratedValue var id: Long? = null; }

Slide 122

Slide 122 text

@Entity class Poltrona( @field:Column(nullable = false) val descricao: String, @field:Column(nullable = false) var reservadoPara: String, @field:Column(nullable = false) var reservado: Boolean = false, @field:Version var version: Long ) { @Id @GeneratedValue var id: Long? = null; }

Slide 123

Slide 123 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id, PESSIMISTIC_WRITE) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 124

Slide 124 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 125

Slide 125 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Syncronized @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; manager.merge(poltrona); return ok(); } }

Slide 126

Slide 126 text

update poltrona set reservado = true, reservadoPara = :user where id = :poltronaId

Slide 127

Slide 127 text

update poltrona set version = 1, reservado = true, reservadoPara = :user where id = :poltronaId and version = 0

Slide 128

Slide 128 text

No content

Slide 129

Slide 129 text

João

Slide 130

Slide 130 text

João Maria

Slide 131

Slide 131 text

João Maria select p.* from poltrona p where id = 1

Slide 132

Slide 132 text

João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 133

Slide 133 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 134

Slide 134 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 135

Slide 135 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 136

Slide 136 text

Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 137

Slide 137 text

1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 138

Slide 138 text

1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 139

Slide 139 text

1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 140

Slide 140 text

1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 141

Slide 141 text

1 linha atualizada Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: joao version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 João Maria OptimisticLockException select p.* from poltrona p where id = 1 select p.* from poltrona p where id = 1

Slide 142

Slide 142 text

No content

Slide 143

Slide 143 text

Como não estourar um erro na cara do usuário?! OptimisticLockException

Slide 144

Slide 144 text

No content

Slide 145

Slide 145 text

João

Slide 146

Slide 146 text

João

Slide 147

Slide 147 text

João POST /poltronas/1/reservas

Slide 148

Slide 148 text

João POST /poltronas/1/reservas select p.* from poltrona p where id = 1

Slide 149

Slide 149 text

João POST /poltronas/1/reservas select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0

Slide 150

Slide 150 text

João POST /poltronas/1/reservas select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0

Slide 151

Slide 151 text

João POST /poltronas/1/reservas select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria version: 1

Slide 152

Slide 152 text

João POST /poltronas/1/reservas select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0

Slide 153

Slide 153 text

João POST /poltronas/1/reservas select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 OptimisticLockException

Slide 154

Slide 154 text

João POST /poltronas/1/reservas select p.* from poltrona p where id = 1 Poltrona -------------- id: 1, descriçao: A3 reservado: false reservadoPara: version: 0 update poltrona set version = 1, reservado = true, reservadoPara = ‘maria’ where id = 1 and version = 0 Poltrona -------------- id: 1, descriçao: A3 reservado: true reservadoPara: maria version: 1 update poltrona set version = 1, reservado = true, reservadoPara = ‘joao’ where id = 1 and version = 0 OptimisticLockException HTTP 500

Slide 155

Slide 155 text

HTTP 500 É uma mensagem muito genérica

Slide 156

Slide 156 text

HTTP 409 CONFLICT

Slide 157

Slide 157 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; try { manager.merge(poltrona); }catch (ex: OptimisticLockException){ throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } return ok(); } }

Slide 158

Slide 158 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; try { manager.merge(poltrona); }catch (ex: OptimisticLockException){ throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } return ok(); } }

Slide 159

Slide 159 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; try { manager.merge(poltrona); }catch (ex: OptimisticLockException){ throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } return ok(); } }

Slide 160

Slide 160 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; try { manager.merge(poltrona); }catch (ex: OptimisticLockException){ throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } return ok(); } }

Slide 161

Slide 161 text

Existe uma forma mais elegante...

Slide 162

Slide 162 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse { val poltrona = manager.find(Poltrona::class.java, id) ?: throw HttpStatusException(NOT_FOUND, "Poltrona não existente.") if (poltrona.isReservada()) { throw HttpStatusException(UNPROCESSABLE_ENTITY, "Poltrona indisponivel") } poltrona.reservadoPara = usuario; poltrona.reservado = true; try { manager.merge(poltrona); }catch (ex: OptimisticLockException){ throw HttpStatusException(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } return ok(); } }

Slide 163

Slide 163 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {...} @Error fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> { return HttpResponse.status(CONFLICT, ex.message) } }

Slide 164

Slide 164 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {...} @Error fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> { return HttpResponse.status(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } }

Slide 165

Slide 165 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {...} @Error fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> { return HttpResponse.status(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } }

Slide 166

Slide 166 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {...} @Error fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> { return HttpResponse.status(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } }

Slide 167

Slide 167 text

@Controller("/api/v1/poltronas/{id}/reservas") class ReservaPoltronaController(val manager: EntityManager) { @Transactional @Post fun reservar(@PathVariable id: Long, @QueryValue usuario: String): HttpResponse {...} @Error fun errorHandler(request: HttpRequest<*>, ex: OptimisticLockException): HttpResponse<*> { return HttpResponse.status(CONFLICT,"Impossivel realizar a reserva, tente novamente.") } }

Slide 168

Slide 168 text

No content

Slide 169

Slide 169 text

CONCLUSÃO

Slide 170

Slide 170 text

read

Slide 171

Slide 171 text

read process

Slide 172

Slide 172 text

read process write ANTI-PATTERN

Slide 173

Slide 173 text

Race Conditions LOST UPDATE

Slide 174

Slide 174 text

@Syncronized

Slide 175

Slide 175 text

Pessimistic Locking

Slide 176

Slide 176 text

Pessimistic Locking Estratégia: Evitar Conflitos Quando utilizar: alto índice de conflitos, ambientes altamente concorrentes Vantagem: Aumento da consistência Desvantagem: Pode gerar alto nível de contenção levando a queda de produtividade das transações

Slide 177

Slide 177 text

Pessimistic Locking Estratégia: Evitar Conflitos Quando utilizar: alto índice de conflitos, ambientes altamente concorrentes Vantagem: Aumento da consistência Desvantagem: Pode gerar alto nível de contenção levando a queda de produtividade das transações

Slide 178

Slide 178 text

Pessimistic Locking Estratégia: Evitar Conflitos Quando utilizar: alto índice de conflitos, ambientes altamente concorrentes Vantagem: Aumento da consistência Desvantagem: Pode gerar alto nível de contenção levando a queda de produtividade das transações

Slide 179

Slide 179 text

Pessimistic Locking Estratégia: Evitar Conflitos Quando utilizar: alto índice de conflitos, ambientes altamente concorrentes Vantagem: Não exige mudanças no codigo Desvantagem: Pode gerar alto nível de contenção levando a queda de produtividade das transações

Slide 180

Slide 180 text

Optimistic Locking

Slide 181

Slide 181 text

Optimistic Locking Estratégia: Detectar Conflitos Quando utilizar: baixo índice de conflitos, ambientes razoavelmente concorrentes Vantagem: Menor tempo de bloqueio, menor contenção de transações Desvantagem: em ambientes concorrentes pode gerar alto custo computacional, dado ao grande numero de rollbacks em transações

Slide 182

Slide 182 text

Optimistic Locking Estratégia: Detectar Conflitos Quando utilizar: baixo índice de conflitos, ambientes razoavelmente concorrentes Vantagem: Menor tempo de bloqueio, menor contenção de transações Desvantagem: em ambientes concorrentes pode gerar alto custo computacional, dado ao grande numero de rollbacks em transações

Slide 183

Slide 183 text

Optimistic Locking Estratégia: Detectar Conflitos Quando utilizar: baixo índice de conflitos, ambientes razoavelmente concorrentes Vantagem: Menor tempo de bloqueio, menor contenção de transações Desvantagem: em ambientes concorrentes pode gerar alto custo computacional, dado ao grande numero de rollbacks em transações

Slide 184

Slide 184 text

Optimistic Locking Estratégia: Detectar Conflitos Quando utilizar: baixo índice de conflitos, ambientes razoavelmente concorrentes Vantagem: Menor tempo de bloqueio, menor contenção de transações Desvantagem: em ambientes concorrentes pode gerar alto custo computacional, dado ao grande numero de rollbacks em transações

Slide 185

Slide 185 text

Outras estratégias que os Bancos de dados oferecem para lidar com problemas de concorrência

Slide 186

Slide 186 text

Check Constraints Advisory Locks Table Locks Isolation Level

Slide 187

Slide 187 text

Check Constraints Advisory Locks Table Locks Isolation Level

Slide 188

Slide 188 text

Check Constraints Advisory Locks Table Locks Isolation Level

Slide 189

Slide 189 text

Check Constraints Advisory Locks Table Locks Isolation Level

Slide 190

Slide 190 text

Se você usa o Banco de dados ... ... apenas como repositório. VOCÊ ESTA SUB-UTILIZANDO!

Slide 191

Slide 191 text

OBRIGADO! @JORDIHOFC