MongoDB: Step Down entre membros de diferentes prioridades
Quando trabalhamos com um Replica Set no MongoDB (caso você ainda não saiba o que é um Replica Set, expliquei neste artigo), é comum que seja necessário alterar o banco primário em cenários de manutenção programada, ou em cenários de falha do host primário, quando o Mongo não faz isso automaticamente. Entretanto, em ambientes onde os membros do Replica Set possuem diferentes prioridades, a execução de um Step Down (comando para que uma eleição de um novo banco primário seja feita) tem suas particularidades.
Como funciona a priority?
A priority (ou prioridade) de um membro do Replica Set é um número associado a ele, de 0 a 1000, que indica a probabilidade daquele membro se tornar o membro primário. Quanto maior o valor, maior esta probabilidade.
A priority dos membros do Replica Set pode ser vista através do método rs.conf() do mongosh. Esse método nos retorna um documento que contém a configuração do Replica Set. Dentro deste documento existe um array chamado “members” e cada item deste array é um documento referente a cada membro do Replica Set. Por exemplo:
rsMongoServer [direct: primary] test> rs.config() { _id: 'rsMongoServer', version: 2, term: 5, members: [ { _id: 0, host: 'mongo-server-0:27017', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 2, tags: {}, secondaryDelaySecs: Long('0'), votes: 1 }, { _id: 1, host: 'mongo-server-1:27017', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 1, tags: {}, secondaryDelaySecs: Long('0'), votes: 1 }, { _id: 2, host: 'mongo-server-2:27017', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 0, tags: {}, secondaryDelaySecs: Long('0'), votes: 1 } ], protocolVersion: Long('1'), writeConcernMajorityJournalDefault: true, settings: { chainingAllowed: true, heartbeatIntervalMillis: 2000, heartbeatTimeoutSecs: 10, electionTimeoutMillis: 10000, catchUpTimeoutMillis: -1, catchUpTakeoverDelayMillis: 30000, getLastErrorModes: {}, getLastErrorDefaults: { w: 1, wtimeout: 0 }, replicaSetId: ObjectId('66ee89b9905cec1617b71f0e') } }
Neste exemplo, o membro “mongo-server-0” tem uma prioridade de 2, o membro “mongo-server-1” tem uma prioridade de 1 e o membro “mongo-server-2” tem uma prioridade de 0. Sendo assim, o membro com prioridade 2 tem a maior probabilidade de ser o membro primário da configuração. Esse tipo de configuração é útil quando desejamos que determinado host seja o primário (um cenário onde um dos hosts possui um hardware melhor ou uma latência menor que os demais, pode ser uma justificativa para essa abordagem).
Membros com prioridade igual a 0 (zero) não podem se tornar o membro primário, e não iniciam eleições por um novo primário.
Cuidados durante o Step Down
Digamos que neste cenário, tenhamos a necessidade de executar uma manutenção no host primário que irá afetar temporariamente a sua performance. Em um Replica Set onde as prioridades dos membros são idênticas, teríamos simplesmente que executar o método rs.stepDown() do mongosh, e um dos demais membros se tornaria o primário, fazendo com que o workload dele não fosse impactado pela manutenção. O mesmo não ocorre em Replica Sets com prioridades diferentes entre seus membros.
Caso um Step Down seja executado para a configuração acima, o membro “mongo-server-1” irá assumir o papel de primário, uma vez que o membro “mongo-server-2” tem prioridade 0 (zero). O problema aqui é que se existe algum membro com uma prioridade maior que o atual primário, o Mongo continua a fazer periodicamente novas eleições, até que o membro com maior prioridade se torne o primário. Esse comportamento é muito útil em cenários onde, após uma falha do primário, desejamos que tão logo ele seja restabelecido, volte a ser o primário novamente.
Como no cenário atual desejamos manter o membro “mongo-server-1” por um período indefinido como primário, precisamos alterar a sua prioridade para um valor maior do que o membro “mongo-server-1”. Para isso, salvamos o documento retornado pelo rs.config() em uma variável:
rsMongoServer [direct: primary] test> cfg = rs.config()
Com o documento na variável, podemos editar o valor dos campos do documento. Como desejamos alterar a prioridade do membro “mongo-server-1”, podemos executar:
rsMongoServer [direct: primary] test> cfg.members[1].priority = 3
Antes de aplicar os novos valores ao Replica Set, podemos verificar como ficaram as prioridades, chamando o array “members”:
rsMongoServer [direct: primary] test> cfg.members [ { _id: 0, host: 'mongo-server-0:27017', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 2, tags: {}, secondaryDelaySecs: Long('0'), votes: 1 }, { _id: 1, host: 'mongo-server-1:27017', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 3, tags: {}, secondaryDelaySecs: Long('0'), votes: 1 }, { _id: 2, host: 'mongo-server-2:27017', arbiterOnly: false, buildIndexes: true, hidden: false, priority: 0, tags: {}, secondaryDelaySecs: Long('0'), votes: 1 } ]
Agora nosso membro “mongo-server-1” possui uma prioridade de 3, superior à prioridade 2 do membro “mongo-server-0”.
Para aplicar os novos valores à configuração do Replica Set, usamos o método rs.reconfig(), passando por parâmetro o documento presente na variável:
rsMongoServer [direct: primary] test> rs.reconfig(cfg)
Importante: o método rs.reconfig() só pode ser executado no primário.
Uma vez aplicada a nova configuração, o Mongo identificará a alteração da prioridade do membro e uma nova eleição é iniciada, alterando automaticamente o primário, sem a necessidade da execução do Step Down.
Conclusão
De modo geral, antes de executar um Step Down, quando temos a intenção de manter o novo primário por um tempo indeterminado, é verificar como está a atual configuração do Replica Set. Com isso evitamos que novas eleições ocorram e que o primário volte a ser o membro que não desejamos, possivelmente impactando a aplicação conectada ao banco.
Publicar comentário