O que é replicação?

Os dados podem ser copiados de um banco de dados para outro na mesma conta do IBM® Cloudant® for IBM Cloud®, entre contas e entre data centers.

Os dados podem até mesmo ser replicados de e para uma conta do IBM Cloudant e um dispositivo móvel por meio do uso PouchDB. A replicação pode ser executada em uma ou em ambas as direções, como um "disparo único" ou operação contínua e pode ser ajustada com precisão ao usar parâmetros.

O protocolo de replicação do IBM Cloudant é compatível com um intervalo de outros bancos de dados e bibliotecas, tornando-o um bom ajuste para Internet of Things (IoT) e aplicativos móveis.

O IBM Cloudant é um armazenamento de dados JSON distribuído com uma API HTTP. O IBM Cloudant pode ser executado como um serviço em diversas nuvens ou em seu rack de servidor. Os documentos são armazenados em bancos de dados e podem chegar a qualquer tamanho, pois o IBM Cloudant fragmenta seus dados em vários nós. A replicação é a cópia de dados de um banco de dados de origem para um banco de dados de destino. Os bancos de dados de origem e de destino não precisam estar na mesma conta do IBM Cloudant ou ainda no mesmo data center.

O gráfico mostra uma figura do banco de dados a e b. Banco de dados b tem um documento. Após a replicação, os documentos do banco de dados a são exibidos no banco de dados b.
Replicação em imagens

A replicação é concluída quando a versão mais recente de cada documento na origem é transferida para o banco de dados de destino. As transferências incluem novos documentos, atualizações para documentos existentes e exclusões. Apenas a versão mais recente de um documento permanece após a replicação; versões mais antigas são omitidas.

O banco de dados de origem permanece inalterado por replicação, separadamente dos dados de ponto de verificação que são gravados nele para permitir que replicações parciais continuem da última posição conhecida. Os dados preexistentes no banco de dados de destino permanecem.

Como começar a replicar com o painel

O painel do IBM Cloudant fornece uma interface com o usuário conveniente para acionar a replicação. Clique em Replication no painel do IBM Cloudant e em Start Replication. Complete o formulário de replicação a seguir:

caption-side=bottom"
Esta captura de tela mostra o formulário de replicação com todos os campos adequados preenchidos. Há uma seção de origem, que é o banco de dados local, e uma seção de destino, que é o novo banco de dados e a autenticação. Na seção “Opções”, você seleciona a replicação única ou recorrente e adiciona um documento de replicação. Formulário de replicação do

Para fins de segurança, a equipe do IBM Cloudant recomenda o uso de chaves de API do IAM ou de chaves de API de autenticação anterior do IBM Cloudant, em vez de credenciais em nível de conta, para as tarefas de replicação. Para obter mais informações, consulte a documentação Gerenciando o acesso ou a autenticação e a autorização anteriores.

Usando o formulário, definir os bancos de dados de origem e de destino, em seguida, clique em Start Replication.

O status de cada tarefa de replicação pode ser visto clicando em Replication. Cada tarefa muda de estado de Running para Completed à medida que ela progride. A captura de tela a seguir mostra o estado “ Completed ”.

No campo “Estado” da tabela, aparece “Concluído”.
Estado “Concluído”

Como replicar em diferentes contas do IBM Cloudant

A origem e o destino de uma replicação são URLs de bancos de dados IBM Cloudant, conforme mostrado no exemplo a seguir.

Veja o exemplo a seguir que define URLs de origem e de destino para replicação:

{
  "source": {
    "url": "https://myfirstaccount.cloudant.com/a",
    "auth": {
      "basic": {
        "username": "$USERNAME",
        "password": "$PASSWORD"
      }
    }
  },
  "target": {
    "url": "https://mysecondaccount.cloudant.com/b",
    "auth": {
      "basic": {
        "username": "$USERNAME",
        "password": "$PASSWORD"
      }
    }
  }
}

A origem e o destino não precisam estar na mesma conta. Os nomes dos bancos de dados de origem e de destino não precisam corresponder. Deve-se estar autorizado a acessar a origem e o destino e estar autorizado a gravar no destino.

A replicação é executada na origem ou no destino?

A replicação pode ser iniciada na extremidade de origem ou de destino. Essa opção significa que é possível decidir se a conta A enviará dados por push para a conta B ou a conta B puxará dados da conta A. Em alguns casos, talvez não seja possível executar a replicação em nenhuma das configurações, por exemplo, quando uma conta estiver protegida por um firewall. A replicação ocorre por meio do protocolo HTTPS; portanto, não é necessário abrir portas fora do padrão. A decisão quanto a qual dispositivo iniciará a replicação é sua.

Como a replicação afeta a lista de mudanças?

É possível obter uma lista das alterações feitas em um documento usando o endpoint _changes. No entanto, a natureza distribuída de bancos de dados IBM Cloudant significa que a resposta que é fornecida pelo feed _changes não pode ser uma lista simples de mudanças que ocorreram após uma determinada data e hora.

A discussão Teorema do CAP deixa claro que o IBM Cloudant usa um modelo "eventualmente consistente". Esse modelo significa que é possível obter resultados diferentes ao solicitar duas réplicas diferentes de um banco de dados para um documento simultaneamente. Isso pode acontecer quando uma das cópias do banco de dados ainda está esperando para concluir a replicação.

