Cos'è la replica?

I dati possono essere copiati da un database a un altro nello stesso account IBM® Cloudant® for IBM Cloud®, in più account e in più data center.

I dati possono anche essere sincronizzati tra un account IBM Cloudant e un dispositivo mobile utilizzando PouchDB. La replica può avvenire in una sola direzione o in entrambe le direzioni, come operazione "una tantum" o continua, e può essere regolata con precisione tramite l'uso di parametri.

Il protocollo di replica di IBM Cloudant è compatibile con una gamma di altri database e librerie il che lo rende particolarmente adatto per le applicazioni Internet of Things (IoT) e mobili.

IBM Cloudant è un archivio dati JSON distribuito con un'API HTTP. IBM Cloudant può essere eseguito come servizio su più cloud o nel tuo rack di server. I documenti vengono memorizzati nei database e possono raggiungere qualsiasi dimensione poiché IBM Cloudant frammenta i suoi dati in molti nodi. La replica è la copia dei dati da un database di origine a un database di destinazione. I database di origine e di destinazione non devono essere necessariamente nello stesso account IBM Cloudant o nello stesso data center.

Il grafico mostra un'immagine dei database a e b. Il database b ha un documento. Dopo la replica, i documenti del database a vengono visualizzati nel database b.
La replica illustrata

La replica è completa quando la versione più recente di ogni documento nell'origine viene trasferita nel database di destinazione. I trasferimenti includono i nuovi documenti, gli aggiornamenti ai documenti esistenti e le eliminazioni. Solo la versione più recente di un documento rimane dopo la replica; le versioni precedenti vengono omesse.

Il database di origine rimane inalterato dalla replica, ad eccezione dei dati del checkpoint che vengono scritti in esso per consentire la ripresa delle repliche parziali dall'ultima posizione nota. Rimane qualsiasi dato preesistente nel database di destinazione.

Come avviare la replica con il dashboard

Il dashboard IBM Cloudant fornisce una pratica interfaccia utente per attivare la replica. Fai clic su Replication sul dashboard IBM Cloudant e fai clic su Start Replication. Completare il seguente modulo di replica:

caption-side=bottom"
Questa schermata mostra il modulo di replica con tutti i campi corretti compilati. C'è una sezione di origine, che è il database locale, e una sezione di destinazione, che è il nuovo database e l'autenticazione. Nella sezione "Opzioni", è possibile scegliere tra una replica una tantum o ricorrente e aggiungere un documento di replica. Modulo di replica "

Per motivi di sicurezza, il team di IBM Cloudant consiglia di utilizzare le chiavi API IAM o le chiavi API di autenticazione legacy dell' IBM Cloudant, anziché le credenziali a livello di account, per i processi di replica. Per ulteriori informazioni, vedi la documentazione Gestione dell'accesso o dell'autenticazione legacy e autorizzazione.

Utilizzando il modulo, definisci i database di origine e di destinazione, poi fai clic su Start Replication.

È possibile visualizzare lo stato di ciascuna attività di replica cliccando su Replication. Lo stato di ogni lavoro viene modificato da Running a Completed man mano che avanza. La seguente schermata mostra lo stato Completed.

Sotto il campo "Stato" nella tabella è visualizzato "Completato".
Stato Completato""

Come replicare tra diversi account IBM Cloudant

L'origine e la destinazione di una replica sono URL di database IBM Cloudant, come mostrato nel seguente esempio.

Vedere il seguente esempio che definisce gli URL di origine e di destinazione per la replica:

{
  "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"
      }
    }
  }
}

L'origine e la destinazione non devono essere sullo stesso account. I nomi dei database di origine e di destinazione non devono corrispondere. Devi essere autorizzato ad accedere sia all'origine che alla destinazione e devi essere autorizzato a scrivere sulla destinazione.

La replica viene eseguita sull'origine o sulla destinazione?

La replica può essere avviata nell'estremità di origine o di destinazione. Questa scelta significa che puoi decidere se l'account A inserisce i dati nell'account B o se l'account B estrae i dati dall'account A. In alcuni casi, potrebbe non essere possibile eseguire la replica in alcuna configurazione, ad esempio se un account è dietro un firewall. La replica avviene tramite HTTPS, pertanto non è necessario aprire alcuna porta non standard. La decisione su quale dispositivo avvia la replica è tua.

