Base teórica de transação distribuída

Hoje, neste blog, vamos aprender sobre um dos aspectos principais e difíceis dos microsserviços: as transações distribuídas.

Aprenderemos com base na estrutura Seata.

1. Problema de transação distribuída

Deveríamos ter uma melhor compreensão das transações. Sabemos que todas as transações devem atender aos princípios ACID. Aquilo é

imagem-20230328192513554

Na arquitetura monolítica que estudamos anteriormente, esse serviço acessa diretamente um banco de dados e o negócio é relativamente simples. Com base nas características do próprio banco de dados, o ACID já pode ser realizado.

No entanto, o que veremos agora são microsserviços. O negócio de microsserviços costuma ser mais complicado: talvez um negócio abranja vários serviços e cada serviço tenha seu próprio banco de dados.

Neste momento, se você confiar nas características do próprio banco de dados, ainda consegue garantir o ACID de todo o negócio? Este não é necessariamente o caso.

Vejamos um exemplo.

imagem-20230328192752165

Por exemplo, tenho aqui um microsserviço que contém três serviços, incluindo pedidos, contas e estoque.

Agora temos um negócio onde o usuário faz um pedido.Quando o usuário faz um pedido, quero que o serviço de pedidos crie o pedido e o grave no banco de dados.

Em seguida, ele chama o serviço de conta e o serviço de estoque, o serviço de conta deduz o saldo do usuário e o serviço de estoque deduz o estoque do produto.

Então você pode ver que este negócio contém chamadas para três microsserviços diferentes, e cada microsserviço tem seu próprio banco de dados independente, que é uma transação independente.

Então, o que esperamos é que, uma vez executado o meu pedido, todos os pedidos serão bem-sucedidos? Claro, se você falhar, todos falharão?

1.1 Demonstrar problemas de transação distribuída

O resultado é esse resultado, mas será que tal efeito pode ser alcançado? Vamos verificar isso.

A estrutura do microsserviço é a seguinte:

imagem-20230328194429179

em:

seata-demo: projeto pai, responsável por gerenciar as dependências do projeto

  • account-service: Serviço de contas, responsável pela gestão das contas de capital dos usuários. Fornece uma interface para dedução de saldos
  • storage-service: Serviço de estoque, responsável por gerenciar o estoque de produtos. Fornece uma interface para dedução de estoque
  • order-service: Serviço de pedidos, responsável pelo gerenciamento de pedidos. Ao criar um pedido, o serviço de conta e o serviço de armazenamento precisam ser chamados

Vamos dar uma olhada neste pedido (serviço de pedido) primeiro. Dê uma olhada na lógica de negócio dentro dele, no controlador podemos ver uma interface para criação de pedidos.

imagem-20230328195453369

No controlador ele ajusta o serviço, então entramos no método de serviço.

imagem-20230328203507452

Neste método de serviço, podemos ver que ele primeiro cria um pedido e grava os dados do pedido diretamente no banco de dados.

Depois de criar o pedido, chame accountClient (para deduzir o saldo do usuário) e storageClient (para deduzir o estoque) para concluir o saldo e a dedução do estoque.

accountClient e storageClient são chamados por meio do Feign.

imagem-20230328200505074

Estes são os dados dessas três tabelas.

Esta é a lógica de negócios. Vamos usar o Postman para testá-la.

imagem-20230328202949554

Enviamos uma solicitação.

imagem-20230328204822270

500 foi retornado, vamos dar uma olhada no banco de dados.

imagem-20230328204905021

Verificou-se que o saldo do usuário foi reduzido em 200.

imagem-20230328204924437

O pedido não foi criado

imagem-20230328204940524

Os estoques também não estão diminuindo.

O status da transação é consistente neste momento? Não é?

Então por que é assim?

No negócio anterior, nosso serviço de pedidos criou um pedido.

Em seguida, ligue para o serviço de contabilidade e serviço de estoque para concluir a dedução do saldo e a dedução do estoque.

Entre eles, os serviços de encomenda e contabilidade foram todos executados com sucesso.

imagem-20230328205156568

Porém, quando o serviço de inventário foi executado, foi relatado um erro devido a inventário insuficiente.

imagem-20230328205213745

Em teoria, se um erro for relatado aqui, todos os anteriores deveriam ser revertidos? Mas o resultado que vemos é que o serviço de inventário falhou.O saldo da conta deve ser deduzido ou deduzido? por que?

Primeiro, cada um dos nossos serviços é independente.

Então agora você lança uma exceção no serviço de inventário.

Ele sabe sobre serviços de conta? Não sabe!