Posteriormente, as cópias do banco de dados concluem sua replicação para que todas as mudanças em um documento estejam presentes em cada cópia.

Este modelo de "consistência eventual" tem duas características que afetam uma lista de mudanças:

  1. Uma mudança que afeta um documento quase certamente ocorrerá em diferentes momentos em diferentes cópias do banco de dados.
  2. A ordem em que as mudanças afetam documentos pode diferir entre cópias diferentes do banco de dados, dependendo de quando e de onde a replicação ocorreu.

Uma consequência da primeira característica é que, ao solicitar uma lista de mudanças, não fará sentido solicitá-la após um momento específico. O motivo é que a lista de mudanças pode ser fornecida por uma cópia de banco de dados diferente, que resultou em atualizações de documentos em momentos diferentes. No entanto, fará sentido solicitar uma lista de mudanças após uma mudança específica, que será especificada usando um identificador de sequência.

Uma consequência extra da primeira característica é que pode ser necessário "olhar para trás" nas mudanças anteriores para concordar com a lista de mudanças. Em outras palavras, para obter uma lista de mudanças, você começará da mudança mais recente com a qual as cópias do banco de dados concordarem. O ponto de acordo entre cópias de banco de dados é identificado dentro do IBM Cloudant usando o mecanismo de ponto de verificação que possibilita a replicação entre cópias de banco de dados a serem sincronizadas.

Por fim, quando você considera uma lista de mudanças, elas podem ser apresentadas em uma ordem diferente em solicitações subsequentes. A ordem depende de como os documentos foram mudados entre as diferentes cópias de banco de dados. Em outras palavras, uma lista inicial de mudanças pode relatar mudanças A, B e, em seguida, C, nessa ordem. Mas uma lista subsequente de mudanças pode relatar mudanças C, A e, em seguida, B, nessa ordem. Todas as mudanças são listados, mas em uma ordem diferente. Essa diferença é porque a sequência de mudanças recebidas durante a replicação pode variar entre duas cópias diferentes do banco de dados.

O que significa "consistência eventual" para a lista de mudanças?

Ao solicitar uma lista de mudanças, a resposta obtida poderá variar, dependendo de qual cópia do banco de dados fornecer a lista.

A opção since obtém uma lista de mudanças após um identificador de sequência de atualização específico. A lista sempre inclui mudanças posteriores à atualização, mas mudanças anteriores também podem ser incluídas. O motivo é que a cópia do banco de dados que responde à solicitação de lista deve assegurar que ela liste as mudanças, consistente com todas as réplicas. Para alcançar essa consistência, a cópia do banco de dados poderá ter que iniciar a lista de mudanças do ponto em que todas as cópias tiverem concordado. Esse ponto é identificado usando pontos de verificação.

Portanto, um aplicativo que utilize o feed _changes deve ser “idempotente”. Idempotência significa que o aplicativo deve ser capaz de receber com segurança os mesmos dados várias vezes, e, possivelmente, em uma ordem diferente no caso de solicitações repetidas.

Checkpoints

Internamente, o processo de replicação grava seu estado em documentos de "ponto de verificação" armazenados nos bancos de dados de origem e de destino. Os pontos de verificação permitem que uma tarefa de replicação continue de onde parou, sem precisar começar do início. É possível impedir a criação de pontos de verificação fornecendo o "use_checkpoints": false opção quando você solicita replicação. Será útil deixar o recurso ativado, se a sua replicação tiver que continuar de maneira eficiente da última posição conhecida.

Permissões

O acesso de administrador é necessário para inserir um documento no banco de dados _replicator. As credenciais de login que são fornecidas nos parâmetros de origem e de destino não requerem permissões de administrador integrais. É suficiente que as credenciais executem as tarefas a seguir:

  • Gravar documentos na extremidade de destino.
  • Gravar documentos de ponto de verificação em ambas as extremidades.

O IBM Cloudant tem uma permissão de usuário _replicator especial. Essa permissão permite que os documentos de ponto de verificação sejam criados, mas não permite a criação de documentos comuns em um banco de dados. Em geral, crie chaves API que tenham:

  • Acesso _reader e _replicator no lado de origem.
  • Acesso _reader e _writer no lado de destino.

As chaves API podem ser criadas e configuradas no Painel do IBM Cloudant, em uma base por banco de dados.

As chaves de API podem ser criadas e configuradas no IBM Cloudant Dashboard, com base em cada banco de dados
IBM Cloudant Usuários e chaves de API com

Elas também podem ser criadas programaticamente usando a API do IBM Cloudant.

Para fins de segurança, a equipe do IBM Cloudant recomenda o uso de chaves de API do IAM ou de chaves de API de autenticação anterior do IBM Cloudant, em vez de credenciais em nível de conta, para as tarefas de replicação. Para obter mais informações, consulte a documentação Gerenciando acesso ou a autenticação e a autorização anteriores.

Replicação em duas vias

Os dados podem ser copiados em ambas as direções em um processo conhecido como replicação em duas vias ou sincronização. Você ativa essa sincronização configurando dois processos de replicação separados, um levando os dados de A para B, o outro levando dados de B para A. Ambos os processos de replicação trabalham de forma independente, com dados movidos perfeitamente em ambas as direções.