Come influisce la replica sull'elenco delle modifiche?

Puoi ottenere un elenco delle modifiche apportate a un documento utilizzando l' endpoint _changes. Tuttavia, la natura distribuita dei database IBM Cloudant indica che la riposta fornita dal feed _changes non può essere un semplice elenco di modifiche che si sono verificate dopo una determinata data e ora.

La discussione Teorema CAP chiarisce che IBM Cloudant utilizza un modello "eventualmente coerente". Questo modello indica che è possibile ottenere risultati diversi quando si richiedono due repliche differenti di un database per un documento contemporaneamente. Ciò può verificarsi quando una copia del database è ancora in attesa di terminare la replica.

Alla fine, le copie del database completano la loro replica in modo che tutte le modifiche a un documento siano presenti in ciascuna copia.

Questo modello di "consistenza eventuale" presenta due caratteristiche che influiscono sull'elenco delle modifiche:

  1. Una modifica che influenza un documento avviene quasi certamente in tempi diversi in diverse copie del database.
  2. L'ordine in cui le modifiche influenzano i documenti può differire tra le diverse copie del database, a seconda di quando e dove è avvenuta la replica.

Una conseguenza della prima caratteristica è che, quando un utente richiede un elenco di modifiche, non ha senso richiedere un elenco delle modifiche dopo uno specifico punto nel tempo. Il motivo è che l'elenco delle modifiche potrebbe essere fornito da una copia di database diversa, che ha provocato aggiornamenti di documenti in tempi diversi. Tuttavia, è utile richiedere un elenco delle modifiche successive a una modifica specifica, che viene indicata utilizzando un identificatore di sequenza.

Un'ulteriore conseguenza della prima caratteristica è che potrebbe essere necessario "ripercorrere" le modifiche precedenti per concordare l'elenco delle modifiche. In altre parole, per ottenere un elenco delle modifiche, inizi dalla modifica più recente concordata dalle copie del database. Il punto di accordo tra le copie del database è identificato all'interno IBM Cloudant utilizzando il meccanismo checkpoint che consente la replica tra le copie del database da sincronizzare.

Infine, quando si guarda un elenco di modifiche, queste potrebbero essere presentate in un ordine diverso nelle richieste successive. L'ordine dipende dal modo in cui i documenti sono stati modificati tra diverse copie del database. In altre parole, un elenco iniziale delle modifiche potrebbe riportare le modifiche A, B e C in tale ordine. Ma un successivo elenco di modifiche potrebbe riportare le modifiche C, A e B in quest'ordine. Vengono elencate tutte le modifiche, ma in un ordine diverso. Questa differenza è dovuta al fatto che la sequenza delle modifiche ricevute durante la replica può variare tra due diverse copie del database.

Cosa significa "coerenza eventuale" per l'elenco delle modifiche?

Quando richiedi un elenco di modifiche, la risposta che ottieni potrebbe variare a seconda di quale copia del database fornisce l'elenco.

L'opzione since ottiene un elenco di modifiche dopo uno specifico identificativo della sequenza di aggiornamento. L'elenco include sempre le modifiche dopo l'aggiornamento, ma potrebbero essere incluse anche le modifiche prima dell'aggiornamento. Il motivo è che la copia del database che risponde alla richiesta di elenco deve garantire che questo elenchi le modifiche, consistenti con tutte le repliche. Per ottenere questa consistenza, la copia del database potrebbe dover iniziare l'elenco di modifiche dal punto di accordo tra tutte le copie. Questo punto viene identificato utilizzando i checkpoint.

Pertanto, un'applicazione che utilizza il feed _changes deve essere "idempotente". L'idempotenza implica che l'applicazione debba essere in grado di ricevere in modo sicuro gli stessi dati più volte, e potenzialmente in un ordine diverso nel caso di richieste ripetute.

Checkpoint

