Estou usando uma replicação Galera e um MaxScale readwriterouter.
Estou enfrentando um problema porque o aplicativo foi desenvolvido com este fluxo:
- iniciar transação
- atualizar um registro
- comprometer-se
- leia esse registro
O resultado é que o registro é atualizado usando o servidor de gravação e a próxima leitura é feita no servidor de leitura. Ele não obtém os dados que acabaram de ser atualizados devido ao atraso de replicação.
Infelizmente, é um pouco difícil refatorar todo o aplicativo e estou procurando se existe alguma solução para forçar uma leitura no servidor de gravação para que eu possa ter certeza de obter os dados que acabaram de ser atualizados.
Edição: O
causal_reads
recurso sugerido na resposta original só funciona com replicação assíncrona do MariaDB.Replicação de Galera
Para replicação Galera, a melhor maneira de atingir causalidade de leitura é ativar
wsrep_sync_wait
. Você pode ativar isso sem modificar seu aplicativo, escrevendoSET SESSION wsrep_sync_wait=1
em um arquivo e, em seguida, usando esse arquivo econnection_init_sql_file
no listener ao qual seu aplicativo se conecta.Uma alternativa a isso seria usar o filtro Consistent Critical Read para redirecionar as leituras para o nó onde as gravações foram feitas por um curto período.
Replicação Assíncrona
Há um recurso no roteador readwritesplit especificamente para esse tipo de carga de trabalho. O modo causal_reads=local é o que você está procurando. Esse modo sincronizará suas leituras feitas com suas gravações anteriores, o que lhe dará algo como consistência Read Your Writes e fará com que o MaxScale se comporte como se você estivesse lidando com um único nó de banco de dados em vez de um cluster de servidores.
O
local
modo prefere a taxa de transferência de leitura ao custo da latência, mas você pode alterar isso para preferir a latência ao custo da taxa de transferência de leitura configurando-o comcausal_reads=fast
. Neste modo, em vez de sincronizar a leitura com a gravação, a leitura é direcionada para um servidor atualizado que replicou essas gravações. Embora normalmente neste modo as leituras feitas logo após uma gravação sejam simplesmente roteadas para o servidor original onde a gravação foi feita.Os modos
causal_reads=global
(favorece o throughput de leitura) ecausal_reads=fast_global
(favorece a latência) estendem essa ideia de uma sessão para uma instância MaxScale. Nesses modos, em vez de olhar para as gravações de uma sessão, todas as gravações feitas por meio de uma única instância readwritesplit são visíveis para leituras de outras sessões feitas pela mesma instância readwritesplit. Esse modo dá as mesmas garantias que olocal
modo dá, mas ao custo de mais sincronização para leituras e gravações potencialmente não relacionadas.Há também os modos
causal_reads=universal
ecausal_reads=fast_universal
que estendem a ideia de uma instância MaxScale para qualquer número de instâncias MaxScale. Esses modos também têm o recurso de garantir visibilidade de gravações feitas fora de qualquer instância MaxScale (por exemplo, a carga de dados que é feita localmente é visível para leituras feitas por meio do MaxScale). Como de costume, esse tipo de "causalidade universal" tem um alto custo de latência e throughput e geralmente deve ser o último recurso.