Então eu nem sei que você lançou uma exceção, então o que devo reverter?

Em segundo lugar, cada serviço é independente, pelo que os seus assuntos também são independentes.

Então agora meu serviço de pedidos e atendimento de conta, depois que eu terminar o negócio, meu negócio acabou, devo enviar diretamente?

Agora você me pede para reverter, como faço para reverter? Eu fiz tudo, enviei e não pode ser desfeito.

Então, no final das contas, não há consenso sobre o estado da transação, então neste momento surge o problema das transações distribuídas!

1.2 O que é transação distribuída

Então, vamos resumir o que são transações distribuídas.

Um negócio em sistema distribuído, que abrange vários serviços e fontes de dados. Cada serviço pode ser considerado como uma transação de agência, e o que queremos garantir é que o status final de todas as transações de agência seja consistente.

Ou todos conseguem ou todos falham. Então tal transação é uma transação distribuída.

Então, por que existem problemas com transações distribuídas?

Isto porque os vários serviços, ou as transacções dos vários ramos, não têm conhecimento uns dos outros.Se cada um submeter os seus próprios assuntos, não poderão reverter no futuro, resultando num estado inconsistente.

2. Base teórica

A seguir entraremos no estudo da base teórica das transações distribuídas.

Resolver problemas de transações distribuídas requer algum conhecimento básico de sistemas distribuídos como orientação teórica.

2.1 Teorema CAP

O teorema CAP foi proposto por Eric Brewer, cientista da computação da Universidade da Califórnia, em 1998. Ele diz que geralmente existem três indicadores em sistemas distribuídos.

Eles são:

  • Consistência
  • Disponibilidade
  • Tolerância de partição

O que Eric disse é que é impossível para um sistema distribuído atender a esses três indicadores ao mesmo tempo.

Se você olhar para esses três círculos, não distinguirá apenas três características?

imagem-20230328211612211

Mas veja, esses três círculos não se sobreporão a três ao mesmo tempo. No máximo, eles se sobreporão em dois.

Então esta conclusão é chamada de teorema CAP. Então, por que tal situação ocorre?

Devemos primeiro entender o que a consistência, a disponibilidade e a tolerância à partição representam antes de podermos entender o significado.

2.1.1.Consistência

Então, vamos dar uma olhada no primeiro deles, consistência.

Consistência significa que os dados obtidos pelos usuários ao acessar qualquer nó do sistema distribuído devem ser consistentes. Digamos que eu tenha dois nós agora.

imagem-20230328212029032

Há um dado no primeiro nó chamado dados cujo valor é v0, e o mesmo acontece no segundo nó. Então, o que eles realmente formam? Senhor de escravos.

Agora, quando um usuário acessar esses dois nós, o resultado será o mesmo, não importa quem seja acessado?

imagem-20230328212247822

Mas, agora se eu modificar os dados do nó 1 nó.

imagem-20230328212305352

Os dados dos dois nós são diferentes neste momento?

Então, o que você faz para alcançar consistência?

Você precisa sincronizar os dados do nó 01 para o nó 02?

imagem-20230328212322284

Depois que a sincronização de dados entre os dois for concluída, os dados estarão consistentes novamente? Então, como um sistema distribuído.

Ao fazer backup de dados, você deve concluir a sincronização de dados em tempo hábil para garantir consistência.

2.1.2. Disponibilidade

O segundo conceito é a disponibilidade.

Ele diz que quando os usuários acessam qualquer nó íntegro no cluster, eles devem obter uma resposta em vez de tempo limite ou rejeição.

Por exemplo, atualmente tenho três nós neste cluster.

imagem-20230328212442424

Em circunstâncias normais, não há problema para os usuários acessarem nenhum deles.

imagem-20230328212504702

Agora, esses três nós não sofreram tempo de inatividade. Mas não sei porque, por exemplo, este node3, sua solicitação será bloqueada ou rejeitada.

imagem-20230328212521372

Então, todas as solicitações recebidas não estarão acessíveis. Neste momento, o node3 não estará disponível. Portanto, disponibilidade refere-se a se este nó pode ser acessado normalmente.

2.1.3 Tolerância a falhas de partição

O terceiro conceito: tolerância a falhas de partição.

O particionamento refere-se ao fato de alguns nós do sistema distribuído perderem conexões com outros nós devido a falhas de rede ou outros motivos, formando partições independentes.

Por exemplo, esses três nós ainda são o nó 123.

imagem-20230328213428467

Então o usuário pode acessar qualquer um deles.

Mas devido a uma falha na rede, a máquina não travou e o nó 3 foi desconectado do nó 1 e do nó 2.