Internamente, il processo di replica scrive il suo stato nei documenti di "checkpoint" che vengono memorizzati in entrambi i database di origine e di destinazione. I checkpoint consentono di riprendere un'attività di replica da dove era stata interrotta, senza dover ricominciare da capo. La creazione del punto di controllo può essere impedita fornendo Opzione "use_checkpoints": false quando si richiede la replica. È utile lasciare attiva la funzione se la replica deve riprendere efficacemente dall'ultima posizione nota.

Autorizzazioni

L'accesso come amministratore è necessario per inserire un documento nel database _replicator. Le credenziali di accesso fornite nei parametri di origine e di destinazione non richiedono autorizzazioni di amministratore complete. È sufficiente che le credenziali eseguano le seguenti attività:

  • Scrivere i documenti all'estremità di destinazione.
  • Scrivere i documenti di checkpoint in entrambe le estremità.

IBM Cloudant ha una speciale autorizzazione utente _replicator. Questa autorizzazione consente di creare i documenti di checkpoint, ma non consente la creazione di documenti comuni in un database. In generale, crea chiavi API che abbiano:

  • accesso _reader e _replicator sul lato di origine.
  • accesso _reader e _writer sul lato di destinazione.

Le chiavi API possono essere create e configurate all'interno del dashboard IBM Cloudant in base al database.

Le chiavi API possono essere create e configurate all'interno della Dashboard di IBM Cloudant, per ogni database.
IBM Cloudant utenti e chiavi API con autorizzazioni

Possono essere create anche in modo programmatico utilizzando l'API IBM Cloudant.

Per motivi di sicurezza, il team di IBM Cloudant consiglia di utilizzare le chiavi API IAM o le chiavi API di autenticazione legacy dell' IBM Cloudant, anziché le credenziali a livello di account, per i processi di replica. Per ulteriori informazioni, vedi la documentazione Gestione dell'accesso o dell'autenticazione legacy e autorizzazione.

Replica a due vie

I dati possono essere copiati in entrambe le direzioni in un processo noto come replica a due vie o sincronizzazione. Puoi abilitare questa sincronizzazione impostando due processi di replica separati, uno prendendo i dati da A a B e l'altro prendendo i dati da B ad A. Entrambi i processi di replica funzionano in modo indipendente, con i dati spostati uniformemente in entrambe le direzioni.

Il grafico mostra i database a e b. Il database a ha quattro documenti, uno è cancellato. Il database b ha un documento. Dopo aver replicato il database a nel database b, il database b ha cinque documenti, uno è cancellato. Dopo aver replicato il database b nel database a, anche il database a contiene cinque documenti, di cui uno è barrato.
Replica bidirezionale

Discussione sulla replica continua

Finora, la discussione si è occupata solo della replica singola, che termina quando tutti i dati di origine vengono scritti nel database di destinazione. Con la replica continua, i dati fluiscono continuamente. Tutte le modifiche successive apportate al database di origine vengono trasmesse al database di destinazione in tempo reale.

La replica continua viene attivata selezionando la casella di controllo “ Make this replication continuous ” quando si definisce un’attività di replica nella dashboard di IBM Cloudant, oppure impostando il continuous flag nell'API di IBM Cloudant.

La replica a due vie può essere resa continua in una o entrambe le direzioni, impostando l'indicatore continuous.

Si veda il seguente esempio che utilizza HTTP per avviare una replica continua:

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

Per avviare una replica continua, consultare il seguente esempio:

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))

L'esempio Go precedente richiede il seguente blocco di importazione:

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

Tutti gli esempi Go richiedono l'iniziazione dell'oggetto service. Per ulteriori informazioni, vedi la sezione Autenticazione della documentazione API per degli esempi.

Si veda il seguente esempio di documento JSON che definisce una replica continua:

{
    "_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
}

Altri casi d'uso della replica

Il protocollo di replica di IBM Cloudant è compatibile con altri database e librerie per diverse applicazioni del mondo reale.

Apache CouchDB

Apache CouchDB è un database open source in grado di comunicare con IBM Cloudant, e che richiede una configurazione minima. Sono incluse le seguenti applicazioni:

  • Backup - Replica i tuoi dati da IBM Cloudant ai tuoi database su CouchDB e creare snapshot notturni dei dati a scopo di archiviazione. Invia i dati a un servizio di backup come Amazon Glacier per conservarli in modo sicuro.
  • Raccolta dati "local-first" - Salva prima i dati su un' Apache CouchDB e locale, quindi copiarlo su IBM Cloudant per l'archiviazione a lungo termine, aggregazione, e analisi.

