mongodb, replica e erro: {“$ err”: “not master and slaveOk = false”, “code”: 13435}

174

Tentei conjuntos de réplicas mongo pela primeira vez.

Estou usando o ubuntu no ec2 e inicializei três instâncias. Eu usei o endereço IP privado de cada uma das instâncias. Eu escolhi como o principal e abaixo é o código.

mongo --host Private IP Address
rs.initiate()
rs.add(“Private IP Address”)
rs.addArb(“Private IP Address”)

Tudo neste momento está bem. Quando vou ao site http://ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com:28017/_replSet , vejo que tenho um primário, um segundo dia e um árbitro.

Ok, agora para um teste.

No primário, crie um banco de dados neste é o código:

use tt
db.tt.save( { a : 123 } )

no secundário, faço isso e obtenho o erro abaixo:

db.tt.find()
error: { "$err" : "not master and slaveOk=false", "code" : 13435 }

Eu sou muito novo no mongodb e replico, mas pensei que se eu fizer algo em um, ele vai para o outro. Portanto, se eu adicionar um registro em um, o que devo fazer para replicar nas máquinas?

eLRuLL
fonte
descobri que eu tenho que usar rs.slaveOk (); Isso me deixa com outra pergunta. Eu tenho que fazer isso fazer isso para cada consulta? E se eu estiver no nó principal?

Respostas:

282

Você precisa definir o modo "slave okay" para que o mongo shell saiba que está permitindo leituras de um secundário. Isso serve para proteger você e seus aplicativos de realizar leituras eventualmente consistentes por acidente. Você pode fazer isso no shell com:

rs.slaveOk()

Depois disso, você pode consultar normalmente a partir de secundários.

Uma observação sobre "eventual consistência": em circunstâncias normais, os secundários do conjunto de réplicas têm todos os mesmos dados que as primárias em um segundo ou menos. Sob carga muito alta, os dados que você gravou no primário podem demorar um pouco para replicar nos secundários. Isso é conhecido como "atraso de réplica" e a leitura de um secundário atrasado é conhecida como uma leitura "eventualmente consistente", porque, embora os dados recém-gravados sejam exibidos em algum momento (exceto falhas de rede, etc.), pode não ser disponível imediatamente.

Editar: Você só precisa definir o slaveok ao consultar de secundários e apenas uma vez por sessão.

dcrosta
fonte
3
Sempre verifique o manual antes de executar comandos que você não entende em seus DBs. Pode haver consequências para o comando que a resposta não explica. Esse comando altera a maneira como as operações de leitura são distribuídas para todas as conexões com o conjunto de réplicas? Melhor descobrir. Esse comando aparece já na v2.2 docs.mongodb.com/v2.2/reference/method/rs.slaveOk Você pode (e deve) sempre substituir a parte "/ manual /" de uma URL do docs.mongodb.com à sua versão específica para garantir que você está recebendo informações relevantes.
Bruno Bronosky
45

Para evitar digitar rs.slaveOk()sempre, faça o seguinte:

Crie um arquivo chamado replStart.js, contendo uma linha:rs.slaveOk()

Em seguida, inclua --shell replStart.jsquando você iniciar o shell Mongo. Obviamente, se você estiver se conectando localmente a uma única instância, isso não salvará nenhuma digitação.

Ed Norris
fonte
26
Uma maneira melhor de economizar ao digitar seria adicionar rs.slaveOk()ao seu ~/.mongorc.jsarquivo, que será executado automaticamente ao iniciar o mongo shell.
Stennie #
2
Acho que é útil para colocar a configuração padrão no ~/.mongorc.jse configurações personalizadas em replStart.jsou adminStart.jsou qualquer outra coisa.
Ed Norris
41

no mongodb2.0

você deveria digitar

rs.slaveOk()

no nó mongod secundário

andyshi
fonte
11

ESTA É APENAS UMA NOTA PARA ALGUÉM LIDAR COM ESTE PROBLEMA USANDO O RUBY DRIVER

Eu tive esse mesmo problema ao usar a Ruby Gem.

Para definir slaveOk no Ruby, você apenas o passa como argumento quando cria o cliente assim:

mongo_client = MongoClient.new("localhost", 27017, { slave_ok: true })

https://github.com/mongodb/mongo-ruby-driver/wiki/Tutorial#making-a-connection

mongo_client = MongoClient.new # (optional host/port args)

Observe que 'args' é o terceiro argumento opcional.

campeterson
fonte
1

Estou apenas adicionando esta resposta para uma situação embaraçosa do provedor de banco de dados.

o que aconteceu no nosso caso é o banco de dados primário e secundário alterado de forma inversa (primário para secundário e vice-versa) e estamos recebendo o mesmo erro.

portanto, verifique as definições de configuração do status do banco de dados que podem ajudá-lo.

jit
fonte
0

Cheguei aqui procurando o mesmo erro, mas a partir de Node.js driver nativo . A resposta para mim foi a combinação de respostas de Campeterson e Prabhat .

O problema é que a readPreferenceconfiguração padrão é o que primary, de alguma forma, leva ao slaveOkerro confuso . Meu problema é que eu apenas quero ler do meu conjunto de réplicas a partir de qualquer nó. Eu nem me conecto a ele como replicaset. Acabei de me conectar a qualquer nó para ler a partir dele.

Definir readPreferencepara primaryPreferred(ou melhor para a ReadPreference.PRIMARY_PREFERREDconstante) resolveu isso para mim. Basta passá-lo como uma opção paraMongoClient.connect() ou para client.db()ou para qualquer find(), aggregate()ou outra função.

const { MongoClient, ReadPreference } = require('mongodb');
const client = await MongoClient.connect(MONGODB_CONNECTIONSTRING, { readPreference: ReadPreference.PRIMARY_PREFERRED });
kub1x
fonte