O gráfico mostra banco de dados a e b. Banco de dados a tem quatro documentos, um é riscada. Banco de dados b tem um documento. Depois de replicar banco de dados a para banco de dados b, banco de dados b tem cinco documentos, um é riscada. Após replicar o banco de dados b para o banco de dados a, o banco de dados a também passa a ter cinco documentos, sendo que um deles está riscado.
Replicação bidirecional

Discussão sobre replicação contínua

Até agora, a discussão lida apenas com replicação única, que é concluída quando todos os dados de origem são gravados no banco de dados de destino. Com a replicação contínua, os dados fluem continuamente. Todas as mudanças subsequentes no banco de dados de origem são transmitidas para o banco de dados de destino em tempo real.

A replicação contínua é acionada ao marcar a caixa de seleção “ Make this replication continuous ” ao definir uma tarefa de replicação no Painel do IBM Cloudant, ou ao definir o continuous na API do IBM Cloudant.

A replicação em duas vias pode se tornar contínua em uma ou em ambas as direções, configurando a sinalização como continuous.

Veja o exemplo a seguir que usa HTTP para iniciar uma replicação contínua:

POST /_replicator HTTP/1.1
Content-Type: application/json
Host: $SERVICE_URL
Authorization: ...

Veja o exemplo a seguir para iniciar uma replicação contínua:

curl -X POST \
    -H "Content-type: application/json" \
    "$SERVICE_URL/_replicator" \
    -d '{ "_id": "repldoc-example",
          "continuous": true,
          "create_target": true,
          "source": { "url": "'"$SOURCE_SERVICE_URL/source"'" },
          "target": {
            "auth": { "iam": { "api_key": "'"$API_KEY"'" } },
            "url": "'"$TARGET_SERVICE_URL/target"'"
          }
        }'
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.DocumentResult;
import com.ibm.cloud.cloudant.v1.model.PutReplicationDocumentOptions;
import com.ibm.cloud.cloudant.v1.model.ReplicationDatabase;
import com.ibm.cloud.cloudant.v1.model.ReplicationDatabaseAuth;
import com.ibm.cloud.cloudant.v1.model.ReplicationDatabaseAuthIam;
import com.ibm.cloud.cloudant.v1.model.ReplicationDocument;
Cloudant service = Cloudant.newInstance();
ReplicationDatabase sourceDb = new ReplicationDatabase.Builder()
    .url("<your-source-service-url>/source")
    .build();
ReplicationDatabaseAuthIam targetAuthIam =
    new ReplicationDatabaseAuthIam.Builder()
        .apiKey("<your-iam-api-key>")
        .build();
ReplicationDatabaseAuth targetAuth = new ReplicationDatabaseAuth.Builder()
    .iam(targetAuthIam)
    .build();
ReplicationDatabase targetDb = new ReplicationDatabase.Builder()
    .auth(targetAuth)
    .url("<your-target-service-url>/target")
    .build();
ReplicationDocument replDocument = new ReplicationDocument();
replDocument.setSource(sourceDb);
replDocument.setTarget(targetDb);
replDocument.setContinuous(true);
PutReplicationDocumentOptions replicationDocumentOptions =
    new PutReplicationDocumentOptions.Builder()
        .docId("repldoc-example")
        .replicationDocument(replDocument)
        .build();
DocumentResult response =
    service.putReplicationDocument(replicationDocumentOptions).execute()
        .getResult();
