A Rinha de Backend é um desafio que tem como principal objetivo compartilhar conhecimento em formato de desafio!
Se você quiser saber mais sobre dá um check no github oficial
O desafio dessa rinha foi tratar de controle de concorrência com o tema créditos e débitos, basicamente é uma API que recebe requests de transações do tipo CREDITO e DÉBITO. Além desse endpoint deveriar ter um outro onde retornasse as 10 últimas transações de um cliente e seu saldo total (extrato).
Nessa implementação eu decidir sair da zona de conforto, na qual minha stack principal sempre foi usar JAVA e SPRING. Como venho estudando mais sobre Functional Programming com scala, decidir escolher utiliza-la. Meu objetivo principal não foi ganhar a rinha, mas colocar em prática assuntos que venho estudando de forma teórica, e ganhar mais experiência.
Scala
para implementação
Slick
para fazer a integração com o banco de dados que foi PostgreSQL
Javalin
(nunca tinha usando, mas já tinha lido sobre diratamente do site oficial deles) para ser o framework web.
Por eu está usando como uma linguagem de estudo sobre FP, e por ter interoperabilidade com o java, foi onde me sentir menos desconfortável para caso precise utilizar algumas bibliotecas.
Como nesse desafio precisavamos manter a consistência dos dados, com um banco de dados SQL é mais simples de implementar esse cenário, já que iria ter momentos de precisar abrir transações criando um conjunto de instruções. Então decidir utilizar o PostgreSQL por ser um banco de dados SQL e também por já ter familiaridade com o mesmo.
Bom o slick eu acabei conhecendo no decorrer da rinha, achei a documentação muito boa, e atendia no que eu preicisava.
A rinha consiste em trabalhar em uma arquitetura controlada, com requisitos minimos de CPU e Memória
Dentro do seu arquivo docker-compose.yml, você deverá limitar todos os serviços para que a soma deles não ultrapasse os seguintes limites:
deploy.resources.limits.cpu
1.5 – uma unidade e meia de CPU distribuída entre todos os seus serviçosdeploy.resources.limits.memory
550MB – 550 mega bytes de memória distribuídos entre todos os seus serviços > By Rinha Backend - 2024-q1
São abordagens diferentes para lidar com múltiplos acessos concorrentes a dados.
O Optimistic locking, antes de salvar as alterações, o sistema verifica se outros usuários modificaram os mesmos dados. Isso geralmente é feito por meio do uso de um campo de controle de versão.
Já o pessimistic locking presume-se que conflitos entre operações concorrentes são prováveis (nosso cenário). Portanto, um bloqueio é adquirido nos dados antes de qualquer modificação, garantindo que outros usuários não possam acessar ou modificar os mesmos dados simultaneamente.
Bom no cenário proposto pela rinha, seria possível utilizar esses 2 cenários, acho que dependendo, até um terceiro algo como um lock distribuido.
Mas como eu falei acima do meu objetivo que seria colocar em prática assuntos que venho estudando, e ganhar mais exp, pensando de forma rapida um pessimistic locking seria uma escolha mais assertiva, porém iriamos perder performace.
Tentei com o optimistic locking, mas como esperando, houve algumas incossistencias nos dados porém obtive um bom ganho de performace.
Então acabei optando em usar o pessimistic locking, chegando nesses números:
Submissão feita com:
nginx
como load balancerpostgres
como banco de dadosscala
para implementação da API junto com Javalin + Slick- repositório da api
@andrelucas.io @ Blog Linkedin @ Linkedin Github @ Github