imagem-20230328213509738

O nó 1 e o nó 2 podem acessar um ao outro normalmente, mas o nó 3 não. Portanto, todo o cluster será dividido em duas áreas neste momento.

Então node1 e node2 estão na mesma área, e o próprio node3 é uma partição.

Neste momento, se um usuário gravar novos dados no nó 02.

imagem-20230328213621216

Então o nó 02 pode sincronizar os dados com o nó 01.

imagem-20230328213631968

Mas há sincronização no nó 3?

Obviamente que não, porque eles não conseguem sentir isso, então como podem sincronizá-lo?

Então os dados das duas partições serão inconsistentes.

Então, o que significa tolerância a falhas de partição?

Tolerância a falhas significa que, independentemente de haver partições no cluster, todo o sistema deve continuar a fornecer serviços ao mundo exterior.

2.1.4.Contradição

Ou seja, mesmo que seu local esteja particionado, os usuários ainda precisam acessá-lo quando deveriam?

Mas se eu visitar o node1 agora, o resultado que obterei será o mesmo obtido ao acessar o node3? não é o mesmo.

Portanto, ocorre inconsistência de dados e a consistência não é atendida. Então, se devo satisfazer a consistência.

O que devo fazer? Então, posso fazer isso?

Solicitei ao nó 3 que aguardasse a recuperação da rede do nó 2 e a sincronização dos dados.

antes da recuperação. Todas as solicitações de acesso estão bloqueadas aqui, avisando para aguardar, meus dados ainda não estão prontos.

É possível?

Se eu fizer isso, poderei satisfazer a consistência dos dados? Mas seu node3 é obviamente um nó íntegro, mas como resultado, todas as solicitações recebidas ficam presas aqui, impedindo que outros o acessem.

Então o node3 não ficaria indisponível? Portanto, não satisfaz a usabilidade.

Então agora você descobrirá que quando a rede é particionada, não há como satisfazer a disponibilidade e a consistência ao mesmo tempo? No entanto, esta partição é inevitável.

Por que você diz isso?

Contanto que você seja um sistema distribuído, seus nós estarão necessariamente conectados através da rede? E enquanto você estiver conectado pela rede, você tem como garantir que a rede esteja 100% sempre íntegra?

Isso é impossível, certo?

Portanto, podemos pensar que todas as partições distribuídas do sistema aparecerão definitivamente, já que as partições aparecerão definitivamente.

E todo o seu cluster deve fornecer serviços para o mundo exterior, por isso é considerado.

A tolerância à partição deve ser alcançada, então, neste momento, você precisa escolher entre Consistência e Disponibilidade? Você tem consistência ou disponibilidade. Não há como ficar satisfeito ao mesmo tempo,

Esta é uma das razões para o teorema CAP.

2.2 Teoria BASE

Já estudamos o teorema do CAP. Sabemos que em um sistema distribuído, porque o particionamento é inevitável, é necessário fazer uma escolha entre consistência e disponibilidade. No entanto, essas duas características são realmente muito importantes. Não quero desistir de qualquer um deles, então o que devo fazer?

Bem, então a teoria BASE pode simplesmente resolver este problema.

A teoria BASE é uma solução para o CAP. Na verdade, inclui principalmente três ideias:

  • Basicamente Disponível (basicamente disponível) : Quando um sistema distribuído falha, é permitido perder parte de sua disponibilidade, ou seja, garantir que o núcleo esteja disponível.
  • **Soft State (soft state): **Em um determinado período de tempo, um estado intermediário é permitido, como um estado inconsistente temporário.
  • Eventualmente consistente : embora a consistência forte não possa ser garantida, a consistência dos dados será eventualmente alcançada após o término do estado suave.

Na verdade, a teoria BASE é uma forma de reconciliar e escolher a contradição entre Consistência e Disponibilidade no CAP.

No CAP, se você quiser alcançar consistência, você tem que sacrificar a disponibilidade. Mas no BASE, se conseguirmos uma consistência forte, você tem que sacrificar a disponibilidade, mas não é indisponibilidade, mas sim um sacrifício ou perda temporária de disponibilidade parcial. disponível.

2.3. Ideias para resolver transações distribuídas

Tendo dito tantas ideias, isso pode resolver nosso problema de transação distribuída?

Na verdade, é possível. Então, quais problemas surgem em nossas transações distribuídas?

As transações distribuídas geralmente contêm n subtransações, cada uma delas executada e enviada de forma independente. Como resultado, alguns tiveram sucesso e outros falharam.Neste momento, o status de todos era inconsistente.