System.out.println(response);
const { CloudantV1 } = require('@ibm-cloud/cloudant');
const service = CloudantV1.newInstance({});
const sourceDb: CloudantV1.ReplicationDatabase = {
  url: '<your-source-service-url>/source'
};
const targetDb: CloudantV1.ReplicationDatabase = {
  auth: {
    iam: {
      'api_key': '<your-iam-api-key>'
    }
  },
  url: '<your-target-service-url>/target'
};
const replDocument: CloudantV1.ReplicationDocument = {
  id: 'repldoc-example',
  continuous: true,
  create_target: true,
  source: sourceDb,
  target: targetDb
}
service.putReplicationDocument({
  docId: 'repldoc-example',
  replicationDocument: replDocument
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1, ReplicationDocument, ReplicationDatabase, ReplicationDatabaseAuthIam, ReplicationDatabaseAuth
service = CloudantV1.new_instance()
source_db = ReplicationDatabase(
  url='<your-source-service-url>/source'
)
target_auth_iam = ReplicationDatabaseAuthIam(
  api_key='<your-iam-api-key>'
)
target_auth = ReplicationDatabaseAuth(
  iam=target_auth_iam
)
target_db = ReplicationDatabase(
  auth=target_auth,
  url='<your-target-service-url>/target'
)
replication_document = ReplicationDocument(
  id='repldoc-example',
  continuous=True,
  create_target=True,
  source=source_db,
  target=target_db
)
response = service.put_replication_document(
  doc_id='repldoc-example',
  replication_document=replication_document
).get_result()
print(response)
source, err := service.NewReplicationDatabase(
  "<your-source-service-url>/source",
)
if err != nil {
  panic(err)
}
target, err := service.NewReplicationDatabase(
  "<your-target-service-url>/target",
)
if err != nil {
  panic(err)
}
auth, err := service.NewReplicationDatabaseAuthIam(
  "<your-iam-api-key>",
)
if err != nil {
  panic(err)
}
target.Auth = &cloudantv1.ReplicationDatabaseAuth{Iam: auth}
replicationDoc, err := service.NewReplicationDocument(
  source,
  target,
)
if err != nil {
  panic(err)
}
replicationDoc.Continuous = core.BoolPtr(true)
replicationDoc.CreateTarget = core.BoolPtr(true)
putReplicationDocumentOptions := service.NewPutReplicationDocumentOptions(
  "repldoc-example",
  replicationDoc,
)
documentResult, response, err := service.PutReplicationDocument(putReplicationDocumentOptions)
if err != nil {
  panic(err)
}
b, _ := json.MarshalIndent(documentResult, "", "  ")
fmt.Println(string(b))

O exemplo do Go anterior requer o bloco de importação a seguir:

import (
   "encoding/json"
   "fmt"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

Todos os exemplos do Go requerem que o objeto service seja inicializado. Para obter mais informações, consulte a seção Autenticação da documentação da API para exemplos.

Veja o exemplo a seguir de um documento JSON que define uma replicação contínua:

{
    "_id": "weekly_continuous_backup",
    "source": {
      "url": "https://$SOURCE_SERVICE_DOMAIN/source",
      "auth": {
        "basic": {
          "username": "$USERNAME",
          "password": "$PASSWORD"
        }
      }
    },
    "target": {
      "url": "https://$TARGET_SERVICE_DOMAIN/target",
      "auth": {
        "basic": {
          "username": "$USERNAME",
          "password": "$PASSWORD"
        }
      }
    },
    "continuous": true
}

Outros casos de uso de replicação

O protocolo de replicação do IBM Cloudant é compatível com outros bancos de dados e bibliotecas para vários aplicativos do mundo real.

Apache CouchDB

Apache CouchDB é um banco de dados de código aberto que pode se comunicar com o IBM Cloudant, e que requer uma configuração mínima. Os aplicativos a seguir estão incluídos:

  • Backup — Replique seus dados do IBM Cloudant para seus próprios bancos de dados CouchDB e faça backups noturnos dos seus dados para fins de arquivamento. Envie os dados para um serviço de backup, como o Amazon Glacier, para mantê-los em segurança.
  • Coleta de dados com prioridade local — Grave seus dados primeiro no Apache CouchDB local, em seguida, replicá-lo para IBM Cloudant para armazenamento de longo prazo, agregação, e análise.

PouchDB

PouchDB é um banco de dados de código aberto, disponível diretamente no navegador, que permite a replicação de dados em ambas as direções entre o navegador e IBM Cloudant. Armazenar os dados em um navegador da web no lado do cliente permite que os aplicativos da web funcionem mesmo sem uma conexão com a Internet. O PouchDB pode sincronizar qualquer dado mudado para e do IBM Cloudant quando uma conexão de Internet está presente. Configurar a replicação do lado do cliente requer algumas linhas de JavaScript.

Veja o exemplo de JavaScript a seguir que usa o PouchDB para ativar a replicação:

var db = new PouchDB("myfirstdatabase");
var URL = "https://$USERNAME:$PASSWORD@$SERVICE_DOMAIN/my_database");
db.sync(URL, { live: true });

Replicações filtradas

É prático poder remover alguns dados durante o processo de replicação ao replicar um banco de dados para outro, como pode ser visto nos exemplos a seguir:

  • Remoção de todos os rastreios de documentos excluídos, tornando o banco de dados de destino menor que o de origem.
  • Separar os dados em partes menores, como, por exemplo, armazenar os dados do Reino Unido em um banco de dados e os dados dos EUA em outro.

Funções do filtro de replicação

A replicação filtrada do IBM Cloudant permite a definição de uma função JavaScript que usa o valor de retorno para determinar se cada documento em um banco de dados deve ser filtrado ou não. As funções de filtro são armazenadas em documentos de design.

Veja a função de filtro de exemplo a seguir para replicar documentos não excluídos:

function(doc, req) {
    if (doc._deleted) {
        return false;
    }
    return true;
}

Quando uma tarefa de replicação é iniciada, o nome de uma função de filtro é especificado como uma combinação do documento de design de onde está armazenado e o nome da função de filtro. Também é possível especificar um valor query_params. Esse valor é um objeto que contém propriedades que são passadas para a função de filtro no campo query de seu segundo argumento (req).

Veja o exemplo a seguir que usa HTTP para iniciar uma replicação filtrada:

POST /_replicator HTTP/1.1
Content-Type: application/json
Host: $SERVICE_URL
Authorization: ...

Veja o exemplo a seguir que usa a linha de comandos para iniciar uma replicação filtrada:

curl -X POST \
    -H "Content-type: application/json" \
    "$SERVICE_URL/_replicator" \
    -d @filtered-replication.json
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.DocumentResult;
import com.ibm.cloud.cloudant.v1.model.PutReplicationDocumentOptions;
import com.ibm.cloud.cloudant.v1.model.ReplicationDatabase;
import com.ibm.cloud.cloudant.v1.model.ReplicationDatabaseAuth;
import com.ibm.cloud.cloudant.v1.model.ReplicationDatabaseAuthIam;
import com.ibm.cloud.cloudant.v1.model.ReplicationDocument;
Cloudant service = Cloudant.newInstance();
ReplicationDatabase sourceDb = new ReplicationDatabase.Builder()
    .url("<your-source-service-url>/source")
    .build();
ReplicationDatabaseAuthIam targetAuthIam =
    new ReplicationDatabaseAuthIam.Builder()
        .apiKey("<your-iam-api-key>")
        .build();
ReplicationDatabaseAuth targetAuth = new ReplicationDatabaseAuth.Builder()
    .iam(targetAuthIam)
    .build();
ReplicationDatabase targetDb = new ReplicationDatabase.Builder()
    .auth(targetAuth)
    .url("<your-target-service-url>/target"))
    .build();
ReplicationDocument replDocument = new ReplicationDocument();
replDocument.setSource(sourceDb);
replDocument.setTarget(targetDb);
replDocument.setFilter("mydesigndoc/myfilter");
Map queryParams = new HashMap<>();
queryParams.put("foo", "bar");
queryParams.put("baz", 5);
replDocument.setQueryParams(queryParams);
PutReplicationDocumentOptions replicationDocumentOptions =
    new PutReplicationDocumentOptions.Builder()
        .docId("repldoc-example")
        .replicationDocument(replDocument)
        .build();
DocumentResult response =
    service.putReplicationDocument(replicationDocumentOptions).execute()
        .getResult();
System.out.println(response);
const { CloudantV1 } = require('@ibm-cloud/cloudant');
const service = CloudantV1.newInstance({});
const sourceDb: CloudantV1.ReplicationDatabase = {
  url: '<your-source-service-url>/source'
};
const targetDb: CloudantV1.ReplicationDatabase = {
  auth: {
    iam: {
      'api_key': '<your-iam-api-key>'
    }
  },
  url: '<your-target-service-url>/target'
};
const replDocument: CloudantV1.ReplicationDocument = {
  id: 'repldoc-example',
  filter: 'mydesigndoc/myfilter',
  query_params: {'foo': 'bar', 'baz': 5},
  source: sourceDb,
  target: targetDb
}
service.putReplicationDocument({
  docId: 'repldoc-example',
  replicationDocument: replDocument
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1, ReplicationDocument, ReplicationDatabase, ReplicationDatabaseAuthIam, ReplicationDatabaseAuth
service = CloudantV1.new_instance()
source_db = ReplicationDatabase(
  url='<your-source-service-url>/source'
)
target_auth_iam = ReplicationDatabaseAuthIam(
  api_key='<your-iam-api-key>'
)
target_auth = ReplicationDatabaseAuth(
  iam=target_auth_iam
)
target_db = ReplicationDatabase(
  auth=target_auth,
  url='<your-target-service-url>/target'
)
replication_document = ReplicationDocument(
  id='repldoc-example',
  filter='mydesigndoc/myfilter',
  query_params={'foo': 'bar', 'baz': 5},
  source=source_db,
  target=target_db
)
response = service.put_replication_document(
  doc_id='repldoc-example',
  replication_document=replication_document
).get_result()
print(response)
source, err := service.NewReplicationDatabase(
  "<your-source-service-url>/source",
)
if err != nil {
  panic(err)
}
target, err := service.NewReplicationDatabase(
  "<your-target-service-url>/target",
)
if err != nil {
  panic(err)
}
auth, err := service.NewReplicationDatabaseAuthIam(
  "<your-iam-api-key>",
)
if err != nil {
  panic(err)
}
target.Auth = &cloudantv1.ReplicationDatabaseAuth{Iam: auth}
replicationDoc, err := service.NewReplicationDocument(
  source,
  target,
)
if err != nil {
  panic(err)
}
replicationDoc.Filter := "mydesigndoc/myfilter"
replicationDoc.QueryParams := map[string]interface{}{"foo": "bar", "baz": 5}
putReplicationDocumentOptions := service.NewPutReplicationDocumentOptions(
  "repldoc-example",
  replicationDoc,
)
documentResult, response, err := service.PutReplicationDocument(putReplicationDocumentOptions)
if err != nil {
  panic(err)
}
b, _ := json.MarshalIndent(documentResult, "", "  ")
fmt.Println(string(b))

O exemplo do Go anterior requer o bloco de importação a seguir:

import (
   "encoding/json"
   "fmt"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
   "github.com/IBM/go-sdk-core/core"
)

Todos os exemplos do Go requerem que o objeto service seja inicializado. Para obter mais informações, consulte a seção Autenticação da documentação da API para exemplos.

Veja o exemplo a seguir de um documento JSON que define uma replicação filtrada:

{
    "_id": "weekly_backup",
    "source": {
      "url": "https://$SOURCE_SERVICE_DOMAIN/source",
      "auth": {
        "basic": {
          "username": "$USERNAME",
          "password": "$PASSWORD"
        }
      }
    },
    "target": {
      "url": "https://$TARGET_SERVICE_DOMAIN/target",
      "auth": {
        "basic": {
          "username": "$USERNAME",
          "password": "$PASSWORD"
        }
      }
    },
    "filter": "mydesigndoc/myfilter",
    "query_params": {
        "foo": "bar",
        "baz": 5
    }
}

Feed de mudanças

IBM Cloudant publica as adições, edições e exclusões que afetam um banco de dados por meio de um único feed HTTP a partir do endpoint _changes. Esse feed pode ser usado por seu aplicativo para acionar eventos. É possível acessar o feed usando HTTP ou curl, conforme mostrado nos exemplos. O uso da opção feed=continuous significa que o fluxo fornecerá a você todas as mudanças necessárias para obter a versão mais recente de cada documento no banco de dados.

Para obter mais informações, consulte Usando as FAQs do feed de mudanças do IBM Cloudant.

Veja o exemplo a seguir que usa HTTP para consultar o feed de mudanças:

GET /$DATABASE/_changes?feed=continuous HTTP/1.1
Host: $SERVICE_URL
Authorization: ...

Veja o exemplo a seguir que usa a linha de comandos para consultar o feed de mudanças:

curl "$SERVICE_URL/$DATABASE/_changes?feed=continuous"

As mudanças são descritas usando uma linha por mudança. Cada mudança consiste em:

  1. Uma sequência que contém um número de sequência (seq).
  2. Uma sequência que contém o ID do documento que foi mudado.
  3. Uma matriz de mudanças.

Para ver o próprio corpo do documento, anexe &include_docs=true ao comando curl.

Cada mudança é descrita usando o formato mostrado no exemplo (abreviado) a seguir.

Veja o feed de exemplo _changes a seguir:

{
    "seq":"11-g1A...c1Q",
    "id":"6f8ab9fa52c117eb76240daa1a55827f",
    "changes":[
        {
          "rev":"1-619d7981d7027274a4b88810d318a7b1"
        }
    ]
}

Para associar-se ao feed de mudanças por meio de uma posição conhecida, transmita um argumento since com o número de sequência que deseja iniciar.

Veja o exemplo a seguir (abreviado) que usa HTTP para fornecer a opção since para se associar a um feed _changes em uma posição conhecida:

GET /$DATABASE/_changes?feed=continuous&include_docs=true&since=11-g1A...c1Q HTTP/1.1
HOST: $SERVICE_URL
Authorization: ...

Veja o exemplo a seguir (abreviado) que usa a linha de comandos para fornecer a opção since para se associar a um feed _changes em uma posição conhecida:

curl "$SERVICE_URL/$DATABASE/_changes?feed=continuous&include_docs=true&since=11-g1A...c1Q"

Para unir novamente o feed de mudanças do momento atual, configure since=now.

Veja o exemplo a seguir que usa HTTP para fornecer since=now para se unir a um feed _changes no momento atual:

GET /$DATABASE/_changes?feed=continuous&include_docs=true&since=now HTTP/1.1
Host: $SERVICE_URL
Authorization: ...

Veja o exemplo a seguir que usa a linha de comandos para fornecer since=now para se associar a um feed _changes no momento atual:

curl "$SERVICE_URL/$DATABASE/_changes?feed=continuous&include_docs=true&since=now"

O acesso aos dados _changes programaticamente é feito de forma direta. Por exemplo, veja os exemplos do SDK no IBM Cloudant API docs para seguir mudanças com algumas linhas de código.

A lista a seguir inclui alguns casos de uso de exemplo:

  • Inclusão de itens em uma fila de mensagens para emitir ações em seu aplicativo, como enviar um e-mail do cliente.
  • Atualização de um banco de dados contido na memória para registrar contagens de atividades em tempo real.
  • Gravação de dados em um arquivo de texto para enviar dados por push para um banco de dados SQL.

O feed de mudanças pode ser filtrado com uma função de filtro usando uma técnica semelhante à filtragem durante a replicação.

Veja o exemplo a seguir que usa HTTP para filtrar as mudanças de feed:

GET /$DATABASE/_changes?feed=continuous&include_docs=true&since=now&filter=mydesigndoc/myfilter HTTP/1.1
Host: $SERVICE_URL
Authorization: ...

Veja o exemplo a seguir que usa a linha de comandos para filtrar as mudanças de feed:

curl "$SERVICE_URL/$DATABASE/_changes?feed=continuous&include_docs=true&since=now&filter=mydesigndoc/myfilter"

A ordenação de documentos dentro do feed _changes não é sempre a mesma. Em outras palavras, as mudanças podem não aparecer em ordem estrita de tempo. A razão é que os dados são retornados de diversos nós do IBM Cloudant e as regras de consistência eventual se aplicam.

Armadilhas de replicação

Para replicar com êxito, a soma do tamanho do documento e de todos os tamanhos do anexo deve ser menor que o tamanho máximo da solicitação do cluster de destino. Por exemplo, se o tamanho máximo da solicitação de HTTP for 11 MB, os cenários a seguir se aplicarão:

Tamanho do documento Tamanho do anexo Tamanho total Replica?
1 MB Cinco anexos de 2 MB 11 MB True
1 MB Um anexo de 10 MB 11 MB True
1 MB Cem anexos de 1 MB 101 MB Não
{: caption="Vários cenários com base no tamanho máximo de uma solicitação de HTTP, que é de 11 MB" caption-side="top"}

Várias considerações se aplicam quando você usa a replicação.

Permissões de usuário incorretas

Para que a replicação continue de forma ideal ao replicar do banco de dados "a" para o banco de dados "b", as credenciais fornecidas deverão ter:

  • Permissões _reader e _replicator no banco de dados "a".
  • Permissões _writer no banco de dados "b".

As chaves de API são geradas no Painel do IBM Cloudant ou por meio da API. Cada chave pode receber permissões individuais relacionadas a um banco de dados específico do IBM Cloudant. O IBM Cloudant deve ser capaz de gravar seus documentos de ponto de verificação na extremidade de "leitura" da replicação, caso contrário, nenhum estado é salvo e a replicação não pode continuar de onde parou. Se o estado não for salvo, ele poderá levar a problemas de desempenho quando a replicação de conjuntos de dados grandes continuar. O motivo é que sem os pontos de verificação, o processo de replicação é reiniciado do começo sempre que é continuado.

O documento de replicação entra em conflito

Outra consequência da configuração de permissões de usuário incorretamente é que o documento _replicator torna-se conflituoso. O documento _replicator registra o estado atual do processo de replicação. Em um caso extremo, o documento pode se tornar grande porque contém muitos conflitos não resolvidos. Um documento tão grande usa muito do espaço disponível e causa carregamento extra do servidor.

É possível verificar o tamanho do banco de dados _replicator enviando uma solicitação GET para o terminal /_replicator:

curl "$SERVICE_URL/_replicator"
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.DatabaseInformation;
import com.ibm.cloud.cloudant.v1.model.GetDatabaseInformationOptions;
Cloudant service = Cloudant.newInstance();
GetDatabaseInformationOptions databaseInfoOptions =
    new GetDatabaseInformationOptions.Builder()
        .db("_replicator")
        .build();
DatabaseInformation response =
    service.getDatabaseInformation(databaseInfoOptions).execute()
        .getResult();
System.out.println(response);
const { CloudantV1 } = require('@ibm-cloud/cloudant');
const service = CloudantV1.newInstance({});
service.getDatabaseInformation({db: '_replicator'}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.get_database_information(db='_replicator').get_result()
print(response)
getDatabaseInformationOptions := service.NewGetDatabaseInformationOptions(
  "_replicator",
)
databaseInformation, response, err := service.GetDatabaseInformation(getDatabaseInformationOptions)
if err != nil {
  panic(err)
}
b, _ := json.MarshalIndent(databaseInformation, "", "  ")
fmt.Println(string(b))

O exemplo do Go anterior requer o bloco de importação a seguir:

import (
   "encoding/json"
   "fmt"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

Todos os exemplos do Go requerem que o objeto service seja inicializado. Para obter mais informações, consulte a seção Autenticação da documentação da API para exemplos.

Obter conflitos a partir de documento de replicação

No JSON retornado, procure o valor disk_size. Se o valor indicar um tamanho acima de 1 GB, acesse o Portal de Suporte do IBM Cloud para mais conselhos.

É possível verificar um documento _replicator individual para conflitos, conforme mostrado no exemplo a seguir:

curl "$SERVICE_URL/_replicator/$DOCID?conflicts=true"
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.GetReplicationDocumentOptions;
import com.ibm.cloud.cloudant.v1.model.ReplicationDocument;
Cloudant service = Cloudant.newInstance();
GetReplicationDocumentOptions replicationDocOptions =
    new GetReplicationDocumentOptions.Builder()
        .conflicts(true)
        .docId("$DOCID")
        .build();
ReplicationDocument response =
    service.getReplicationDocument(replicationDocOptions).execute()
        .getResult();
System.out.println(response);
const { CloudantV1 } = require('@ibm-cloud/cloudant');
const service = CloudantV1.newInstance({});
service.getReplicationDocument({
  conflicts: true,
  docId: '$DOCID'
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.get_replication_document(
  conflicts=True,
  doc_id='$DOCID'
).get_result()
print(response)
getReplicationDocumentOptions := service.NewGetReplicationDocumentOptions(
  "$DOCID",
)
replicationDocument, response, err := service.GetReplicationDocument(getReplicationDocumentOptions)
if err != nil {
  panic(err)
}
replicationDocument.Conflicts = core.BoolPtr(true)
b, _ := json.MarshalIndent(replicationDocument, "", "  ")
fmt.Println(string(b))

O exemplo do Go anterior requer o bloco de importação a seguir:

import (
   "encoding/json"
   "fmt"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
   "github.com/IBM/go-sdk-core/core"
)

Todos os exemplos do Go requerem que o objeto service seja inicializado. Para obter mais informações, consulte a seção Autenticação da documentação da API para exemplos.

Cancelar todas as replicações

Se desejar cancelar todas as replicações e iniciar com uma nova, limpe o banco de dados _replicator, exclua e, em seguida, recrie o banco de dados replicator.

Consulte o seguinte link HTTP para remover e recriar o banco de dados _replicator:

DELETE /_replicator HTTP/1.1
HOST: $SERVICE_URL
Authorization: ...
PUT /_replicator HTTP/1.1
HOST: $SERVICE_URL
Authorization: ...

Excluir o banco de dados do replicador

Veja o exemplo a seguir para remover o banco de dados _replicator:

curl -X DELETE "$SERVICE_URL/_replicator"
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.DeleteDatabaseOptions;
import com.ibm.cloud.cloudant.v1.model.Ok;
Cloudant service = Cloudant.newInstance();
DeleteDatabaseOptions deleteDatabaseOptions = new DeleteDatabaseOptions.Builder()
        .db("_replicator")
        .build();
Ok response = service.deleteDatabase(deleteDatabaseOptions).execute()
        .getResult();
System.out.println(response);
const { CloudantV1 } = require('@ibm-cloud/cloudant');
const service = CloudantV1.newInstance({});
service.deleteDatabase({db: '_replicator'}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.delete_database(db='_replicator').get_result()
print(response)
deleteDatabaseOptions := service.NewDeleteDatabaseOptions(
  "_replicator",
)
ok, response, err := service.DeleteDatabase(deleteDatabaseOptions)
if err != nil {
  panic(err)
}
b, _ := json.MarshalIndent(ok, "", "  ")
fmt.Println(string(b))

O exemplo do Go anterior requer o bloco de importação a seguir:

import (
   "encoding/json"
   "fmt"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

Todos os exemplos do Go requerem que o objeto service seja inicializado. Para obter mais informações, consulte a seção Autenticação da documentação da API para exemplos.

Recriar o banco de dados do replicador

Veja o exemplo a seguir para recriar o banco de dados _replicator:

curl -X PUT "$SERVICE_URL/_replicator"
import com.ibm.cloud.cloudant.v1.Cloudant;
import com.ibm.cloud.cloudant.v1.model.Ok;
import com.ibm.cloud.cloudant.v1.model.PutDatabaseOptions;
Cloudant service = Cloudant.newInstance();
PutDatabaseOptions databaseOptions = new PutDatabaseOptions.Builder()
    .db("_replicator")
    .build();
Ok response =
    service.putDatabase(databaseOptions).execute()
        .getResult();
System.out.println(response);
const { CloudantV1 } = require('@ibm-cloud/cloudant');
const service = CloudantV1.newInstance({});
service.putDatabase({
  db: '_replicator'
}).then(response => {
  console.log(response.result);
});
from ibmcloudant.cloudant_v1 import CloudantV1
service = CloudantV1.new_instance()
response = service.put_database(db='_replicator').get_result()
print(response)
putDatabaseOptions := service.NewPutDatabaseOptions(
  "_replicator",
)
ok, response, err := service.PutDatabase(putDatabaseOptions)
if err != nil {
  panic(err)
}
b, _ := json.MarshalIndent(ok, "", "  ")
fmt.Println(string(b))

O exemplo do Go anterior requer o bloco de importação a seguir:

import (
   "encoding/json"
   "fmt"
   "github.com/IBM/cloudant-go-sdk/cloudantv1"
)

Todos os exemplos do Go requerem que o objeto service seja inicializado. Para obter mais informações, consulte a seção Autenticação da documentação da API para exemplos.

Muitas replicações simultâneas

É fácil de esquecer que você configurou anteriormente a replicação entre dois bancos de dados e, portanto, criar processos de replicação extras com erro. Cada tarefa de replicação é independente da outra, então o IBM Cloudant não evita a criação de processos extras de replicação. No entanto, cada tarefa de replicação esgota os recursos do sistema.

É possível verificar suas "replicações ativas" no painel do IBM Cloudant para garantir que nenhuma tarefa de replicação indesejada esteja em andamento. Exclua os documentos _replicator que não são mais necessários.

Ajustando a velocidade de replicação

Por padrão, A replicação do IBM Cloudant é executada em uma taxa apropriada para obter os dados da origem para o destino sem afetar negativamente o desempenho. Escolher entre a taxa de replicação e o desempenho do cluster para outras tarefas é uma troca. Seu caso de uso pode requerer replicação mais rápida às custas de outros serviços do IBM Cloudant. Como alternativa, talvez você requeira que o desempenho do cluster tenha prioridade, com a replicação tratada como um processo de segundo plano.

Opções avançadas de API de replicação estão disponíveis. Essas opções permitem um aumento ou uma diminuição na quantidade de energia de computação usada durante a replicação, conforme mostrado nos exemplos a seguir:

  • Se os seus documentos contiverem anexos, talvez você queira considerar a redução de batch_size e o aumento de worker_processes para acomodar documentos maiores em lotes menores.
  • Se você tiver muitos documentos pequenos, poderá considerar aumentar os valores worker_process e http_connections.
  • Se desejar executar a replicação com impacto mínimo, a configuração de worker_processes e http_connections como 1 poderá ser apropriada.
  • Para mais informações, consulte Consumo de Operações de Leitura e Gravação por Replicação.

Para obter mais assistência sobre a melhor configuração para o seu caso de uso, acesse o Portal de Suporte do IBM Cloud.

O desempenho da replicação pode ser melhorado, possibilitando a opção de replicação "use_bulk_get": true". Nesse caso, o replicador busca documentos da fonte em lotes em vez de individualmente.

{
  "_id": "rep_doc_id",
  "source": "https://account1.cloudant.com/db1",
  "target": "https://account2.cloudant.com/db2",
  "use_bulk_get": true
}

A taxa de replicação aumentada pode consumir a capacidade de taxa de leitura ou gravação disponível nas contas de terminais de origem e de destino.

Como remover revisões de documentos conflitantes com replicação

Uma maneira de remover revisões de documentos conflituados via replicação é ativando a opção "winning_revs_only": true. Esta opção apenas replica as revisões de documentos vencedoras. Essa é a revisão devolvida por padrão por uma solicitação GET $SERVICE_URL/$DATABASE/$DOCID. Essa opção é uma opção avançada, uma vez que descarta revisões de documentos em conflito. Use essa opção com cuidado.