PouchDB

PouchDB è un database open source, integrato nel browser, che consente la replica bidirezionale dei dati tra il browser e IBM Cloudant. La memorizzazione dei dati in un browser web sul lato client consente alle applicazioni web di funzionare anche senza una connessione a Internet. PouchDB può sincronizzare qualsiasi dato modificato da e verso IBM Cloudant quando è disponibile una connessione a Internet. L'impostazione della replica dal lato client richiede alcune righe di JavaScript.

Vedi il seguente esempio JavaScript che utilizza PouchDB per abilitare la replica:

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

Repliche filtrate

È utile essere in grado di rimuovere alcuni dati durante il processo di replica, quando si replica un database su un altro, come si può vedere nei seguenti esempi:

  • Rimozione di tutte le tracce dei documenti eliminati, rendendo il database di destinazione più piccolo rispetto a quello di origine.
  • Suddividere i dati in blocchi più piccoli, ad esempio memorizzando i dati relativi al Regno Unito in un database e quelli relativi agli Stati Uniti in un altro.

Funzioni di filtro della replica

La replica filtrata di IBM Cloudant consente la definizione di una funzione JavaScript che utilizza il valore restituito per determinare se ogni documento in un database deve essere filtrato o meno. Le funzioni di filtro sono memorizzate nei documenti di progettazione.

Consultare la seguente funzione di filtro di esempio per la replica di documenti non eliminati:

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

Quando viene avviato un lavoro di replica, viene specificato il nome di una funzione di filtro come combinazione del documento di progettazione in cui è memorizzata e il nome della funzione di filtro. Puoi anche specificare un valore query_params. Questo valore è un oggetto che contiene le proprietà che vengono passate alla funzione di filtro nel campo query del suo secondo argomento (req).

Si veda il seguente esempio che utilizza HTTP per avviare una replica filtrata:

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

Vedi il seguente esempio che utilizza la riga di comando per avviare una replica filtrata:

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))

L'esempio Go precedente richiede il seguente blocco di importazione:

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

Tutti gli esempi Go richiedono l'iniziazione dell'oggetto service. Per ulteriori informazioni, vedi la sezione Autenticazione della documentazione API per degli esempi.

Si veda il seguente esempio di documento JSON che definisce una replica filtrata:

{
    "_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 delle modifiche

IBM Cloudant pubblica le aggiunte, le modifiche e le eliminazioni che interessano un database attraverso un singolo feed HTTP dall' endpoint _changes. Questo feed può essere utilizzato dalla tua applicazione per attivare gli eventi. Puoi accedere al feed utilizzando HTTP o curl, come mostrato negli esempi. L'utilizzo dell'opzione feed=continuous significa che il flusso ti fornisce tutte le modifiche necessarie per ottenere la versione più recente di ogni documento presente nel database.

Per ulteriori informazioni, consulta Using the IBM Cloudant changes feed FAQ.

Si veda il seguente esempio che utilizza HTTP per interrogare il feed delle modifiche:

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

Fare riferimento al seguente esempio che utilizza la riga comandi per eseguire una query del feed delle modifiche:

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

Le modifiche vengono descritte utilizzando una riga per ogni modifica. Ciascuna modifica è composta da:

  1. Una stringa che contiene un numero di sequenza (seq).
  2. Una stringa che contiene l'ID del documento che è stato modificato.
  3. Un array di modifiche.

Per visualizzare il corpo del documento stesso, aggiungi &include_docs=true al comando curl.

Ogni modifica viene descritta utilizzando il formato mostrato nel seguente esempio (abbreviato).

Vedere il seguente feed _changes di esempio:

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

Per unire il feed delle modifiche da una posizione nota, passa un argomento since con il numero di sequenza da cui vuoi iniziare.

Si veda il seguente esempio (abbreviato) che utilizza HTTP per specificare l'opzione since e collegarsi a un feed _changes in una posizione nota:

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

Si veda il seguente esempio (abbreviato) che utilizza la riga di comando per specificare l'opzione since , al fine di unirsi a un feed _changes in una posizione nota:

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

Per riunire il feed delle modifiche dal momento corrente, imposta since=now.

Si veda il seguente esempio, che utilizza HTTP per fornire since=now e collegarsi a un feed _changes in questo preciso momento:

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

Si veda il seguente esempio, in cui si utilizza la riga di comando per specificare since=now al fine di collegarsi a un feed _changes nel momento attuale:

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

L'accesso ai dati _changes in modo programmato è semplice. Ad esempio, vedi gli esempi di SDK in IBM Cloudant API docs per seguire le modifiche con alcune righe di codice.

Il seguente elenco include alcuni casi di utilizzo di esempio:

  • Aggiunta di elementi a una coda di messaggi per attivare azioni nella tua applicazione, come l'invio di una e-mail del cliente.
  • Aggiornamento di un database in memoria per registrare i conteggi in diretta dell'attività.
  • Scrittura dei dati in un file di testo per inserire i dati in un database SQL.

Il feed delle modifiche può essere filtrato con una funzione di filtro, utilizzando una tecnica simile al filtraggi durante la replica.

Si veda il seguente esempio che utilizza HTTP per filtrare il feed delle modifiche:

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

Consultare il seguente esempio che utilizza la riga comandi per filtrare il feed delle modifiche:

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

L'ordine dei documenti nel feed _changes non è sempre lo stesso. In altre parole, le modifiche potrebbero non essere visualizzate in un rigoroso ordine di tempo. Il motivo è che i dati vengono restituiti da più nodi IBM Cloudant e si applicano le regole della consistenza eventuale.

Insidie della replica

Per eseguire correttamente la replica, la somma della dimensione del documento e di quelle di tutti gli allegati deve essere inferiore alla dimensione massima della richiesta del cluster di destinazione. Ad esempio, se la dimensione massima della richiesta HTTP è 11 MB, si applicano i seguenti scenari:

Vari scenari basati sulla dimensione massima della richiesta HTTP 11 MB
Dimensione documento Dimensione allegato Dimensione totale Repliche?
1 MB Cinque allegati da 2 MB 11 MB
1 MB Un allegato da 10 MB 11 MB
1 MB Cento allegati da 1 MB 101 MB No

Si applicano diverse considerazioni sull'utilizzo della replica.

Autorizzazioni utente non corrette

Affinché la replica proceda in modo ottimale quando replichi dal database "a" al database "b", le credenziali fornite devono avere:

  • le autorizzazioni _reader e _replicator sul database "a".
  • le autorizzazioni _writer sul database "b".

Le chiavi API vengono generate nella dashboard di IBM Cloudant o tramite l'API. A ciascuna chiave è possibile assegnare autorizzazioni individuali relative a uno specifico database di IBM Cloudant. IBM Cloudant deve essere in grado di scrivere i propri documenti di checkpoint alla fine della "lettura" della replica, altrimenti non viene salvato alcuno stato e la replica non può riprendere da dove è stata interrotta. Se lo stato non viene salvato, potrebbero verificarsi dei problemi di prestazione durante la ripresa della replica di grandi serie di dati. Il motivo è che senza checkpoint, il processo di replica riparte dall'inizio ogni volta che viene ripreso.

Il documento di replica è in conflitto

Un'altra conseguenza dell'impostazione errata delle autorizzazioni utente è che il documento _replicator va in conflitto. Il documento _replicator registra lo stato corrente del processo di replica. In casi estremi, il documento può diventare enorme perché contiene molti conflitti non risolti. Un documento così grande utilizza gran parte dello spazio disponibile e causa un carico aggiuntivo del server.

Puoi controllare la dimensione del tuo database _replicator inviando una richiesta GET all'endpoint /_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))

L'esempio Go precedente richiede il seguente blocco di importazione:

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

Tutti gli esempi Go richiedono l'iniziazione dell'oggetto service. Per ulteriori informazioni, vedi la sezione Autenticazione della documentazione API per degli esempi.

Ottieni conflitti dal documento di replica

Nel JSON restituito, cerca il valore disk_size. Se il valore indica una dimensione superiore a 1 GB, vai al portale di supportoIBM Cloud per ulteriori consigli.

Puoi controllare i conflitti di un singolo documento _replicator, come mostrato nel seguente esempio:

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))