O que esperamos é que cada subtransação nesta transação distribuída tenha o mesmo status final, ou todas tenham sucesso ou todas falhem.

Então, como resolvemos essa transação distribuída com base na teoria de base?

A primeira solução é, na verdade, o modelo baseado em AP.

Modo AP: Cada subtransação é executada e enviada separadamente, permitindo resultados inconsistentes e, em seguida, tomando medidas corretivas para restaurar os dados para alcançar a consistência final.

Isso significa atender à disponibilidade e sacrificar um certo grau de consistência. Por exemplo, se cada uma de nossas subtransações for executada e enviada separadamente quando a executarmos no futuro, algumas serão bem-sucedidas e outras falharão. Então, como se chama isso?

Isso é chamado de inconsistência de status.

Em outras palavras, no que você está?

Estado suave.

Estado inconsistente temporário, ok, por quê? Após a conclusão da execução, cada uma de nossas subtransações pode respirar.

Dê uma olhada um no outro, você conseguiu? Ah, eu consegui. Hum, você conseguiu? Ei, o que devo fazer se alguém falhar nessa comparação?

Não fique ansioso neste momento. Tomaremos medidas compensatórias para restaurar os dados. Alguns dizem que eles foram enviados e não podem ser restaurados. Então podemos fazer a operação inversa. Por exemplo, você adicionou um novo par antes. errado?

Então, se eu excluí-lo em seguida, não será o fim de tudo?

Isso não restaura os dados ao seu estado original? Isso não alcança consistência eventual?

Então esse modelo é na verdade uma ideia de AP.

E vice-versa, posso chegar a um consenso forte? Ei, isso também é possível.

Modo CP: Cada subtransação espera uma pela outra após a execução, confirma ao mesmo tempo e reverte ao mesmo tempo para chegar a um consenso forte. No entanto, durante o processo de espera da transação, ela fica em um estado de disponibilidade fraca.

Anteriormente, cada subtransação era executada e enviada separadamente. Se você terminar de executar todas no início, não será possível reverter, certo?

Mas agora, depois que cada uma das minhas subtransações foi executada, não as envie, apenas esperem um pelo outro. Vamos dar uma olhada um no outro. Ei, terminei de executá-la. Você terminou de executá-la? Assim ficará tudo bem até que tenhamos executado tudo.

Então submetemos ao mesmo tempo ou alguém falha no meio, então revertemos ao mesmo tempo, então podemos chegar a um consenso forte? Não existe estado intermediário, certo?

Mas neste processo, as suas várias subtransações precisam esperar umas pelas outras? Aguardando a execução um do outro, portanto, durante esse processo, seu serviço estará em um estado de disponibilidade fraca.

Porque você bloqueará o recurso, tornando-o inacessível.

Você acha que alcançamos uma solução para transações distribuídas baseada na teoria da base?

Posteriormente resolveremos transações distribuídas com base nesta ideia, mas seja você CP ou AP, há uma coisa em comum aqui, ou seja, cada subtransação terá que se comunicar entre si no futuro para identificar o status de execução de a outra festa.

Então, como se comunicar entre várias subtransações?

Portanto, é necessário um coordenador para ajudar cada subtransação na transação distribuída a se comunicar e perceber. O status da outra parte ou de cada um, vamos dar um exemplo, vamos tomar como exemplo nosso pedido anterior.

imagem-20230329192722139

O usuário faz um pedido e liga para o serviço de pedidos e, em seguida, liga para o serviço de contabilidade e o serviço de estoque. E esse lugar? Precisamos de um coordenador de transações e cada microsserviço mantém uma conexão com o coordenador de transações.

imagem-20230329192830032

Depois que o negócio chega, cada um executa individualmente. Se você quiser ser forte e consistente agora, não o envie quando o terceiro serviço for executado. Execute o serviço de dedução de pedido, execute o serviço de dedução de estoque e execute o inventário.

Mas após a execução, descobriu-se que o inventário falhou.

imagem-20230329192952905

Como você sabe? Querem informar o coordenador dos resultados da sua execução? Em seguida, o coordenador vê que alguém falhou e notifica-o para fazer essa reversão no futuro.

Então, todos serão capazes de ser consistentes? Portanto, o coordenador desta transação desempenha um papel muito importante: durante todo o processo, participamos das transações de cada subsistema na transação distribuída, que chamamos de transações de filial.

Toda a transação da filial é chamada de transação global, portanto, o coordenador da transação está aqui para coordenar o status de cada transação da filial para que eles possam chegar a um acordo.

Acho que você gosta

Origin blog.csdn.net/weixin_53041251/article/details/132419933
Recomendado
Clasificación