L'esempio Go precedente richiede il seguente blocco di importazione:

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

Tutti gli esempi Go richiedono l'iniziazione dell'oggetto service. Per ulteriori informazioni, vedi la sezione Autenticazione della documentazione API per degli esempi.

Annulla tutte le repliche

Se vuoi annullare tutte le repliche e iniziare con una nuova, pulisci il database _replicator e quindi elimina e ricrea il database replicator.

Vedere il seguente HTTP per rimuovere e ricreare il database _replicator:

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

Elimina database replicatore

Consultare il seguente esempio per rimuovere il database _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))

L'esempio Go precedente richiede il seguente blocco di importazione:

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

Tutti gli esempi Go richiedono l'iniziazione dell'oggetto service. Per ulteriori informazioni, vedi la sezione Autenticazione della documentazione API per degli esempi.

Ricreare il database del replicatore

Consultare il seguente esempio per ricreare il database _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))

L'esempio Go precedente richiede il seguente blocco di importazione:

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

Tutti gli esempi Go richiedono l'iniziazione dell'oggetto service. Per ulteriori informazioni, vedi la sezione Autenticazione della documentazione API per degli esempi.

Molte repliche simultanee

È facile dimenticare di aver precedentemente impostato la replica tra due database e creare quindi ulteriori processi di replica per errore. Ogni lavoro di replica è indipendente dall'altro, pertanto IBM Cloudant non ti impedisce di creare processi di replica aggiuntivi. Tuttavia, ogni attività di replica consuma le risorse del sistema.

È possibile controllare le "repliche attive" nella dashboard di IBM Cloudant per assicurarsi che non siano in corso attività di replica indesiderate Elimina tutti i documenti _replicator che non sono più necessari.

Ottimizzazione della velocità di replica

Per impostazione predefinita, IBM Cloudant La replica avviene a una velocità adeguata per trasferire i dati dalla fonte alla destinazione senza compromettere le prestazioni. La scelta tra la frequenza di replica e le prestazioni del cluster per altre attività diventa un compromesso. Il tuo caso d'uso potrebbe richiedere una replica più rapida a scapito di altri servizi IBM Cloudant. In alternativa, potresti richiedere di dare la priorità alle prestazioni del cluster, trattando la replica come processo in background.

Sono disponibili le opzioni API di replica avanzata. Queste opzioni consentono un aumento o una diminuzione della quantità di potenza di calcolo utilizzata durante la replica, come mostrato nei seguenti esempi:

  • Se i tuoi documenti contengono allegati, potresti ridurre il valore di batch_size e aumentare il valore di worker_processes, per ospitare documenti più grandi in batch più piccoli.
  • Se hai tanti piccoli documenti, potresti aumentare i valori di worker_process e http_connections.
  • Se vuoi eseguire la replica con un impatto minimo, l'impostazione di worker_processes e http_connections su 1 potrebbe essere appropriata.
  • Per ulteriori informazioni, consultare Consumption of Read and Write Operations by Replication.

Per ulteriore assistenza sulla migliore configurazione per il tuo caso di utilizzo, vai a Portale di supporto IBM Cloud.

Le prestazioni della duplicazione possono essere migliorate abilitando l'opzione di replica "use_bulk_get": true". In tal caso, il replicatore recupera i documenti dall'origine in batch anziché singolarmente.

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

La maggiore velocità di replica potrebbe consumare la capacità di velocità di lettura o scrittura disponibile sugli account endpoint di origine e di destinazione.

Rimozione delle revisioni di documenti in conflitto con la replica

Un modo per rimuovere le revisioni dei documenti in conflitto mediante la replica è abilitare l'opzione "winning_revs_only": true. Questa opzione replica solo le revisioni del documento vincente. Questa è la revisione restituita per impostazione predefinita da una richiesta GET $SERVICE_URL/$DATABASE/$DOCID. Questa opzione è un'opzione avanzata, poiché elimina le revisioni di documenti in conflitto. Utilizza questa opzione con cautela.